push rbp
mov rbp, rsp
mov dword ptr [rbp - 4], edi
mov edi, dword ptr [rbp - 4]
add edi, 1
mov eax, edi
pop rbp
ret
您好!我正在学习集会,我无法理解两件事:
答案 0 :(得分:1)
对于这两个问题,答案是编译器优化:
原则上,有三种方法可以优化编译:
(通常你不会将方法3称为“优化”。)
默认情况下,C编译器执行第三种方法:始终使用相同的“默认”元素(例如,在函数开头的“push ebp”)始终工作,所以编译器总是执行相同的步骤。这使编译过程更容易。
有关问题1的详细信息:
对于16位软件,使用bp
寄存器几乎是不可避免的,因为没有指令(当然push
和pop
除外)能够访问16位代码中sp
寄存器的内存。
在64位代码中,您始终可以使用[rsp - 4]
代替[rbp - 4]
,但在alloca()
指令的情况下,这将不再可能。
为了节省时间(使用优化类型3时),编译器会在之前将push rbp
和mov rbp, rsp
指令写入文件,它知道是否存在{{1是否指示。
有关问题2的详细信息:
当使用优化方法1或2时,编译器(我尝试使用Linux下的GNU编译器)将生成如下代码:
alloca()
但是要这样做,编译器必须“记住”哪个寄存器当前包含哪个值。编译时会花费时间......
因此,当使用“优化”方法3时,编译器将执行什么是默认,始终在任何情况下都可以工作:
将所有参数写入堆栈并从堆栈中读取所有局部变量(包括参数)......
另外,不应该是
lea eax, [rbp + 1] ret
而不是mov rbp-4, [edi]
?
方括号表示:使用内存位置而不是值。
没有方括号表示不使用内存。
所以[rbp-4], edi
表示:将mov [rbp-4], edi
的值写入地址edi
的内存位置。
真正的x86-64 CPU不支持此指令,但我们可以在某些模拟器中运行指令rbp-4
。该指令会将值mov [edi], rbp-4
写入地址rbp-4
的内存位置。
然而,指令edi
意味着:“从地址mov rbp-4, [edi]
的内存位置读取值......”(这是可能的)“......并将该值写入{ {1}}“(不:”到地址edi
的内存中“)。
CPU必须在一条指令中解决方程式......