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

x86 NASM程序崩溃问题:字符串字符遍历与打印

问题分析与修复

你的程序崩溃的核心原因是调用_printf会破坏eax寄存器的值——printf遵循cdecl调用约定,会将返回值写入eax,而你恰好用eax保存字符串的遍历指针。第一次调用printf后,eax被改写,后续循环无法正确获取下一个字符的地址,直接导致崩溃。

同时你的代码还有一个潜在风险:直接将单个字符的地址作为格式字符串传给printf,如果字符是%这类格式说明符的起始符,会触发未定义行为,导致程序异常。

修复后的代码

global _main
extern _printf

section .data
string: db 'Iterate over this string #test', 0
fmt_char: db '%c', 0  ; 用%c格式符专门打印单个字符
endStr: db 'Ended.', 0

section .text
_main:  
    lea ebx, string         ; 改用非易失寄存器ebx保存字符串地址(cdecl约定中ebx不会被函数破坏)

loop:
    mov cl, [ebx]           ; 读取当前位置的字符到cl
    test cl, cl             ; 检查是否到达字符串结束符(0)
    jz end

    ; 调用printf打印单个字符:参数从右到左压栈
    push ecx                ; 第二个参数:要打印的字符
    push fmt_char           ; 第一个参数:格式字符串
    call _printf
    add esp, 8              ; 清理栈上的两个参数(每个4字节)

    inc ebx                 ; 移动到下一个字符的地址
    jmp loop

end:
    ; 可选:打印结束提示
    push endStr
    call _printf
    add esp, 4
    ret

关键修改点

  1. 寄存器选择:用ebx代替eax存储字符串指针。cdecl调用约定中,ebx、ebp、esi、edi属于非易失性寄存器,函数调用后会保留原值,不会被printf破坏。
  2. 安全打印单个字符:使用%c格式符直接传递字符值,避免将单个字符当作格式字符串传入的风险,同时不需要额外的内存变量存储字符。
  3. 正确清理栈空间:每次调用printf压入了两个参数(格式字符串和字符),因此用add esp, 8清理栈,符合cdecl调用的要求。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.21 09:40:04