x64 mov 而不是推送序列
x64 mov instead of push sequence
所以在反转 x64 二进制文件后,我在函数的开头找到了这个序列:
mov [rsp+8], rbx
mov [rsp+0x10], rbp
mov [rsp+0x18], rsi
push rdi
现在我从来没有在汇编中真正做到这一点(我只在 x86 中有过经验)。对我来说,这只是一个局部变量初始化。
知道为什么会有函数序言这样的代码吗?
似乎使用 (32 bytes above the return address) for saving some of the call-preserved registers 是合理的,而不是使用更多堆栈 space 来推送它们。如果没有它,您只需推送您想要使用的任何呼叫保留寄存器(这样您就可以稍后恢复它们)。在这里,我猜他们是通过在 ret
之前用 mov
重新加载它们来恢复的,而不是 pop
.
(在 Windows x64 中,RDI 和 RSI 是调用保留寄存器,这与 x86-64 System V 不同,它们是调用破坏的 arg 传递寄存器。)
特别是如果它通过允许奇数次的总推送使堆栈对齐很好地工作,如果没有 sub rsp, n
来保留更多堆栈 space。 (这大概就是为什么它推送 RDI 而不是将其保存到 [rsp + 0x20]
。)
所以在反转 x64 二进制文件后,我在函数的开头找到了这个序列:
mov [rsp+8], rbx
mov [rsp+0x10], rbp
mov [rsp+0x18], rsi
push rdi
现在我从来没有在汇编中真正做到这一点(我只在 x86 中有过经验)。对我来说,这只是一个局部变量初始化。
知道为什么会有函数序言这样的代码吗?
似乎使用 ret
之前用 mov
重新加载它们来恢复的,而不是 pop
.
(在 Windows x64 中,RDI 和 RSI 是调用保留寄存器,这与 x86-64 System V 不同,它们是调用破坏的 arg 传递寄存器。)
特别是如果它通过允许奇数次的总推送使堆栈对齐很好地工作,如果没有 sub rsp, n
来保留更多堆栈 space。 (这大概就是为什么它推送 RDI 而不是将其保存到 [rsp + 0x20]
。)