【发布时间】:2013-05-02 10:43:15
【问题描述】:
我知道前四个参数在寄存器中(RCX、RDX、R8、R9),并且其他参数被压入堆栈。
问题:
如何将参数压入堆栈?我尝试使用 (push 0) 但它不起作用?
代码(MASM64)
extrn ExitProcess: PROC
extrn MessageBoxExA: PROC
.data
caption db '64-bit hello!', 0
message db 'Hello World!', 0
.code
Start PROC
sub rsp, 38h
mov rcx, 0 ; hWnd = HWND_DESKTOP
lea rdx, message ; LPCSTR lpText
lea r8, caption ; LPCSTR lpCaption
mov r9d, 0 ; uType = MB_OK
push 0 ; wLanguageId
call MessageBoxExA
mov ecx, eax
add rsp, 38h
call ExitProcess
Start ENDP
End
我知道MessageBox 和MessageBoxEx 的工作方式相同,但我尝试使用MessageBoxEx,因为它需要传递一个参数(用于学习目的)。
我知道我问过类似的问题,但它与 vb.net 更相关,而这不是。
【问题讨论】:
-
我认为你从 rsp 中减去了太多。请改用
sub rsp, 20h。原因是调用者需要在堆栈上为 4 个寄存器 (rcx,rdx,r8,r9) 分配“寄存器主(或溢出)空间”,即 4 * 8 = 0n32 = 0x20。第 5 个(以及随后的 args)出现在这个空间之后,所以这就是为什么我建议从 rsp 中减去 0x20 字节而不是 0x38。 -
Windows ABI 不允许堆栈指针在函数执行期间更改(至少在不做额外工作的情况下不会更改),并且您要更改它两次(一次是推送,一次是外部添加结语),您的函数缺少正确的序言声明,并且您将第五个参数放在堆栈中的错误位置。我认为最简单的解决方案是只用 C 编写程序,然后查看编译器生成的内容。
-
你需要小心所谓的影子空间。我在一个简单的 Windows 应用程序中实现了两个子例程。一个用于 MessageBoxA,另一个用于 ShellAboutA.(对话框)。虽然我到处读到两者都需要 20 小时的阴影空间,但 MessageBox 需要 28 小时的阴影空间。看起来很正常,因为 rcx、rdx、r8 和 r9 的 4x8 字节加上堆栈上调用者的额外返回地址。我对 ShellAbout 使用了相同的逻辑。返回地址也是 4 x 8 + 8,应用程序的那部分崩溃。它只需要 4 x 8 字节的影子空间。多也少是好的。
标签: windows assembly x86-64 masm