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

汇编语言如何正确打印数组元素 解决输出乱码数值错误问题

问题原因

输出乱码、数值错误由3处代码错误共同导致:

  • 数组元素尺寸与寄存器读取长度不匹配:numbers数组使用db定义,每个元素仅占1字节(8位)。但printNumber宏首行执行mov eax, %1时,eax是32位寄存器,传入[r8]作为参数时,会从r8指向的内存地址开始连续读取4字节数据,而非目标位置的单字节值40。小端序下连续读取的4个字节(40、50、60、70)会被拼接为32位整数0x463c3228,转十进制恰好是你看到的乱码值117835012。
  • 缓冲区分配错误:.bss段中digit resb 0仅预留0字节空间,后续写入换行符、数字字符的操作全为越界内存写入,会破坏相邻内存数据,存在段错误风险。
  • 内存引用传参易产生歧义:直接将[r8]作为宏参数传入时,若未显式指定操作数长度,汇编器会默认按目标寄存器的宽度读取内存,容易出现取值长度不符合预期的问题,你调试时看到eax存数组地址,本质是传参时误传入了指针本身而非指针指向的值。

传入立即数3000时可正常打印,是因为立即数会被直接赋值给eax,不存在内存读取长度不匹配的问题;打印0-9正常是因为你此前使用立即数传参,而非从数组中读取元素。

修复方案

按以下步骤修改代码即可正常输出:

  1. 修正缓冲区大小:32位整数最长为10位十进制数,加上1位换行符,预留16字节足够使用,将.bss段定义改为:
    section .bss
        digit resb 16
    
  2. 读取数组元素时显式做零扩展,避免多读取字节:从1字节长度的db数组取值时,使用movzx指令零扩展到32位寄存器,确保高位全为0,不会拼接相邻内存的数据,再将寄存器值传入宏:
    _start:
        mov r8, numbers + 2
        movzx eax, byte [r8]  ; 仅读取1字节元素,零扩展到eax
        printNumber eax       ; 直接传入寄存器中的正确数值
        printNumber 3000
    
  3. (可选优化)宏中除法逻辑可明确使用32位运算,避免64位除法带来的冗余开销,当前你写的xor rdx, rdx配合div rbx可正常运行,但传入大于2^32的数值时需要额外处理长度。
修复后验证

修改后调用printNumber eax会正确读取到数组第3个元素40,输出结果与预期一致,不会再出现乱码。

内容的提问来源于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 05:31:36