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

将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
问题分析与修复

报错及代码问题总结

  1. 分支逻辑错误:原C++判断n < 1 || n > 10跳转错误分支,你写的ble $t0, $t1, invalidInput(n<=1时跳转)不符合逻辑,应该是blt $t0, $t1, invalidInput(n<1时跳转)。
  2. 直接引用字符串字面量:QtSpim不支持la $a0, "\n"这种直接加载字符串字面量的写法,必须在.data段定义字符串常量。
  3. 输出逻辑与原C++不符:原C++是先读取所有输入到数组,再遍历数组输出偶数并计算平均值;你的代码边读边输出偶数,还颠倒了"The even numbers are: "和偶数的输出顺序。
  4. 浮点数处理错误:原C++使用浮点数计算平均值,你用了整数加法和除法,导致结果错误。
  5. 字符串变量未替换:valuesPrompt里的n没有实际输出数值,原C++会显示用户输入的n值,你直接写死了"Enter n..."。
  6. 标签嵌套问题: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

代码说明

  1. 数组存储:定义even_array存储所有输入值,完全匹配原C++先存后处理的逻辑。
  2. 浮点数处理:使用MIPS浮点寄存器处理浮点数运算,确保平均值计算精度符合要求。
  3. 分支逻辑:修正n的范围判断,和原C++的n < 1 || n > 10逻辑完全一致。
  4. 动态字符串输出:拆分输入提示字符串,插入用户输入的n值,实现和原C++一致的动态提示。
  5. 标签规范:所有标签独立定义,避免嵌套导致的跳转异常。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.09 23:32:03