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

如何为MinGW-w64编译的裸汇编函数实现自定义SEH?

纯汇编函数在MinGW-w64下实现自定义SEH的实用技巧

1. 用C函数做异常感知的包装层(最省心的方案)

你之前尝试用C调用汇编没成功,大概率是调用约定或栈帧没对齐的问题。按下面的步骤来:

  • 写一个普通C函数,在里面用__try/__except或者注册向量异常处理器(AddVectoredExceptionHandler),然后在C函数内部调用你的汇编函数。
  • 汇编函数必须严格遵循MinGW默认的cdecl调用约定:
    • 调用者负责清理栈
    • 保存非易失性寄存器(rbp, rbx, rsi, rdi, r12-r15)
    • 栈要保持16字节对齐(调用函数前,rsp必须是16的倍数)
  • 示例结构:
    #include <windows.h>
    #include <excpt.h>
    
    // 声明汇编函数
    extern void my_asm_func(void);
    
    int main() {
        __try {
            my_asm_func();
        } __except(GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ? EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) {
            // 处理异常
        }
        return 0;
    }
    
    汇编里要保证栈对齐,比如开头:
    global my_asm_func
    my_asm_func:
        push rbp
        mov rbp, rsp
        sub rsp, 16  ; 保证栈16字节对齐(如果有局部变量的话)
        ; 你的汇编代码
        mov rsp, rbp
        pop rbp
        ret
    

2. 手动给汇编函数添加MinGW兼容的Unwind元数据

如果不想用C包装,直接给汇编加 unwind 信息,让系统能识别栈帧。MinGW用的是DWARF unwind格式,用.cfi_*伪指令:

global my_asm_func
my_asm_func:
    .cfi_startproc
    push rbp
    .cfi_def_cfa_offset 16
    .cfi_offset rbp, -16
    mov rbp, rsp
    .cfi_def_cfa_register rbp
    ; 你的汇编代码
    mov rsp, rbp
    pop rbp
    .cfi_def_cfa rsp, 8
    ret
    .cfi_endproc

这些伪指令告诉编译器栈帧的变化,异常处理时能正确展开栈,这样你注册的向量异常处理器就能捕获汇编函数里的异常。

3. 用setjmp/longjmp实现轻量级异常捕获

如果不需要系统级SEH的展开能力,用setjmp/longjmp更简单:

  • 在调用汇编函数前用setjmp保存上下文
  • 汇编函数里如果检测到异常(比如触发了访问错误,或者自己判断的错误),调用longjmp跳回处理点
  • 示例:
    #include <setjmp.h>
    
    jmp_buf env;
    extern void my_asm_func(void);
    
    int main() {
        if (setjmp(env) == 0) {
            my_asm_func();
        } else {
            // 处理异常
        }
        return 0;
    }
    
    汇编里调用longjmp的方式(注意参数传递,cdecl下第一个参数在rcx):
    global my_asm_func
    extern longjmp
    my_asm_func:
        ; 假设这里触发了异常,跳回env
        mov rcx, env
        mov rdx, 1
        call longjmp
        ret
    

注意事项

  • 用AddVectoredExceptionHandler时,要在处理器函数里判断异常来源是否是你的汇编函数,可以通过CONTEXT里的rip寄存器范围来确认。
  • 汇编里的栈操作必须严格对齐,否则不仅异常处理会出问题,还可能触发CPU错误。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.14 01:50:02