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

NASM代码打印db字节变量为整数时输出大值的原因

问题分析与解决方案

核心问题

  1. 参数传递错误:
    • 原代码push dword n1是把n1的内存地址压入栈,而printf的%d需要实际的32位整数值,因此输出的是随机的地址数值。
    • 改成push dword [n1]时,由于n1是db(仅1字节),读取dword会从n1地址开始读取4个字节,把后续msg的前3个字符也包含进去,导致得到错误的四字节值。
  2. 栈未正确清理:
    32位x86的cdecl调用约定中,printf属于调用者清理栈的函数,原代码调用后未手动恢复栈指针,可能引发栈不平衡问题。

正确修正方案

方案1:使用dd定义标准32位变量

直接将n1定义为4字节的双字类型,匹配%d的参数要求:

%include "io.inc"

section .data
    n1 dd 2 ; 定义32位整数,匹配%d的参数类型
    msg db 'Number is: %d',10,0 ; 修正拼写错误

section .text
extern printf
global main

main:
    push ebp
    mov ebp, esp

    push dword [n1] ; 传递n1的实际数值
    push msg
    call printf
    add esp, 8 ; 手动清理栈:两个4字节参数,共8字节

    mov esp, ebp
    pop ebp
    ret

方案2:从单字节变量扩展为32位值传递

若必须保留db定义,需将单字节值扩展为完整的32位整数后再压栈:

%include "io.inc"

section .data
    n1 db 2
    msg db 'Number is: %d',10,0

section .text
extern printf
global main

main:
    push ebp
    mov ebp, esp

    xor eax, eax ; 清空eax寄存器
    mov al, [n1] ; 将单字节n1的值放入eax的低8位
    push eax ; 压入完整的32位eax(已自动扩展为00000002)
    push msg
    call printf
    add esp, 8 ; 清理栈空间

    mov esp, ebp
    pop ebp
    ret

关键注意事项

  • 类型严格匹配:printf的%d格式符对应32位int类型,必须传递4字节的整数值,禁止传递地址或不完整的内存读取结果。
  • 调用栈维护:cdecl约定下,调用者必须手动清理参数栈,否则会破坏栈结构,导致后续执行异常。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.17 17:04:58