MIPS汇编迭代乘法程序寄存器传值异常:莫名加28问题排查
问题:MIPS迭代加法模拟乘法程序中被乘数值异常偏移
我正在编写一个用迭代加法模拟乘法的MIPS汇编程序,算法逻辑已完成。首次测试时将被乘数设为50,该值存入$a0后转移到$s0,但最终得到的是十进制78(二进制000001001110),而非预期的十进制50(二进制000000110010),莫名多了28。无法定位问题,附上相关代码、预期输出与实际输出,寻求排查和优化建议。
测试文件代码
.globl main main: TEST1: li $a0, A li $a1, BBB li $a2, 6 # n: number of bits jal ex.3.12 exit: li $v0, 10 syscall
ex.3.12实现文件代码
.include "./cs47.macro.asm" .globl ex.3.12 .text li $a0, 6 li $a1, 7 li $a2, 4 jal ex.3.12 print_reg ($s4) exit ex.3.12: # addi $sp, $sp, -24 sw $ra, ($sp) sw $s0, 4($sp) sw $s1, 8($sp) sw $s2, 12($sp) sw $s3, 16($sp) sw $s4, 20($sp) jal display.title # xxx print_str_literal ("Step Action Multiplier Mutiplicand Product ") move $s0, $a0 # A = multiplicand subi $s0, $s0, 28 move $s1, $a1 # B = multiplier move $s2, $a2 # N = # bits for display, assume N <= 16 li $s4, 0 # product # xxx print out the initial vals print_str_literal ("0 Inital Vals " ) print_triple ($s1, $s0, $s4) # xxx print multiplier multiplicand product print_newline () loop: beq $s2, $0, done # if index $s2==0 quit loop # xxx print out step numbers sub $t0, $a2, $s2 # xxx t0 (step number) = N - s2 (index) addi $t0, $t0, 1 # xxx t0 -- print_reg ($t0) # xxx t0 (step number) = N - 1 - s2 (index) andi $s3, $s1, 1 # s3 = right most bit of multiplier s1. beq $s3, 0, ZERO # if s3 == 0, then jump to ZERO beq $s3 1, ONE ONE: # addition happens addu $s4, $s4, $s0 # if s3 == 1, s4 += s0 (multiplicand) print_str_literal (" Prod=Prod+Mcand ") print_triple($s1,$s0,$s4) j ABC ZERO : # no addition print_str_literal (" lsb=0, no op " ) print_triple($s1, $s0, $s4) j ABC ABC: # xxx sll $s0, $s0, 1 # shift A (multiplicand) 1 bit to the left print_reg ($t0) print_str_literal(" Lshift Mcand ") print_triple($s1, $s0, $s4) srl $s1, $s1, 1 # shift B (multiplier) 1 bit to the right print_reg ($t0) print_str_literal(" Rshift Mplier ") print_triple($s1, $s0, $s4) print_newline () addi $s2, $s2 -1 j loop done: move $t0, $s4 print_str_literal(" Result of A*B by iterative addition --> ") print_reg($t0) lw $ra, ($sp) lw $s0, 4($sp) lw $s1, 8($sp) lw $s2, 12($sp) lw $s3, 16($sp) lw $s4, 20($sp) addi $sp, $sp, 24 jr $ra
预期输出(首行部分)
*********************************************************** A=50 B=10 N=6 ************************************************************ Step Action Multiplier Multiplicand Product 0 Initial Vals 001010 000000110010 000000000000
实际输出(未减28时,首行部分)
************************************************************ A=50 B=10 N=6 ************************************************************ Step Action Multiplier Mutiplicand Product 0 Initial Vals 001010 000001001110 000000000000
排查与优化建议
1. 核心问题定位
- 全局测试代码干扰参数传递:实现文件
.text段开头的li $a0,6、jal ex.3.12等代码属于全局执行逻辑,会在main函数前运行,直接覆盖main传入的$a0=50,导致被乘数初始值异常。 - 指令语法错误:
beq $s3 1, ONE不符合MIPS指令格式(缺少逗号),汇编时会生成错误机器码,引发寄存器值异常。 - 多余修正指令:临时添加的
subi $s0, $s0, 28属于无效修正,掩盖了根源问题。
2. 具体修复步骤
- 删除实现文件中
ex.3.12标签前的全局测试代码,避免干扰main的参数传递。 - 修正指令语法:将
beq $s3 1, ONE改为beq $s3, 1, ONE。 - 移除
move $s0, $a0后的subi $s0, $s0, 28指令。 - 检查
display.title、print_triple等宏的实现,确保它们不会意外修改$a0或$s0寄存器。
3. 优化建议
- 添加参数验证:在
ex.3.12函数开头打印$a0的值,确认参数传递是否正确。 - 统一输出格式:删除
ABC块中重复的print_reg ($t0),保证每一步输出格式一致。 - 增加边界测试:测试0、负数、最大位宽等特殊场景,验证算法鲁棒性。
- 规范注释:清理无用的
xxx注释,添加清晰的逻辑说明,提升代码可读性。
内容的提问来源于stack exchange,提问作者Hydro
相关产品推荐
相关产品推荐

