Assembly 为什么功能结束时需要mov rbp和rsp

Assembly 为什么功能结束时需要mov rbp和rsp,assembly,x86,Assembly,X86,我理解函数序言: push %rbp mov %rsp, %rbp 例如,如果我们想使用rbp作为本地函数stackframe的参考点,那么我们需要: 将rbp设置为堆栈指针的当前位置 恢复末尾的rbp值,因为rsp、rbp已被调用方保存 由此,我开始: push %rbp # save this onto the stack so we can restore it back at the end mov %rsp, %rbp # now we can use rbp

我理解函数序言:

push %rbp
mov %rsp, %rbp
例如,如果我们想使用
rbp
作为本地函数stackframe的参考点,那么我们需要:

  • rbp
    设置为堆栈指针的当前位置
  • 恢复末尾的
    rbp
    值,因为rsp、rbp已被调用方保存
由此,我开始:

push %rbp        # save this onto the stack so we can restore it back at the end
mov %rsp, %rbp    # now we can use rbp as our 'local stack'

...

pop %rbp        # restore the rbp value

但是,为什么结尾处有必要添加mov%rbp,%rsp?通常情况下,它似乎已经与
rbp
具有相同的值。或者,仅当我执行额外的
推送
弹出
,或
添加/订阅%rsp
,这才有必要吗?

查看实际使用堆栈空间进行局部搜索的函数。在
mov%rsp,%rbp
之后将立即出现
sub$NNN、%rsp
,最后的
mov%rsp、%rbp
将有效地撤消该操作,以将堆栈放回原来的位置。在这种情况下,一个简单的
添加$NNN,%rsp
也就足够了,但是一个更复杂的函数可能会通过非恒定量(例如,对于VLA或
alloca
)多次调整堆栈,在这种情况下,跟踪它们将是一件痛苦的事情all@NateEldredge哦,我明白了,所以只有在修改内部堆栈框架时才需要它,是吗?是的,这就是为什么GCC实际上会在除了通过push RSP之外不会改变的函数中省略它(只使用
pop%rbp
)。
leave
指令与
mov RSP,rbp;弹出rbp
。以便恢复rbp,以便被调用函数继续使用。