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

Win64环境下NASM汇编程序无法向控制台输出的问题排查

问题根因

你把Linux系统的中断调用逻辑和Windows x64平台的API调用规则完全混淆了,代码存在多个根本性错误,编译链接没报错不代表逻辑正确,程序实际没有执行到有效输出逻辑,也没有正确触发进程退出。


具体错误点

  • 错误使用int指令调用Win32 API:你链接的WriteFile、ExitProcess是kernel32.dll导出的用户态函数,需要用call指令直接调用,不存在“给寄存器传系统调用号、触发软中断调API”的用法——int后面跟的是中断号,不是函数地址,你写的int WriteFile属于未定义行为,只是刚好没有触发崩溃,程序直接跳过了函数调用逻辑往下执行。
  • 调用约定、参数完全不匹配:
    1. Windows x64的用户态函数调用,前四个参数按顺序放在RCX/RDX/R8/R9寄存器,调用前需要给被调函数预留32字节的影子空间,且栈要16字节对齐,你完全没有遵守这个约定。
    2. 你代码里写的rbx=1(stdout文件描述符)、rdx=4(sys_write系统调用号)是Linux平台的规则,Windows上完全不生效:Windows的控制台标准输出句柄不是硬编码的1,需要调用GetStdHandle传入参数-11(即STD_OUTPUT_HANDLE)才能拿到。
    3. WriteFile的参数顺序你完全传错了,它需要5个参数:控制台句柄、缓冲区指针、写入长度、实际写入长度的输出指针、重叠结构指针,你之前的寄存器赋值完全不符合要求。
  • 换行符不符合Windows控制台规范:你用的单独0xa(即\n)在部分Windows控制台环境下不会触发行缓冲刷新,应该用Windows标准的CRLF换行(0xd,0xa即\r\n)。

修正后的可运行代码

extern GetStdHandle
extern WriteFile
extern ExitProcess

section .text
global Start

Start:
    sub rsp, 28h    ; 预留32字节影子空间 + 调整栈到16字节对齐,共40字节(0x28)

    ; 获取标准输出句柄
    mov rcx, 0FFFFFFFFFFFFFFF5h    ; STD_OUTPUT_HANDLE 常量值为-11
    call GetStdHandle

    ; 调用WriteFile输出字符串
    mov rcx, rax                   ; 参数1:刚拿到的stdout句柄
    mov rdx, msg                   ; 参数2:字符串起始地址
    mov r8, len                    ; 参数3:字符串长度
    mov r9, bytes_written          ; 参数4:接收实际写入字节数的变量指针
    mov qword [rsp + 20h], 0       ; 参数5:lpOverlapped传NULL,放在栈上影子空间之后
    call WriteFile

    ; 退出进程,返回码0
    mov rcx, 0
    call ExitProcess

section .data
msg db 'Hello, world!', 0dh, 0ah  ; 字符串+CRLF换行
len equ $ - msg

section .bss
bytes_written resq 1               ; 预留8字节存储实际写入长度

编译运行命令

和你之前用的命令一致,直接执行即可正常输出:

nasm -f win64 -o hello_world.obj hello_world.asm
golink hello_world.obj kernel32.dll
hello_world.exe

内容的提问来源于stack exchange,提问作者JNichols

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.28 07:01:01