assembly - X.86 X64 汇编器中的正确堆栈操作
问题描述
因此,在阅读了 x64 架构快速入门指南后,我编写了一些汇编程序。
https://software.intel.com/en-us/articles/introduction-to-x64-assembly
汇编器函数是从 C 调用的。反过来,汇编器调用 C 函数。
我不确定堆栈机制是如何工作的,因为我似乎多次破坏堆栈。
以下代码演示:
PUBLIC Lbra_R_A ; Op 16 - Long Branch Always
Lbra_R_A PROC
sub rsp, 28h
push rbx ; must preserve rbx
; Calc destination branch address by Adding the two Bytes at [PC+1] (high byte) and [PC+2] (low byte) with PC+2 reg
; Get first byte high byte
movzx rcx, word ptr [pc_s]
mov rbx, rcx ; save pc_s into temp
inc bx ; inc temp pc_s
call MemRead8_s ; returns byte in ax (al)
push ax ; save high byte
; Get second byte low byte @ pc_s
mov rcx, rbx
inc bx ; inc temp pc_s
call MemRead8_s ; returns byte in ax (al) - this call destroys saved high byte???
; combine low and high bytes to make 16 bit 2 complements offset
pop dx ; get saved high byte - wrong value
mov ah, dl ; move the high byte to high position ; ax now contains 16 bit offset
add bx, ax ; bx now contains pc_s(+2) + offset
mov word ptr [pc_s], bx
pop rbx ; must restore rbx - wrong value???
add rsp, 28h
ret
Lbra_R_A ENDP
我用 sub rsp, 28h 设置了堆栈,但我不知道为什么,我不知道我可以在那个 28h 字节区域做什么!!!是给我的还是保留的。但是没有这个我的代码甚至不能运行!!!
接下来我保留 rbx 寄存器,因为它被认为是非易失性的。但是最后当我恢复 rbx 时它和我保存的不一样???
中间代码我在调用名为 MemRead8_s(由我提供)的 C 函数之前保存/推送 ax 寄存器。但是,当我调用该函数时,现在存储在堆栈中的 ax 的值被覆盖了,所以当我稍后尝试恢复它的几条指令时,它是错误的!!!这个调用之前和之后的 rsp 值似乎是一样的,那么调用这个函数对堆栈做了什么?
谁能阐明正确的堆栈设置协议是什么,并可能解释为什么我的堆栈保存被破坏了?
解决方案
您的函数拥有低于 RSP 初始值(在函数入口处)和高于 RSP 当前值的堆栈空间。
在 Windows 上,您的函数还拥有高于返回地址的 32 个字节(影子空间)。确保在调用另一个函数之前保留此空间,除非它是不使用影子空间的私有辅助函数。
在 Linux 和其他非 Windows 上,x86-64 System V ABI 表示您的函数拥有低于当前 RSP(红色区域)的 128 个字节。显然push
,函数调用会踩到那个空间,所以它在叶函数中最有用,以避免 RSP 的子/添加。但它不会被信号处理程序破坏。
因此sub rsp, 28h
分配 0x28 字节的堆栈空间(并将堆栈对齐 16 字节,因为在调用者推送返回地址之前它是 16 字节对齐call
的。(您使用 16 位(2 字节)推送打破了对齐,这不好)。 ret
基本上是pop rip
,这就是为什么您必须在运行之前将堆栈恢复到其原始值的原因ret
。
不要使用 16 位推送/弹出;保存/恢复完整的 64 位寄存器。MemRead8_s
允许假设 RSP 在为其推送返回地址的调用之前是 16 字节对齐的,你很幸运它碰巧不依赖堆栈对齐。)
推荐阅读
- ios - 如何在 UITableView (Swift 5) 中隐藏特定单元格的 UIElements?
- python - 对 tf.estimator.Estimator 中的参数感到困惑
- python - 卷积神经网络期望 X 但得到 Y
- sql - TSQL - 计算从昨天到今天的值之间的差异,SELF JOIN 问题
- sharepoint - SharePoint online 跨站点查找值
- java - Spring数据JPA是否有任何注释不返回JSON中的整个实体?(休息 API (SQL))
- javascript - 将网站发出的所有 JSON 请求重定向到另一个 URL
- rest - 内容类型应用程序/八位字节流或更具体的东西?
- angular - 我如何在 PayPal javascript sdk 中恢复/停止交易
- visual-studio - 以管理员身份运行时,Ctrl-C 在 Visual Studio 2019 中不起作用