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

请翻译带MIPS汇编注释的冒泡排序C代码并完善对应汇编实现

嘿,我来帮你梳理MIPS里减法相关的条件分支逻辑,同时把那段冒泡排序的C代码补全并翻译成中文,再给出完整的MIPS汇编实现~

MIPS汇编减法条件分支说明与冒泡排序实现

一、MIPS减法相关条件分支指令说明

在MIPS汇编中,没有直接的减法比较分支指令,通常通过设置小于测试指令结合分支指令来实现类似“大于/等于”的条件判断(本质是通过反向判断小于关系来推导):

  • slt rd, rs, rt:若寄存器rs的有符号值小于rt,则将rd设为1,否则设为0;
  • sltu rd, rs, rt:无符号版本的小于测试,逻辑同上,但按无符号数规则比较;
  • beq rd, $0, label:若rd的值为0,就跳转到label标签处。

举个实际场景:要实现C代码中的if(i >= N) goto Endl,我们可以拆解为:

  1. 先用slt $t0, $s0, $s1(假设$s0存i,$s1存N)判断i < N:如果成立,$t0=1;否则$t0=0;
  2. 再用beq $t0, $0, Endl:当$t0=0时,说明i >= N,此时跳转到Endl。

这样就完美实现了“大于等于”的分支逻辑,相当于用减法的反向比较来完成判断。

二、带MIPS注释的冒泡排序C代码(完整补全+翻译)

你提供的代码是未完成的冒泡排序片段,我先补全核心逻辑,同时把注释翻译成中文:

#include <stdio.h>
int arr[5] = {5, 3, 4, 1, 2};  // 待排序的整数数组
int main(){
    int k;
    int N = 5, i, j;
    char * parr0 = (char*) arr;  /* MIPS对应指令:la parr0, arr (加载数组基地址到parr0寄存器)*/
    char * parrj;
    i = 0;
for1: if(i >= N) goto Endl;  /* MIPS对应逻辑:slt $t0, $s0, $s1 ($s0=i,$s1=N);beq $t0, $0, Endl (如果i>=N则跳转到Endl)*/
    j = 0;
for2: if(j >= N-1-i) goto End2;  // 内层循环终止条件:j >= 未排序部分的长度
    parrj = (parr0 + 4*j);  // 计算arr[j]的地址(int占4字节,所以偏移4*j)
    int x1 = *((int*)parrj);  /* MIPS对应指令:lw $t1, 0($t2) ($t2是parrj,加载arr[j]到$t1寄存器,替代C中的arr[j])*/
    int x2 = *((int*)(parrj+4));  /* MIPS对应指令:lw $t2, 4($t2) (加载arr[j+1]到$t2寄存器,对应arr[j+1])*/
    
    // 补全冒泡排序核心逻辑:比较并交换相邻元素
    if(x1 > x2){
        // 交换arr[j]和arr[j+1]
        *((int*)parrj) = x2;
        *((int*)(parrj+4)) = x1;
    }
    j++;
    goto for2;
End2:
    i++;
    goto for1;
Endl:
    // 打印排序后的数组
    for(k=0; k<N; k++){
        printf("%d ", arr[k]);
    }
    return 0;
}

三、完整MIPS汇编实现(对应上述冒泡排序)

以下是基于MIPS32架构的完整汇编代码,包含数据段、代码段,每一步都有详细注释:

.data
arr:    .word   5, 3, 4, 1, 2   # 待排序的整数数组
N:      .word   5               # 数组长度
newline:.asciiz "\n"
space:  .asciiz " "

.text
.globl main
main:
    la  $s0, arr                # $s0 = arr基地址(对应C中的parr0)
    lw  $s1, N                  # $s1 = N = 5
    li  $s2, 0                  # $s2 = i = 0

# 外层循环:对应C中的for1标签
for1:
    slt $t0, $s2, $s1           # 判断i < N?是则$t0=1,否则0
    beq $t0, $0, print_result   # 如果i >= N,跳转到打印结果(对应原代码的Endl)
    
    li  $s3, 0                  # $s3 = j = 0
    sub $t1, $s1, 1             # $t1 = N-1
    sub $t1, $t1, $s2           # $t1 = N-1 - i(内层循环终止条件值)

# 内层循环:对应C中的for2标签
for2:
    slt $t0, $s3, $t1           # 判断j < N-1-i?是则$t0=1,否则0
    beq $t0, $0, end_for2       # 如果j >= N-1-i,跳转到end_for2(对应原代码的End2)
    
    sll $t2, $s3, 2             # $t2 = 4*j(int占4字节,左移2位等价乘4)
    add $t3, $s0, $t2           # $t3 = parr0 + 4*j = &arr[j]
    
    lw  $t4, 0($t3)             # $t4 = arr[j](对应C中的x1)
    lw  $t5, 4($t3)             # $t5 = arr[j+1](对应C中的x2)
    
    slt $t0, $t5, $t4           # 判断arr[j+1] < arr[j]?是则$t0=1(即arr[j] > arr[j+1])
    beq $t0, $0, increment_j    # 如果arr[j] <= arr[j+1],不交换,直接j++
    
    # 交换arr[j]和arr[j+1]
    sw  $t5, 0($t3)
    sw  $t4, 4($t3)

increment_j:
    addi $s3, $s3, 1            # j++
    j   for2                    # 回到内层循环开头

end_for2:
    addi $s2, $s2, 1            # i++
    j   for1                    # 回到外层循环开头

# 打印排序后的数组
print_result:
    li  $s2, 0                  # 重置i为0,用于遍历打印
print_loop:
    slt $t0, $s2, $s1
    beq $t0, $0, exit_program
    
    sll $t2, $s2, 2
    add $t3, $s0, $t2
    lw  $a0, 0($t3)             # 加载当前数组元素到$a0
    li  $v0, 1                  # 系统调用:打印整数
    syscall
    
    la  $a0, space              # 打印空格分隔元素
    li  $v0, 4
    syscall
    
    addi $s2, $s2, 1
    j   print_loop

exit_program:
    la  $a0, newline            # 打印换行
    li  $v0, 4
    syscall
    
    li  $v0, 10                 # 退出程序系统调用
    syscall

关键细节说明:

  • 数组访问:MIPS中没有直接的数组下标访问,通过基地址+偏移量实现,用sll(左移2位)来快速计算4*j(因为int占4字节);
  • 条件分支:所有“大于/等于”的判断都通过slt反向推导,配合beq实现跳转;
  • 系统调用:使用MIPS标准的系统调用号来实现打印和退出,符合SPIM/MARS模拟器的运行规范。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.21 03:53:39