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

Assembly print宏打印大数值时输出多余前缀字符问题排查

汇编print宏打印大数值前缀异常问题

问题表现

  • 打印小数值时输出符合预期,打印大数值时输出开头多了额外字符,暂未定位根因
  • 复现示例:
    • 执行print 1346269时输出为c1346269,开头多了字符c
    • 执行print 40000时输出正常,为预期结果40000

涉及代码

print宏实现:

%macro print 1
    mov rax, %1

    %%printInt:
        mov rcx, digit      ; rcx指向digit缓冲区起始地址
        mov rbx, 10         ; 存入换行符ASCII码
        mov [rcx], rbx      ; 缓冲区第一个字节存换行符
        inc rcx             ; 指针后移1字节

    %%storeLoop:
        xor rdx, rdx        ; 清空rdx,为除法做准备
        mov rbx, 10         
        div rbx             ; rax = rax / 10,rdx = rax % 10

        add rdx, 48         ; 余数转对应ASCII字符
        mov [rcx], dl       ; 存入当前位字符
        inc rcx             ; 指针后移1字节

        cmp rax, 0
        jnz %%storeLoop     ; rax不为0则继续处理下一位

    %%printLoop:
        push rcx

        ; 调用sys_write输出1字节
        mov rax, SYSWRITE
        mov rdi, 1
        mov rsi, rcx
        mov rdx, 1
        syscall

        pop rcx
        dec rcx
        cmp rcx, digit      ; 判断是否已经输出到缓冲区开头的换行符
        jge %%printLoop

%endmacro

宏调用示例:

_start:
        
        print 40000
        exit

根因分析

问题出在数位存储循环的指针处理逻辑:

  1. 在%%storeLoop中,每次存储完当前位的字符后都会执行inc rcx移动指针,当处理完最高位(最后一个有效字符)时,rax已经为0,但代码依然会执行一次inc rcx,导致最终rcx指向最后一个有效字符后面的未初始化内存,而非最高位字符本身。
  2. 进入%%printLoop后,第一次调用sys_write时rsi直接使用了这个指向未初始化内存的指针,输出的是数据段残留的垃圾值:
    • 打印40000这类小数值时,该位置残留的恰好是ASCII控制字符或空字符,终端不会显示,看起来输出正常
    • 打印1346269这类大数值时,该位置残留的是可打印字符(本次是ASCII码0x63对应字符c),就会出现前缀多余字符的异常
  3. 额外隐患:代码中未体现digit缓冲区的定义大小,64位无符号整数最多有20位十进制数,加上末尾换行符,缓冲区至少需要21字节空间,否则打印极大值时会出现缓冲区越界写,破坏其他内存数据。

修复方案

在%%storeLoop结束、%%printLoop开始前,加一条dec rcx指令,让指针回退到最后一个有效字符(最高位数字)的位置,再开始循环打印即可。
修复后的核心逻辑片段:

cmp rax, 0
        jnz %%storeLoop     ; 数位存储完成后退出循环

        dec rcx             ; 回退指针,跳过存储最后一个字符后多余的自增
    %%printLoop:
        push rcx
        ; 后续sys_write逻辑保持不变

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.03 02:45:50