Windows11下NASM编译x86汇编生成exe遇WinMain@16未定义错误求助
问题排查:Windows下汇编Hello World链接报错WinMain@16未定义
问题描述
你编写的x86汇编代码如下:
section .data msg db 'Hello World', 0x0A msg_len equ $ - msg section .text global _start _start: mov eax, 4 mov ebx, 1 mov ecx, msg mov edx, msg_len int 0x80 mov eax, 1 xor ebx, ebx int 0x80
使用命令nasm -fwin32 hello_world.asm编译为.obj文件后,执行gcc hello_world.obj链接时出现错误:
c:/mingw/bin/../lib/gcc/mingw32/6.3.0/../../../libmingw32.a(main.o):(.text.startup+0xa0): undefined reference to `WinMain@16' collect2.exe: error: ld returned 1 exit status
错误原因
- 你的代码采用的是Linux x86平台的系统调用规范:
int 0x80是Linux下触发系统调用的指令,_start是Linux程序的默认入口点,这套逻辑在Windows系统下完全不兼容。 - GCC链接器在Windows环境下,默认会寻找控制台程序入口
main或GUI程序入口WinMain@16,但你的代码定义的是Linux风格的_start,导致链接器找不到合法入口,抛出错误。
解决方案
方案1:改用Windows兼容的C标准库入口(推荐,适合新手)
修改代码为调用C标准库的printf函数,适配Windows链接规则:
section .data msg db 'Hello World', 0x0A, 0 ; 注意添加字符串结束符0,符合C标准库要求 section .text global main extern _printf ; 声明外部C标准库函数 main: push msg ; 传递printf的参数 call _printf ; 调用printf输出字符串 add esp, 4 ; 清理栈(因为push了4字节的参数) mov eax, 0 ; 返回0表示程序正常结束 ret
编译链接命令:
nasm -fwin32 hello_world.asm && gcc hello_world.obj -o hello_world.exe
方案2:强制链接器使用_start作为入口(仅解决链接问题,代码需适配Windows系统调用)
如果想保留_start入口,可通过GCC参数指定链接器忽略默认入口,命令改为:
gcc hello_world.obj -o hello_world.exe -nostartfiles
但注意:原代码中的int 0x80系统调用在Windows下无效,执行会崩溃,必须把Linux系统调用替换为Windows的系统调用或API(比如WriteFile,需处理句柄等细节,相对复杂)。
内容的提问来源于stack exchange,提问作者Felix Hötzendorfer
相关产品推荐
相关产品推荐

