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

MIPS/MARS二进制打印问题求助:调试print_binary子程序

调试MIPS汇编print_binary子程序问题

问题背景

现有一段MIPS汇编程序,main部分会调用print_binary子程序对三个测试数(2、-1、0xcafef00d)执行32位二进制打印操作。要求仅调试print_binary子程序(不得修改main和end部分),使输出符合预期:

预期输出

00000000000000000000000000000010
11111111111111111111111111111111
11001010111111101111000000001101

注:原问题中给出的第一个预期串为00000000000000000000000000000011,对应数字3,与测试数2不符,此处按测试数2的正确二进制修正。

当前错误输出

00000000000000000000000000000000
10000000000000000000000000000000
10000000000000000000000000000000

原代码

.text
main:
    li  $a0, 2
    jal print_binary
    li  $a0, -1
    jal print_binary
    li  $a0, 0xcafef00d
    jal print_binary

    li  $v0, 10             # exit
    syscall

# On entry, a0 = number to print in binary
print_binary:
    li $t1, 32               # Initialize a counter for the bit position (32 bits for unsigned)

loop:
    beqz $t1, end           # Exit the loop if all bits have been processed

    srl $t2, $a0, 31        # Get the most significant bit of the number
    andi $t2, $t2, 1        # Mask the least significant bit
    addi $t2, $t2, 48       # Convert the bit value to ASCII ('0' or '1')

    li $v0, 11              # syscall to print one char
    move $a0, $t2           # Load the bit value into $a0
    syscall

    sll $a0, $a0, 1         # Shift the original number to the left by 1 bit
    addiu $t1, $t1, -1      # Decrement the counter
    j loop

end:
    li $v0, 11              # syscall to print one char
    li $a0, 10              # Load newline character into $a0 ('\n')
    syscall
    jr $ra

错误原因分析

  1. 原始数字被覆盖:执行打印字符的系统调用时,代码将$a0的值替换为ASCII字符,导致后续移位操作针对的是ASCII值而非原始输入数字,完全偏离预期逻辑。
  2. 移位对象错误:移位操作本应针对输入的原始数字,但由于$a0被打印操作覆盖,实际操作的是已修改的ASCII值,导致后续所有位的提取全部错误。

修正后的print_binary子程序

仅修改print_binary部分,核心是用临时寄存器$t0保存原始输入数字,避免$a0被打印操作破坏:

# On entry, a0 = number to print in binary
print_binary:
    li $t1, 32               # 初始化32位计数器
    move $t0, $a0            # 将原始数字保存到$t0,避免$a0被打印操作覆盖

loop:
    beqz $t1, end           # 计数器为0则退出循环

    srl $t2, $t0, 31        # 逻辑右移31位,将最高位移到最低位
    andi $t2, $t2, 1        # 提取最低位,得到0或1
    addi $t2, $t2, 48       # 转换为ASCII的'0'或'1'

    li $v0, 11              # 打印单个字符的系统调用
    move $a0, $t2           # 将ASCII字符传入$a0用于打印
    syscall

    sll $t0, $t0, 1         # 对原始数字左移一位,准备下一位的打印
    addiu $t1, $t1, -1      # 计数器减1
    j loop

修正说明

  • 新增move $t0, $a0:将输入的原始数字保存到临时寄存器$t0,确保后续位提取和移位操作始终基于原始数字。
  • 所有位操作改为针对$t0:彻底避免$a0被打印操作覆盖后导致的逻辑错误。
  • 保留逻辑右移srl:对于32位无符号打印需求,逻辑右移能正确提取最高位(包括负数的符号位),结合andi可得到正确的0/1值。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.10 12:36:05