在NASM中编写"Hello World!"程序无输出问题求助
问题原因及解决方案
你的代码是Linux x86-64平台的系统调用实现,但你是在Windows下编译成Win64程序,两者的系统调用机制完全不兼容,导致程序执行无效指令后直接终止,没有任何输出。
为什么原代码不行?
Linux x86-64中,rax=1对应write系统调用,rax=60对应exit系统调用;但Windows的系统调用号、调用约定和Linux完全不同,直接执行这些syscall指令会触发错误,程序崩溃退出。
正确的Win64汇编实现(控制台输出)
下面提供两种可行的实现方式:
方式1:调用Win32 API(Kernel32.dll)
global main extern GetStdHandle extern WriteConsoleA extern ExitProcess section .text main: ; 获取标准输出句柄(STD_OUTPUT_HANDLE = -11) mov rcx, -11 call GetStdHandle mov rbx, rax ; 保存句柄到rbx ; 调用WriteConsoleA输出内容 mov rcx, rbx ; 参数1:控制台输出句柄 mov rdx, msg ; 参数2:输出缓冲区 mov r8, msg_len ; 参数3:要写入的字符数 mov r9, bytes_written ; 参数4:接收实际写入字节数的变量 push 0 ; 参数5:预留参数(Win64调用约定中第5个参数需栈传) call WriteConsoleA ; 退出程序 mov rcx, 0 call ExitProcess section .data msg: db 'Hello World!', 10 msg_len equ $ - msg section .bss bytes_written resd 1
编译链接命令:
../../../bin/NASM/nasm.exe -f win64 hello.asm ../../../bin/Golink/Golink.exe /console hello.obj kernel32.dll
方式2:调用C标准库printf(更简洁)
global main extern printf section .text main: sub rsp, 32 ; Win64调用约定要求预留32字节的阴影空间(shadow space) mov rcx, msg ; printf的第一个参数:格式字符串 call printf add rsp, 32 xor eax, eax ; 返回0给操作系统 ret section .data msg: db 'Hello World!', 10, 0 ; C字符串需要以0结尾
编译链接命令:
../../../bin/NASM/nasm.exe -f win64 hello.asm ../../../bin/Golink/Golink.exe /console hello.obj msvcrt.dll
运行注意
如果双击生成的hello.exe,控制台窗口会在程序结束后立刻关闭,建议打开命令提示符(CMD)或PowerShell,切换到exe所在目录后手动执行hello.exe,就能看到输出内容。
内容的提问来源于stack exchange,提问作者Jonah Currie
相关产品推荐
相关产品推荐

