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

在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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.11 11:48:12