无法访问传递给NASM 64位DLL的数组指针

时间:2018-01-05 22:34:05

标签: python assembly dll nasm ctypes

我将两个数组从Python程序(使用ctypes)传递给NASM 64位DLL。在Windows调用约定中,指针在rcx和rdx中传递。这两个数组都是Int64。数组是用Python创建的,并以这种方式传递给DLL:

PassArrayType = ctypes.c_int64 * 10
PVarrNew = PassArrayType()
OutputArrayType = ctypes.c_int64 * 1000
arrNew = OutputArrayType()
retvar = SimpleTest(ctypes.byref(PVarrNew), ctypes.byref(arrNew))

在DLL中,我可以从rcx中的数组指针读取,但我无法写入数组。

例如,从rcx指向的数组中读取值可以起作用:

push qword [rcx+32]
pop qword [tempvar]

但是将值写入rcx指向的数组不起作用:

mov rax,1235
push rax
pop qword [rcx+32]

将相同的值写入变量时:

mov rax,1235
push rax
pop qword [tempvar]

我无法读取或写入rdx指向的数组。

所以我的问题是:

  1. 为什么我可以从rcx指向的数组中读取但不能写入它?
  2. 为什么我不能读取或写入rdx指向的数组?
  3. 迈克尔,谢谢你的回复。我误解了minimal只意味着有问题的代码行。我对Stack Overflow相当新,但现在我知道要发布多少代码。这里是完整的Python代码和完整的NASM代码。 Python是3.6.2。 NASM是64位的。

    Python代码:

    OutputArrayType = ctypes.c_int64 * 1000
    arrNew = OutputArrayType()
    
    PassArrayType = ctypes.c_int64 * 10
    PVarrNew = PassArrayType()
    PVarrNew[0] = id(PVarrNew)
    PVarrNew[1] = 2
    PVarrNew[2] = len(PVarrNew)
    
    ThisDll = ctypes.WinDLL(r"C:/Temp2/Std_Math_Formulas.dll")
    SimpleTest = ThisDll.SimpleTest
    SimpleTest.argtypes = [ctypes.c_void_p, ctypes.c_void_p]
    SimpleTest.restype = ctypes.c_int64
    
    retvar = SimpleTest(ctypes.byref(PVarrNew), ctypes.byref(arrNew))
    

    NASM代码:

    ; Header Section
    [BITS 64]
    
    export SimpleTest
    section .data
    tempvar:  dq 0
    
    section .text
    finit
    
    SimpleTest:
    
    push rdi
    push rbp
    
    mov rdi,rcx
    mov rbp,rdx
    
    push qword [rcx+32]
    pop qword [tempvar]
    
    ; this works with rcx, but not rdx
    mov rdi,rcx
    push qword [rdi+32]
    pop qword [tempvar]
    
    ; this works with rcx, but not rdx
    mov rax,1235
    push rax
    pop qword [rcx+32]
    
    mov rax,[tempvar]
    
    pop rbp
    pop rdi
    ret
    

    我汇编并链接我的DLL:

    nasm -Z myfile.err -f Win64 C:\Temp2\Std_Math_Formulas.asm -l myfile.lst -F cv8 -g -o C:\Temp2\Std_Math_Formulas.obj 
    GoLink Std_Math_Formulas.obj /dll /entry SimpleTest msvcrt.dll 
    

1 个答案:

答案 0 :(得分:2)

Michael Petch上面提出的解决方案解决了这个问题。我从GoLink链接器命令字符串中删除了“/ entry SimpleTest”,就像迈克尔提出的那样,现在我可以从rcx和rdx指向的数组中读取和写入。正确的命令字符串是:

GoLink Std_Math_Formulas.obj /dll msvcrt.dll

非常感谢你的解决方案;我非常感谢你的帮助。