首页 文章

如何在进入dll时访问堆栈上传递的参数?

提问于
浏览
1

我从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 回答

  • 2

    提供的链接相对清晰,但如果事情不明确,我会尝试编译C示例并查看程序集 . 结果是在这篇文章的最后 . 作业是:

    [RSP]           Return address
    [RSP+8]  ECX    int a     (XMM0 unused)
    [RSP+16] EDX    int b     (XMM1 unused)
    [RSP+24] XMM2   double c  (R8 unused)
    [RSP+32] R9     int d     (XMM3 unused)
    [RSP+40]        double e    
    [RSP+48]        int f
    

    前四个参数在寄存器中 . 第一个参数是R8 / XMM0,具体取决于类型 . 第二个是R9 / XMM1等 . 第五个和后面的参数(在这种情况下为[RSP 40]和[RSP 48])总是在堆栈上 . [RSP 8]到[RSP 32]的四个四字是寄存器的阴影空间 . 我在下面没有进行优化编译,因此函数立即将寄存器溢出到阴影空间 .

    希望这可以解决它 .

    C example

    int func(int a, int b, double c, int d, double e, int f)
    {
        return (int)(a+b+c+d+e+f);
    }
    
    int main()
    {
        func(1,2,1.1,4,5.5,6);
        return 0;
    }
    

    Assembly generated:

    ; Listing generated by Microsoft (R) Optimizing Compiler Version 19.00.24215.1 
    
    include listing.inc
    
    INCLUDELIB LIBCMT
    INCLUDELIB OLDNAMES
    
    PUBLIC  func
    PUBLIC  main
    PUBLIC  __real@3ff199999999999a
    PUBLIC  __real@4016000000000000
    EXTRN   _fltused:DWORD
    pdata   SEGMENT
    $pdata$main DD  imagerel $LN3
            DD      imagerel $LN3+62
            DD      imagerel $unwind$main
    pdata   ENDS
    ;       COMDAT __real@4016000000000000
    CONST   SEGMENT
    __real@4016000000000000 DQ 04016000000000000r   ; 5.5
    CONST   ENDS
    ;       COMDAT __real@3ff199999999999a
    CONST   SEGMENT
    __real@3ff199999999999a DQ 03ff199999999999ar   ; 1.1
    CONST   ENDS
    xdata   SEGMENT
    $unwind$main DD 010401H
            DD      06204H
    xdata   ENDS
    ; Function compile flags: /Odtp
    ; File c:\users\metolone\x.c
    _TEXT   SEGMENT
    main    PROC
    
    ; 7    : {
    
    $LN3:
      00000 48 83 ec 38      sub     rsp, 56                        ; 00000038H
    
    ; 8    :     func(1,2,1.1,4,5.5,6);
    
      00004 c7 44 24 28 06
            00 00 00         mov     DWORD PTR [rsp+40], 6
      0000c f2 0f 10 05 00
            00 00 00         movsd   xmm0, QWORD PTR __real@4016000000000000
      00014 f2 0f 11 44 24
            20               movsd   QWORD PTR [rsp+32], xmm0
      0001a 41 b9 04 00 00
            00               mov     r9d, 4
      00020 f2 0f 10 15 00
            00 00 00         movsd   xmm2, QWORD PTR __real@3ff199999999999a
      00028 ba 02 00 00 00   mov     edx, 2
      0002d b9 01 00 00 00   mov     ecx, 1
      00032 e8 00 00 00 00   call    func
    
    ; 9    :     return 0;
    
      00037 33 c0            xor     eax, eax
    
    ; 10   : }
    
      00039 48 83 c4 38      add     rsp, 56                        ; 00000038H
      0003d c3               ret     0
    main    ENDP
    _TEXT   ENDS
    ; Function compile flags: /Odtp
    ; File c:\users\metolone\x.c
    _TEXT   SEGMENT
    a$ = 8
    b$ = 16
    c$ = 24
    d$ = 32
    e$ = 40
    f$ = 48
    func    PROC
    
    ; 2    : {
    
      00000 44 89 4c 24 20   mov     DWORD PTR [rsp+32], r9d
      00005 f2 0f 11 54 24
            18               movsd   QWORD PTR [rsp+24], xmm2
      0000b 89 54 24 10      mov     DWORD PTR [rsp+16], edx
      0000f 89 4c 24 08      mov     DWORD PTR [rsp+8], ecx
    
    ; 3    :     return (int)(a+b+c+d+e+f);
    
      00013 8b 44 24 10      mov     eax, DWORD PTR b$[rsp]
      00017 8b 4c 24 08      mov     ecx, DWORD PTR a$[rsp]
      0001b 03 c8            add     ecx, eax
      0001d 8b c1            mov     eax, ecx
      0001f f2 0f 2a c0      cvtsi2sd xmm0, eax
      00023 f2 0f 58 44 24
            18               addsd   xmm0, QWORD PTR c$[rsp]
      00029 f2 0f 2a 4c 24
            20               cvtsi2sd xmm1, DWORD PTR d$[rsp]
      0002f f2 0f 58 c1      addsd   xmm0, xmm1
      00033 f2 0f 58 44 24
            28               addsd   xmm0, QWORD PTR e$[rsp]
      00039 f2 0f 2a 4c 24
            30               cvtsi2sd xmm1, DWORD PTR f$[rsp]
      0003f f2 0f 58 c1      addsd   xmm0, xmm1
      00043 f2 0f 2c c0      cvttsd2si eax, xmm0
    
    ; 4    : }
    
      00047 c3               ret     0
    func    ENDP
    _TEXT   ENDS
    END
    

相关问题