如何用MIPS Assembly从数组提取整数并实现求和打印?
MIPS汇编:输入整数数组求和问题修正
问题说明
使用MARS IDE编写MIPS汇编代码,目标是从用户输入的字符串中提取整数存入堆数组,然后求和并打印。目前能正确存储输入值到堆中,但无法正确提取值计算总和,附上测试打印语句。
原代码中的关键错误
- 数组基地址丢失:在
endGetNIntsLoop中执行la $t2, 0会将$t2设置为0地址,彻底丢失了之前用syscall 9分配的数组基地址,后续无法正确读取数组元素。 - 测试打印逻辑错误:尝试打印数组第一个元素时用
la $t3, 0($t2)是取地址而非数值,应该用lw指令加载内存中的值。 - 求和循环的潜在混淆:求和时通过
subi $t2, $t2, 4往回遍历数组,虽然求和结果不受顺序影响,但搭配错误的$t2值会完全读取错误的内存区域。
修正后的代码
.data prompt1: .asciiz "Enter an int n (# of integers): " prompt2: .asciiz "Input " prompt3: .asciiz " \nwith a space between each value, then press enter: " newLine: .asciiz " \n" inputString: .space 100 # 修正:用.space而非.word分配字符串空间 .text main: # 提示输入n li $v0, 4 la $a0, prompt1 syscall # 获取用户输入的n li $v0, 5 syscall move $t0, $v0 # n存到$t0 # 计算数组所需字节数并分配堆内存 li $t4, 4 mul $a0, $t0, $t4 mflo $t1 li $v0, 9 move $a0, $t1 syscall move $t2, $v0 # $t2用于遍历数组存数 move $t7, $v0 # 保存数组基地址到$t7,后续求和用 # 提示输入n个整数 li $v0, 4 la $a0, prompt2 syscall li $v0, 1 move $a0, $t0 syscall li $v0, 4 la $a0, prompt3 syscall # 获取输入字符串 li $v0, 8 la $a0, inputString li $a1, 100 syscall la $t3, inputString # 初始化循环变量 li $t4, 0 # 已读取的整数计数 li $t6, 0 # 临时存储正在解析的整数 getNIntsLoop: beq $t4, $t0, endGetNIntsLoop # 读取完n个整数则退出 lb $t5, 0($t3) # 读取当前字符 beq $t5, 31, skipFirstByte # 跳过控制字符 beq $t5, 32, saveLastInt # 遇到空格保存当前整数 beq $t5, 10, saveLastInt # 遇到回车保存当前整数 # 解析数字字符为整数 subi $t5, $t5, 48 mul $t6, $t6, 10 add $t6, $t6, $t5 addi $t3, $t3, 1 j getNIntsLoop skipFirstByte: addi $t3, $t3, 1 j getNIntsLoop saveLastInt: # 保存解析好的整数到数组 sw $t6, 0($t2) # 测试打印:确认存储的值 li $v0, 1 move $a0, $t6 syscall li $v0, 1 lw $a0, 0($t2) syscall li $v0, 4 la $a0, newLine syscall addi $t2, $t2, 4 # 移动到数组下一个位置 addi $t3, $t3, 1 # 移动到下一个字符 li $t6, 0 # 重置临时解析变量 addi $t4, $t4, 1 # 计数+1 j getNIntsLoop endGetNIntsLoop: move $t2, $t7 # 恢复数组基地址到$t2 # 测试打印数组元素 li $v0, 4 la $a0, newLine syscall li $v0, 1 lw $a0, 0($t2) # 打印第一个元素 syscall li $v0, 4 la $a0, newLine syscall li $v0, 1 lw $a0, 4($t2) # 打印第二个元素(如果n>=2) syscall li $v0, 4 la $a0, newLine syscall # 初始化求和变量 li $t5, 0 # $t5存储总和 li $t4, 0 # 重置计数器为0 getSumLoop: beq $t4, $t0, endSumLoop # 遍历完n个元素则退出 lw $t6, 0($t2) # 加载当前数组元素 add $t5, $t5, $t6 # 累加到总和 addi $t2, $t2, 4 # 移动到下一个元素 addi $t4, $t4, 1 # 计数器+1 j getSumLoop # 继续循环 endSumLoop: # 打印总和 li $v0, 4 la $a0, newLine syscall li $v0, 1 move $a0, $t5 syscall # 退出程序 li $v0, 10 syscall
关键修改点
- 保留数组基地址:在分配堆内存后,用
$t7保存基地址,避免$t2在存数时递增导致基地址丢失。 - 修正字符串存储:将
inputString: .word 100改为inputString: .space 100,正确分配字符串存储空间。 - 求和循环正向遍历:重置计数器从0开始,正向遍历数组,逻辑更直观,避免反向遍历的混淆。
- 修复测试打印:用
lw指令加载数组元素的值而非地址,正确打印存储的整数。
内容的提问来源于stack exchange,提问作者adamruehle
相关产品推荐
相关产品推荐

