x86-64平台Windows与Linux下int 0x80系统调用汇编Hello World问题
解决Linux汇编代码在Windows下无法输出Hello World的问题
你的汇编代码是基于Linux x86系统调用编写的,依赖int 0x80触发内核服务完成输出和退出,但Windows完全不兼容这套机制——它没有int 0x80这类系统调用,所有用户态功能都需要通过Win32 API实现,这就是编译通过但运行无输出的根本原因。
解决方案:针对Windows平台重写代码
需要使用Win32 API完成控制台输出和程序退出,同时遵循Win64汇编的调用约定,以下提供两种实现方案:
方案1:纯Win32 API实现控制台输出
使用WriteConsoleA和ExitProcess系统API完成功能,代码如下:
section .data var_msg db 0xA, 'hello world', 0xA ; 带换行的输出内容 var_len equ $ - var_msg ; 计算字符串长度 section .text global main ; 程序入口,对应Windows PE的mainCRTStartup extern GetStdHandle, WriteConsoleA, ExitProcess ; 声明外部API main: ; 获取标准输出句柄 mov rcx, -11 ; STD_OUTPUT_HANDLE的常量值为-11 call GetStdHandle ; 调用WriteConsoleA输出字符串 mov rcx, rax ; 参数1:标准输出句柄(GetStdHandle的返回值) mov rdx, var_msg ; 参数2:要输出的字符串指针 mov r8, var_len ; 参数3:字符串长度 sub rsp, 8 ; 栈对齐(Win64要求栈始终保持16字节对齐) mov r9, rsp ; 参数4:接收实际写入字节数的指针(可忽略,但必须传递) mov qword [rsp+32], 0 ; 参数5:保留参数,设为0 call WriteConsoleA add rsp, 8 ; 恢复栈空间 ; 退出程序 mov rcx, 0 ; 参数1:程序返回码(0表示正常退出) call ExitProcess
编译命令(Windows下)
编译后需要链接Windows的kernel32.dll库(提供上述API):
nasm -f win64 hello_win.asm -o hello_win.o ld hello_win.o -lkernel32 -o hello_win.exe
或者用MinGW的GCC链接更简便:
nasm -f win64 hello_win.asm -o hello_win.o gcc hello_win.o -o hello_win.exe
方案2:调用C标准库printf简化代码
如果不想直接写Win32 API,也可以调用C标准库的printf函数,代码更简洁:
section .data fmt_str db '%s', 0xA, 0 ; printf的格式字符串 hello_str db 'hello world', 0xA, 0 ; 要输出的内容 section .text global main extern printf, exit ; 声明C库函数 main: ; 调用printf输出字符串 mov rcx, fmt_str ; 参数1:格式字符串指针 mov rdx, hello_str ; 参数2:要输出的字符串指针 call printf ; 退出程序 mov rcx, 0 ; 返回码0 call exit
编译命令
编译后链接C标准库(msvcrt.dll):
nasm -f win64 hello_printf.asm -o hello_printf.o gcc hello_printf.o -o hello_printf.exe
关键注意点
- 调用约定差异:Win64汇编使用FastCall约定,前4个参数依次放入
RCX、RDX、R8、R9寄存器,且调用前必须保证栈是16字节对齐 - 入口点差异:Windows PE程序的默认入口是
mainCRTStartup,定义main函数后,链接器会自动处理C运行时的初始化工作 - 依赖库:必须链接对应API所在的系统库(kernel32.dll或msvcrt.dll),否则会出现链接错误
内容的提问来源于stack exchange,提问作者DevMaster
相关产品推荐
相关产品推荐

