You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

64位NASM DLL通过ctypes调用返回值触发访问违例问题求助

解决64位NASM DLL通过ctypes调用时的访问违例问题

你的问题核心是NASM编写的DLL函数存在关键指令缺失和代码位置错误,导致CPU执行流混乱,触发访问违例。下面是具体的修复方案和原因分析:

核心问题拆解

  1. 缺少函数返回指令ret:你的lcm函数执行完寄存器操作后没有ret指令,CPU会继续执行内存中后续的随机代码,最终试图写入非法内存地址——这就是你看到access violation writing错误的根本原因,不管怎么设置rax的返回值,没有ret就无法正确回到Python调用点。
  2. finit指令位置错误:finit是初始化浮点运算单元的指令,你把它放在了section .text的全局区域(函数外部),这会在DLL加载时就执行,不仅完全没必要(你的函数没用到浮点操作),还可能引发未知的初始化问题。
  3. 冗余的内存访问(可选优化):你通过.data段的return_val变量赋值rax,其实可以直接用mov rax, 2346完成返回值设置,不需要额外的内存读写。

修复后的NASM代码

[BITS 64]
export lcm
section .text

lcm:
    ; Windows x64调用约定中,rdi是非易失性寄存器,需要保存(你已经做了这一步)
    push rdi
    push rbp

    ; 直接设置返回值到rax(64位Windows下返回值存在rax中)
    mov rax, 2346

    ; 恢复保存的寄存器
    pop rbp
    pop rdi

    ; 关键:函数返回指令,回到调用者
    ret

优化后的Python代码

你的Python代码基本没问题,加上错误捕获会更健壮:

import ctypes

def lcm_ctypes():
    input_value = ctypes.c_int64(235)
    try:
        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)
        print(f"返回值:{retvar}")
        return retvar
    except Exception as e:
        print(f"调用出错:{e}")

if __name__ == "__main__":
    lcm_ctypes()

补充:Windows x64调用约定要点

  • 64位Windows下只有一种调用约定:前4个整数参数依次放在rcx、rdx、r8、r9中,你的函数只有一个参数,会被传入rcx,如果需要使用这个参数,可以直接读取rcx的值。
  • 非易失性寄存器(rbp、rbx、rdi、rsi、r12-r15)需要在函数中保存并恢复,你已经正确保存了rdi和rbp,这部分没问题。
  • 返回值如果是64位整数,必须放在rax寄存器中,修复后的代码已经满足这个要求。

内容的提问来源于stack exchange,提问作者RTC222

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 04:46:54