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

QBE生成的汇编在Windows下用MinGW编译失败的解决方法及ABI相关疑问

QBE生成的汇编在Windows下用MinGW编译失败的解决方法及ABI相关疑问

看起来你遇到了QBE生成的ELF风格汇编和Windows MinGW的COFF汇编格式不兼容的问题,还有System V ABI在Windows上的适配疑问——这很正常,毕竟WSL是Linux环境,天然适配QBE默认输出的ELF汇编,而Windows的汇编格式和调用约定都不一样,我来一步步帮你解决:


一、解决MinGW编译汇编报错的问题

你看到的.type、.size相关的错误,核心原因是QBE默认输出Linux/ELF平台专属的汇编伪指令,而Windows MinGW使用的是COFF格式的汇编标准,这些ELF特有的伪指令在COFF环境下不被识别;另外.section .note.GNU-stack是ELF用于标记栈可执行性的段,Windows平台完全不需要。

具体修复步骤:

  1. 打开QBE生成的out.s文件,删除所有ELF特有的伪指令:
    • 删掉每个函数定义后的.type 函数名, @function和.size 函数名, .-函数名行
    • 删掉末尾的.section .note.GNU-stack,"",@progbits行
  2. (可选)把.balign 8替换成MinGW更兼容的.align 8(大部分MinGW版本也支持.balign,替换更稳妥)

修改后的汇编代码示例:

.text
add:
pushq %rbp
movq %rsp, %rbp
movl %edi, %eax
addl %esi, %eax
leave
ret

/* end function add */

.text
.globl main
main:
pushq %rbp
movq %rsp, %rbp
movl $1, %esi
movl $1, %edi
callq add
movl %eax, %esi
leaq fmt(%rip), %rdi
movl $0, %eax
callq printf
movl $0, %eax
leave
ret

/* end function main */

.data
.align 8
fmt:
.ascii "One and one make %d!\n"
.byte 0

/* end data */
  1. 用MinGW GCC重新编译:
gcc -o hello.exe out.s

此时伪指令相关的报错会消失,但可能还会有运行时问题——这就涉及到你关于ABI的疑问。


二、System V ABI与MinGW CRT的适配疑问

你说的没错,QBE目前只支持System V AMD64 ABI(Linux/macOS等类Unix系统的x86_64调用约定),而Windows x64平台默认使用的是Microsoft x64调用约定,两者的参数传递规则差异很大:

  • System V ABI:前6个整数/指针参数用rdi, rsi, rdx, rcx, r8, r9传递
  • Microsoft ABI:前4个整数/指针参数用rcx, rdx, r8, r9传递

这种差异会导致QBE生成的代码调用printf时参数传递错误,程序可能崩溃或输出乱码,下面是两种可行的解决思路:

思路1:使用支持System V ABI的MinGW版本

MinGW-w64提供了两种线程模型的工具链:

  • win32模型:默认使用Microsoft x64调用约定,依赖msvcrt.dll
  • posix模型:使用System V AMD64调用约定,提供符合该ABI的CRT函数(包括printf)

如果安装的是posix模型的MinGW-w64,QBE生成的代码可以直接和CRT链接,调用约定完全匹配,不需要额外修改,编译运行都正常。

思路2:为Microsoft ABI编写包装函数(适合无法更换MinGW版本的情况)

如果你只能用win32模型的MinGW,需要编写ABI转换stub函数,把QBE生成的System V调用转换成Microsoft调用,比如针对printf的stub:

.global printf
printf:
pushq %rbp
movq %rsp, %rbp
# 把System V的参数(rdi=格式串,rsi=第一个参数)转成Microsoft的(rcx=格式串,rdx=第一个参数)
movq %rdi, %rcx
movq %rsi, %rdx
# 调用msvcrt.dll里的printf(Microsoft ABI)
call printf
movq %rax, %rax  # 传递返回值
leave
ret

把这段代码追加到out.s末尾,再用MinGW GCC编译,就能正确调用Windows的CRT函数了。

补充说明:MinGW的win32模型CRT本身不支持System V ABI,必须通过stub转换;而posix模型的MinGW已经适配了System V ABI,所以可以直接使用。


备注:内容来源于stack exchange,提问作者OetkenPurveyorOfCode

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.20 07:10:29