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

使用NASM与WinAPI编写Hello World无输出,请求排查问题

排查Win64 NASM程序无输出问题

我用Netwide Assembler(NASM)编写输出Hello World的Win64汇编程序,编译运行后无任何输出,但退出状态为0(成功)。程序遵循x64调用约定传递参数:首参数入RCX,次参数入RDX,第三入R8,第四入R9,第五放在[RSP + 32]。

程序代码

section .data
    phrase db 'Hello World'     ; 定义字符串字节变量
    charsWritten dd 0           ; 存储实际写入字符数的变量
section .text
    global _start
    extern ExitProcess          ; 导入退出程序函数
    extern WriteConsoleA        ; 导入控制台输出函数
    extern GetStdHandle         ; 导入标准句柄获取函数
    _start:
        mov  rcx, -10           ; 传入STD_OUTPUT_HANDLE常量值-10
        call GetStdHandle       ; 调用后句柄保存在rax中
        mov r8, rax             ; 保存标准输出句柄到r8

        mov rcx, r8             ; 第一个参数:标准输出句柄
        mov rdx, phrase         ; 第二个参数:字符串指针
        mov r8, 11              ; 第三个参数:字符串长度11
        mov r9, charsWritten    ; 第四个参数:charsWritten的指针
        mov qword [rsp + 32], 0 ; 第五个参数:保留参数设为0
        call WriteConsoleA      ; 调用输出函数

        mov rcx, 0              ; ExitProcess参数:退出码0
        call ExitProcess        ; 退出程序

编译运行步骤

C:\Users\Мила ПК\Desktop>nasm -f win64 test.asm -o test.o

C:\Users\Мила ПК\Desktop>ld -o test.exe test.o -lkernel32
C:\Users\Мила ПК\Desktop>test.exe
C:\Users\Мила ПК\Desktop>echo %ERRORLEVEL%
0

环境信息

参数值
操作系统Windows 11 Pro
系统架构64位
处理器Intel i7

问题原因分析

程序无输出的核心问题是栈对齐不符合Win64调用约定:
Win64调用约定明确要求,执行call指令调用函数前,栈指针RSP必须保持16字节对齐。_start入口点处栈是16字节对齐状态,但调用GetStdHandle时,call指令会将8字节的返回地址压入栈,导致RSP偏移8字节,不再满足对齐要求。后续调用WriteConsoleA时,栈未恢复对齐状态,触发函数调用行为异常,最终没有执行输出操作。

另外代码中存在一个参数保存的风险:调用GetStdHandle后将句柄存入r8,但后续又用r8传递WriteConsoleA的第三个参数,会覆盖之前保存的句柄值——好在代码中紧接着将r8赋值给rcx,刚好在覆盖前完成了句柄传递,未直接引发错误,但写法不严谨。

修正后的代码

section .data
    phrase db 'Hello World'
    charsWritten dd 0
section .text
    global _start
    extern ExitProcess
    extern WriteConsoleA
    extern GetStdHandle
    _start:
        ; 入口处预留32字节影子空间,同时保持栈16字节对齐(32是16的倍数)
        sub rsp, 32
        
        mov rcx, -10
        call GetStdHandle
        
        ; 调用GetStdHandle后栈偏移8字节,调整回16对齐
        sub rsp, 8
        
        mov rcx, rax             ; 1st参数:标准输出句柄
        mov rdx, phrase          ; 2nd参数:字符串指针
        mov r8, 11               ; 3rd参数:字符串长度
        mov r9, charsWritten     ; 4th参数:charsWritten指针
        mov qword [rsp + 32], 0  ; 5th参数:保留参数
        call WriteConsoleA
        
        ; 恢复栈空间后调用ExitProcess
        add rsp, 40
        mov rcx, 0
        call ExitProcess

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.26 06:43:25