就x86汇编代码而言,当我们调用函数时,需要使用基准/帧指针(EBP)和堆栈指针(ESP)。当前的EBP值将被放置在堆栈上,然后EBP获得当前ESP值。接下来,函数的返回值、函数参数和本地变量的占位符将被放置在堆栈上,并且堆栈指针ESP的值将减少(或增加),以指向堆栈上放置的最后一个占位符之后。现在,EBP指向当前堆栈帧的开头,ESP指向堆栈帧的结尾。
由于与EBP的恒定偏移量,EBP将用于访问函数的参数和本地变量。这非常好理解。我不理解的是,为什么不能使用ESP通过其偏移量来访问这些变量。EBP指向堆栈帧的开头,ESP指向堆栈帧的结尾。有什么区别吗?
一旦所有本地变量等的占位符已经存在,ESP就不应该再发生改变了,对吗?
由于与EBP的恒定偏移量,EBP将用于访问函数的参数和本地变量。这非常好理解。我不理解的是,为什么不能使用ESP通过其偏移量来访问这些变量。EBP指向堆栈帧的开头,ESP指向堆栈帧的结尾。有什么区别吗?
一旦所有本地变量等的占位符已经存在,ESP就不应该再发生改变了,对吗?
push
来传递函数参数。但是,使用-Oz
(即使牺牲速度也要优化代码大小)的clang将使用像push 2
/pop rcx
(总共3个字节)这样的东西,而不是5个字节的mov ecx, 2
。然而,使用push/pop代替mov reg,reg
是疯狂的。它只为64位寄存器(不是r8..r15)节省1个字节,否则它是平衡或者是损失。(3个字节的mov r8, r9
与2个字节的push r9
+ 2个字节的pop r8
相比)。在32位代码中,2个字节的mov
始终比push
/pop
更快,并且在大小上保持平衡。 - Peter Cordes