NASM汇编代码转.obj后用GCC生成.exe遇WinMain未定义错误
问题解决方法
核心问题分析
- 你的汇编代码是Linux x86_64平台的系统调用实现,但你在Windows环境下使用MinGW-GCC编译,Windows的系统调用机制与Linux完全不同,
mov rax,1(对应Linux的write调用)、mov rax,60(对应Linux的exit调用)都是Linux专属的系统调用号,Windows无法识别。 - MinGW-GCC默认会链接C运行时库(CRT),CRT会自动寻找
WinMain或main作为程序入口,而你的代码入口是_start,因此触发链接错误。
解决方案
方案1:修改代码适配Windows平台
Windows控制台程序需要调用Windows API实现输入输出和退出逻辑,而非直接使用Linux风格的syscall。以下是适配Windows x64的Hello World汇编代码:
section .data hello db 'Hello, World!', 0Dh, 0Ah ; 追加回车换行符 hello_len equ $ - hello section .text global main extern GetStdHandle, WriteConsoleA, ExitProcess main: ; 获取标准输出句柄 mov rcx, -11 ; 对应STD_OUTPUT_HANDLE常量 call GetStdHandle ; 写入字符串到控制台 mov rcx, rax ; 传入输出句柄 mov rdx, hello ; 传入字符串地址 mov r8, hello_len ; 传入字符串长度 sub rsp, 8 ; 栈对齐(Windows x64调用约定要求栈保持16字节对齐) mov r9, rsp ; 传入接收实际写入字节数的指针 call WriteConsoleA add rsp, 8 ; 退出程序 mov rcx, 0 ; 传入退出码0 call ExitProcess
编译链接命令:
nasm -f win64 hello.asm -o hello.obj gcc hello.obj -o hello.exe
方案2:直接用ld链接,跳过CRT
若仅想解决链接错误(注意:生成的程序在Windows下无法正常运行,因为Linux syscall在Windows中无效),可使用MinGW的ld直接链接,指定入口为_start并跳过CRT:
nasm -f win64 hello.asm -o hello.obj ld hello.obj -o hello.exe --entry=_start -lkernel32
方案3:使用WSL编译运行Linux程序
如果你的目标是编写Linux平台的汇编代码,建议使用Windows Subsystem for Linux(WSL):
- 启用WSL并安装Linux发行版(如Ubuntu)
- 在WSL终端中执行编译运行命令:
nasm -f elf64 hello.asm -o hello.o ld hello.o -o hello ./hello
额外说明
- gdb是调试工具,并非编译链接工具,因此不识别
-o参数。需先通过gcc/ld生成exe后,再用gdb hello.exe启动调试。 - MinGW的g++与gcc行为一致,默认都会链接CRT,因此报相同错误属于正常现象。
内容的提问来源于stack exchange,提问作者Θάνος Δριβάκος
相关产品推荐
相关产品推荐

