将C++11代码转为QtSpim可用MIPS汇编及报错修复请求
问题描述
需要将给定的C++11代码转换为可在QtSpim中运行的MIPS汇编.s文件,要求匹配指定输出效果。自行编写的汇编代码运行时QtSpim报错:
Instruction references undefined symbol at 0x00400044
[0x00400044] 0x10200000 beq $1, $0, 0 [invalidInput-0x00400040]
原C++11代码
#include <iostream> using namespace std; int main() { int n; int c = 0; int i = 0; float d = 0; int even [10]; float sum = 0; cout<<"Enter the number of values: "; cin>>n; if (n < 1 || n > 10) { goto err; } cout<<"Enter "<<n<<" integer values, one per line.\n"; input: { cin>>even[i]; i++; } if (i < n) { goto input; } cout<<"The even numbers are: "; show: { if (even[c]%2!=0) { goto ret; } if (sum == 0) { goto skip; } cout<<", "; skip: cout<<even[c]; sum += (float)even[c]; d++; ret: { c++; if (c < n) { goto show; } } } cout<<"\nThe average of the even numbers is: "<<(sum/d); goto end; err: { cout<<"Error: number of values should be between 1-10"; } end: { return 0; } }
预期输出
Enter the number of values: 4 Enter 4 integer values, one per line. 4 6 10 3 The even numbers are: 4, 6, 10 The average of the even numbers is: 6.66667
自行编写的报错汇编代码
.data prompt: .asciiz "Enter the number of values: " valuesPrompt: .asciiz "Enter n integer values, one per line:\n" evenNumbers: .asciiz "\nThe even numbers are:\n" averagePrompt: .asciiz "\nThe average of the even numbers is:\n" comma: .asciiz "," negOne: .word -1 count: .word 0 sum: .word 0 .globl main .text main: # Prompt the user for the number of values li $v0, 4 la $a0, prompt syscall # Read n from the user li $v0, 5 syscall move $t0, $v0 # Check if n is between 1 and 10 li $t1, 1 ble $t0, $t1, invalidInput li $t1, 10 bgt $t0, $t1, invalidInput # Prompt the user for n values li $v0, 4 la $a0, valuesPrompt syscall # Initialize loop counter li $t1, 0 readValuesLoop: # Read the next value from the user li $v0, 5 syscall move $t2, $v0 # Check if the value is even andi $t3, $t2, 1 beqz $t3, evenNumber # Value is odd, continue to next iteration j incrementCounter evenNumber: # Print the even number li $v0, 1 move $a0, $t2 syscall # Add the even number to the sum addu $t4, $t4, $t2 # Check if it's the last even number li $t5, 1 sub $t6, $t0, $t1 beq $t5, $t6, calculateAverage # Print a comma separator li $v0, 4 la $a0, comma syscall calculateAverage: # Increment the loop counter incrementCounter: addiu $t1, $t1, 1 # Check if we have processed all values beq $t1, $t0, doneReadingValues # Continue reading values j readValuesLoop doneReadingValues: # Print even numbers message li $v0, 4 la $a0, evenNumbers syscall # Print a new line li $v0, 4 la $a0, "\n" syscall # Calculate average of even numbers divu $t4, $t0 mthi $zero # Clear upper 32 bits of dividend mflo $t4 # Print the average li $v0, 2 move $a0, $t4 syscall # Print a new line li $v0, 4 la $a0, "\n" syscall # Exit the program li $v0, 10 syscall invalidInput: # Print error message for invalid input li $v0, 4 la $a0, "Invalid input. Please enter a value between 1 and 10.\n" syscall # Exit the program li $v0, 10 syscall
问题分析与修复
报错及代码问题总结
- 分支逻辑错误:原C++判断
n < 1 || n > 10跳转错误分支,你写的ble $t0, $t1, invalidInput(n<=1时跳转)不符合逻辑,应该是blt $t0, $t1, invalidInput(n<1时跳转)。 - 直接引用字符串字面量:QtSpim不支持
la $a0, "\n"这种直接加载字符串字面量的写法,必须在.data段定义字符串常量。 - 输出逻辑与原C++不符:原C++是先读取所有输入到数组,再遍历数组输出偶数并计算平均值;你的代码边读边输出偶数,还颠倒了"The even numbers are: "和偶数的输出顺序。
- 浮点数处理错误:原C++使用浮点数计算平均值,你用了整数加法和除法,导致结果错误。
- 字符串变量未替换:
valuesPrompt里的n没有实际输出数值,原C++会显示用户输入的n值,你直接写死了"Enter n..."。 - 标签嵌套问题:
incrementCounter标签嵌套在calculateAverage内部,可能导致跳转逻辑混乱。
修复后的可运行汇编代码
.data prompt: .asciiz "Enter the number of values: " values_prompt1: .asciiz "Enter " values_prompt2: .asciiz " integer values, one per line.\n" even_msg: .asciiz "The even numbers are: " comma_space: .asciiz ", " average_msg: .asciiz "\nThe average of the even numbers is: " err_msg: .asciiz "Error: number of values should be between 1-10" newline: .asciiz "\n" even_array: .word 0:10 # 存储输入的10个整数 sum_float: .float 0.0 # 偶数和(浮点数) count_float: .float 0.0 # 偶数个数(浮点数) .globl main .text main: # 提示输入n li $v0, 4 la $a0, prompt syscall # 读取n li $v0, 5 syscall move $s0, $v0 # s0 = n # 检查n是否在1-10之间 li $t0, 1 blt $s0, $t0, err # n < 1 跳转到错误 li $t0, 10 bgt $s0, $t0, err # n > 10 跳转到错误 # 输出"Enter n integer values..." li $v0, 4 la $a0, values_prompt1 syscall li $v0, 1 move $a0, $s0 syscall li $v0, 4 la $a0, values_prompt2 syscall # 读取n个值到even_array li $s1, 0 # s1 = i(循环计数器) input_loop: li $v0, 5 syscall sll $t0, $s1, 2 # t0 = i * 4(计算数组字节偏移) sw $v0, even_array($t0) addi $s1, $s1, 1 # i++ blt $s1, $s0, input_loop # i < n 继续循环 # 输出"The even numbers are: " li $v0, 4 la $a0, even_msg syscall # 初始化变量:c=0,sum=0,d=0 li $s2, 0 # s2 = c(遍历计数器) lwc1 $f0, sum_float # f0 = sum(浮点数) lwc1 $f2, count_float # f2 = d(浮点数) show_loop: # 获取even[c]的值 sll $t0, $s2, 2 lw $t1, even_array($t0) # t1 = even[c] # 判断是否为奇数:even[c] % 2 != 0 andi $t2, $t1, 1 bne $t2, $zero, ret # 是奇数跳转到ret # 判断sum是否为0,是则跳过逗号 c.eq.s $f0, $f31 # f31默认是0.0 bc1t skip_comma # 输出", " li $v0, 4 la $a0, comma_space syscall skip_comma: # 输出even[c] li $v0, 1 move $a0, $t1 syscall # sum += (float)even[c] mtc1 $t1, $f4 cvt.s.w $f4, $f4 # 整数转浮点数 add.s $f0, $f0, $f4 # d++ addi.s $f2, $f2, 1.0 ret: addi $s2, $s2, 1 # c++ blt $s2, $s0, show_loop # c < n 继续循环 # 输出平均值提示 li $v0, 4 la $a0, average_msg syscall # 计算平均值:sum / d div.s $f12, $f0, $f2 li $v0, 2 syscall # 跳转到结束 j end err: # 输出错误信息 li $v0, 4 la $a0, err_msg syscall end: # 换行并退出 li $v0, 4 la $a0, newline syscall li $v0, 10 syscall
代码说明
- 数组存储:定义
even_array存储所有输入值,完全匹配原C++先存后处理的逻辑。 - 浮点数处理:使用MIPS浮点寄存器处理浮点数运算,确保平均值计算精度符合要求。
- 分支逻辑:修正n的范围判断,和原C++的
n < 1 || n > 10逻辑完全一致。 - 动态字符串输出:拆分输入提示字符串,插入用户输入的n值,实现和原C++一致的动态提示。
- 标签规范:所有标签独立定义,避免嵌套导致的跳转异常。
内容的提问来源于stack exchange,提问作者Aacro
相关产品推荐
相关产品推荐

