我从ctypes调用NASM 64位DLL . dll需要五个输入参数 . 在Windows调用约定中,前四个在rcx,rdx,r8和r9中传递,第五个在堆栈上传递 .
x64调用约定概述doc(https://docs.microsoft.com/en-us/cpp/build/overview-of-x64-calling-conventions)说"Any parameters beyond the first four must be stored on the stack, above the shadow store for the first four, prior to the call."所以因此值不能't be accessed with a pop, and I think it should be accessed with RSP. If the fifth (and later) parameters are above the shadow store, then I guessed it would be RSP minus 40 (mov rax,[rsp-40]), but it' .
我试过“走堆栈”,这意味着我尝试了rsp-0,rsp-8,rsp-16等,一直到rsp-56,但它没有返回我作为第五个参数传递的值(单个64位双) .
根据https://docs.microsoft.com/en-us/cpp/build/stack-allocation,条目上的堆栈布局是返回地址,rcx,rdx,r8,r9和堆栈参数区域,所以我希望在rsp-48找到我的值,但它不存在,也不是在rsp -56 .
所以我的问题是:在Windows调用约定中,如何在进入dll时访问堆栈上传递的参数?
编辑:这是相关的ctypes代码:
hDLL = ctypes.WinDLL("C:/Test_Projects/MultiCompare/py_descent.dll")
CallName = hDLL.Main_Entry_fn
CallName.argtypes = [ctypes.POINTER(ctypes.c_double),ctypes.POINTER (ctypes.c_double),ctypes.c_double,ctypes.POINTER(ctypes.c_double),ctypes.c_double]
CallName.restype = ctypes.c_double
ret_ptr = CallName(CA_x,CA_d,CA_mu,length_array_out,CA_N_epochs)
Data types:
CA_x: pointer to double(float) array
CA_d: pointer to double(float) array
CA_mu: double
length_array_out: pointer to double(float) array
CA_N_epochs: double
这是检索变量的dll入口点 . 我总是在输入时推送rdi和rbp,所以在我这样做之前先将参数传递给堆栈,以防止堆栈错位:
Main_Entry_fn:
; First the stack parameters
movsd xmm0,[rsp+40]
movsd [N_epochs],xmm0
; End stack section
push rdi
push rbp
mov [x_ptr],rcx
mov [d_ptr],rdx
movsd [mu],xmm2
mov [data_master_ptr],r9
; Now assign lengths
; (this part intentionally omitted for brevity)
call py_descent_fn
exit_label_for_Main_Entry_fn:
pop rbp
pop rdi
ret
1 回答
提供的链接相对清晰,但如果事情不明确,我会尝试编译C示例并查看程序集 . 结果是在这篇文章的最后 . 作业是:
前四个参数在寄存器中 . 第一个参数是R8 / XMM0,具体取决于类型 . 第二个是R9 / XMM1等 . 第五个和后面的参数(在这种情况下为[RSP 40]和[RSP 48])总是在堆栈上 . [RSP 8]到[RSP 32]的四个四字是寄存器的阴影空间 . 我在下面没有进行优化编译,因此函数立即将寄存器溢出到阴影空间 .
希望这可以解决它 .
C example
Assembly generated: