我知道前四个参数在寄存器中(RCX
,RDX
,R8
,R9
),并且其他参数被压入堆栈。
如何将参数推入堆栈?我试过(按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有关,而事实并非如此。
答案 0 :(得分:0)
我的程序集有点生疏,但我的印象是所有参数都进入堆栈(按相反的顺序) - 我原以为你想要推送r8和rdx以及其他参数。坦率地说,尽管你可能只是为每个指针参数继续lea rax, param
和push rax
。
答案 1 :(得分:0)
传递参数的顺序以及它们是在寄存器中还是在堆栈中传递(以及调用者或被调用者是否负责清理)由“呼叫约定”定义。
您可能正在考虑的是STDCALL或CDECL,两者都是在32位Windows中使用的调用约定,它以相反的顺序(从右到左)传递堆栈中的参数。 x64已经转移到FastCall调用约定,其中参数以正向顺序(从左到右)传递,前4个参数在寄存器RCX,RDX,R8和&中传递。 R9。超过4的任何参数都以相同的从左到右的顺序传递到堆栈上。原始海报具有使用MASM进行x64汇编的正确调用约定设置。另外,上述响应者表示从RSP中减去的阴影空间应该是20h(32d)是正确的。阴影空间允许堆栈中的空间用于由FastCall中的寄存器传入的4个参数。
将上面的代码更改为:
extrn ExitProcess: PROC
extrn MessageBoxExA: PROC
.data
caption db '64-bit hello!', 0
message db 'Hello World!', 0
.code
Start PROC
sub rsp, 20h
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, 20h
call ExitProcess
Start ENDP
End
在64位计算机上的Visual Studio中运行良好