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

Windows 64位NASM代码使用变量时无输出,求原因及解决方法

Windows 64位NASM代码变量参数传递的重定位错误解决

问题代码

extern GetStdHandle, WriteConsoleA, ExitProcess

section .text

_main:
    mov rcx, STD_OUTPUT_HANDLE
    call GetStdHandle

    mov rcx, rax    ; hConsoleOutput
    mov rdx, msg    ; *lpBuffer
    mov r8, len     ; nNumberOfCharsToWrite
    ;mov r9, 0      ; lpNumberOfCharsWritten
    ;push 0         ; lpReserved
    call WriteConsoleA

    mov rcx, 0
    call ExitProcess

section .data

STD_OUTPUT_HANDLE: dq -11

msg:
    db "Hello World!", 0x0A
    len equ $-msg

问题现象

  • 代码编译链接正常,但运行无输出
  • 替换mov rcx, STD_OUTPUT_HANDLE为mov rcx, -11可正常输出,但希望使用变量形式
  • 修改为mov rcx, [STD_OUTPUT_HANDLE]时出现重定位错误:main.obj:main.asm:(.text+0x4): relocation truncated to fit: IMAGE_REL_AMD64_ADDR32 against '.data'
  • 编译链接命令:nasm -fwin64 main.asm && ld -LC:/Windows/System32 -lkernel32 -o main.exe main.obj

问题分析

  1. 原代码mov rcx, STD_OUTPUT_HANDLE传递的是变量的内存地址,而非变量存储的-11值,导致GetStdHandle收到非法参数,调用失败无输出。
  2. 使用mov rcx, [STD_OUTPUT_HANDLE]时,NASM默认生成32位绝对地址重定位,但64位Windows程序的.data段地址是64位的,超出32位范围,因此触发截断错误。

解决方法

在64位NASM代码中,需使用RIP相对寻址来访问数据段变量,明确生成符合64位PE规范的重定位。将mov rcx, STD_OUTPUT_HANDLE修改为:

mov rcx, [rel STD_OUTPUT_HANDLE]

修改后的完整代码

extern GetStdHandle, WriteConsoleA, ExitProcess

section .text

_main:
    mov rcx, [rel STD_OUTPUT_HANDLE]
    call GetStdHandle

    mov rcx, rax    ; hConsoleOutput
    mov rdx, [rel msg]    ; 可选:同样用RIP相对寻址访问msg
    mov r8, len     ; len是汇编时计算的常量,无需修改
    ;mov r9, 0      ; lpNumberOfCharsWritten
    push 0         ; lpReserved(注:原代码注释掉了,这里建议保留以符合Win64调用约定)
    call WriteConsoleA

    mov rcx, 0
    call ExitProcess

section .data

STD_OUTPUT_HANDLE: dq -11

msg:
    db "Hello World!", 0x0A
    len equ $-msg

注:Win64调用约定中,WriteConsoleA的第五个参数需要通过栈传递,原代码注释掉了push 0,建议保留以保证参数完整。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.25 10:56:24