代码之家  ›  专栏  ›  技术社区  ›  RTC222

CTypes返回值错误

  •  1
  • RTC222  · 技术社区  · 7 年前

    我正在测试一个从ctypes调用的非常简单的NASM dll(64位)。我传递一个int\u 64,该函数将返回一个不同的int\u 64。

    每次我都会遇到同样的错误:

    OSError: exception: access violation writing 0x000000000000092A
    

    其中,十六进制值转换为我返回的值(在本例中为2346)。如果我更改该值,十六进制值将更改为该值,因此问题在于我在rax中返回的值。如果我分配mov-rax,2346,我会得到同样的错误。

    我已经反复测试了这个,尝试了不同的事情,我做了很多研究,但这个看似简单的问题仍然没有解决。

    下面是Python代码:

    def lcm_ctypes():
    
        input_value = ctypes.c_int64(235)
    
         hDLL = ctypes.WinDLL(r"C:/NASM_Test_Projects/While_Loop_01/While_loops-01.dll")
    
        CallTest = hDLL.lcm
        CallTest.argtypes = [ctypes.c_int64]
        CallTest.restype = ctypes.c_int64
    
        retvar = CallTest (input_value)
    

    以下是NASM代码:

    [BITS 64]
    
    export lcm
    
    section .data
    return_val: dq 2346
    
    section .text
    finit
    
    lcm:
    push rdi
    push rbp
    mov rax,qword[return_val]
    pop rbp
    pop rdi
    

    感谢您提供帮助解决此问题的任何信息。

    1 回复  |  直到 7 年前
        1
  •  1
  •   Peter Cordes    7 年前

    您的函数正确加载 2346 ( 0x92a )进入RAX。 然后执行继续到下面的一些字节,因为您没有 jmp ret .

    在这种情况下,我们可以推断以下字节可能是 00 00 ,解码为 add byte [rax], al ,因此 access violation writing 0x000000000000092A 错误消息。(也就是说,它抱怨的地址是你的常量,这不是巧合)。

    正如迈克尔·佩奇所说,使用调试器可以发现问题。

    您也不需要保存/恢复 rdi 因为你没有碰它。Windows x86-64调用约定有许多调用中断寄存器,因此对于最不常见的多功能,您不需要保存/恢复任何内容,只需使用rax、rcx、rdx、r8、r9以及Windows允许您中断的任何其他内容(我忘了,请查看 x86 tag wiki ,尤其是Agner Fog的指南)。


    你绝对应该使用 default rel 在文件的顶部 [return_val] 加载将使用RIP相对寻址模式,而不是绝对寻址模式。


    而且 finit 从不执行,因为 之前 您的函数标签。 但你也不需要它。你也一样 菲尼特 在您之前的asm问题中: Passing arrays to NASM DLL, pointer value gets reset to zero ,也不需要也不执行。调用约定要求在函数输入(和返回)时,x87 FPU已经处于 菲尼特 或多或少地把它放进去。所以在执行x87指令之前不需要它,比如 fmulp fidivr . 但无论如何,您并没有这样做,您使用的是SSE FP指令(建议使用,尤其是在64位模式下),它根本不涉及x87状态。

    去读一本好的教程和一些文档(x86标记wiki中的一些链接),这样您就可以很好地理解正在发生的事情,从而可以自己调试这样的问题,否则您将很难编写更复杂的内容。对于asm来说,猜测什么可能有用并不太好。

    从已删除的非答案: https://www.cs.uaf.edu/2017/fall/cs301/reference/nasm_vs/ 演示如何设置Visual Studio以使用C++和NASM源代码构建可执行文件,以便进行调试。