MIPS汇编:冒泡排序


推荐入门教程:【十分钟教会你汇编】MIPS编程入门


我是先写出C++冒泡排序的代码,然后再将之手动转为汇编代码。

以下是冒泡排序的汇编代码:

################################################
# # include <iostream>
# using namespace std;
# int main(void) {
#    int num;
#    cin >> num;
#    int* arr = new int[num];
#    for (int i = 0; i < num; i++) {
#        cin >> arr[i];
#    }
#    for (int i = 0; i < num-1; i++) {
#        for (int j = 0; j+1 < num-i; j++) {
#            if (arr[j] < arr[j+1]) {
#                int temp = arr[j];
#                arr[j] = arr[j+1];
#                arr[j+1] = temp;
#            }
#        }
#    }
#    for (int i = 0; i < num; i++) {
#        cout << arr[i] << " ";
#    }
#    return 0;
# }
##################################################


.text
.globl main
main:
    la $a0,input_num_msg; # 打印字符串,提示用户输入待排序数组长度
    li $v0,4
    syscall

    li $v0,5   # 接收用户收入的数组长度
    syscall

    la $t6,array     # $t6 是数组首地址
    move $t7,$zero   # $t7 是循环变量i
    move $t8,$v0       # $t8 是数组长度
    move $t9,$zero   # $t9 是循环变量j

input:               # input代码块用于完成数组元素的输入
    la $a0,input_int_msg  # 打印字符串,提示用户输入数组的元素
    li $v0,4
    syscall

    li $v0,5
    syscall

    move $t0,$t7     # 此处类似于C/C++中指针访问数组元素的方法
    mul $t0,$t0,4    # 数组元素所占字节数*循环变量+数组的起始地址=数组[循环变量]
    addu $t1,$t0,$t6
    sw $v0,0($t1)

    addi $t7,$t7,1
    blt $t7,$t8,input
    move $t7,$zero  # 完成输入后将循环变量置为0,可作为下一个循环的循环变量,以节省寄存器

loop1:
    move $t9,$zero    # 每次执行外层循环都将内层循环的循环变量置为0
loop2:
    move $t0,$t9      # 获取a[i]
    mul $t0,$t0,4
    addu $t1,$t0,$t6
    lw $t2,0($t1)

    addi $t0,$t9,1    # 获取a[i+1]
    mul $t0,$t0,4
    addu $t4,$t0,$t6
    lw $t3,0($t4)

    bge $t2,$t3,skip  # 如果a[i] > a[i+1],跳转到skip代码块
    sw $t3,0($t1)   # 否则就执行下面这两句,交换两者的值
    sw $t2,0($t4)    

skip:
   addi $t9,$t9,1   # 内层循环变量自增,且判断是否还满足循环条件
   addi $t0,$t9,1   # 如果满足,则跳转到loop2
   sub $t1,$t8,$t7    # 如果不满足,则将外层循环的循环变量自增,且判断是否还满足循环条件
   blt $t0,$t1,loop2  # 如果满足,则跳转到loop1
   addi $t7,$t7,1     # 如果不满足,则不跳转,继续执行下面的代码
   sub $t2,$t8,1
   blt $t7,$t2,loop1

output:
   la $a0,output_int_msg  #  打印字符串,提示用户即将输出程序
   li $v0,4
   syscall

   move $t7,$zero   # 将循环变量置为0,用于下一循环,节省寄存器

print:          # 实现打印数组元素
   move $t0,$t7
   mul $t0,$t0,4
   addu $t1,$t0,$t6
   lw $a0,0($t1)
   li $v0,1
   syscall

   la $a0,seperate  # 分隔数组元素
   li $v0,4
   syscall

   addi $t7,$t7,1
   blt $t7,$t8,print   # 如果满足循环条件,跳转到print继续执行循环


.data
array:.space 1024
input_num_msg:.asciiz "Please enter the number of integers:\n"
input_int_msg:.asciiz "Please enter the integers to be sorted:\n"
output_int_msg:.asciiz "The sorted numbers are:\n"
seperate:.asciiz " "

问题一:如何利用寄存器?
解决:从计组理论课了解到,MIPS体系中有32个寄存器,且寄存器都有各自的作用。所以我就查找资料,将这32个寄存器的作用熟记于心,这对我后续使用寄存器进行各种操作提供了莫大的帮助。

问题二:如何定义一个数组?
解决:类似于C++中动态分配内存,直接给变量申请一块内存。

问题三:如何实现循环?
解决:定义代码块且指定一个名字,通过条件判断指令实现跳转,跳转的目的地可以设置为我指定的代码块。

问题四:如何实现数组的读入?
解决:我使用了一个非常巧妙的方法,来实现数组每个元素的数据的存储,即是我用循环变量乘以数组元素所占字节大小(本次实验为4字节)+数组的起始地址。这有点类似于C++中利用指针访问数组元素。(后来发现可以用左移操作符)

问题五:如何实现数组的输出?
解决:与数组的读入类似,只不过将sw指令改为lw指令。

问题六:如何实现冒泡排序?
解决:有了循环的基础,便很容易的就能实现二重循环。因此目前排序的关键就是如何定义元素内容的交换。我采用的是将两个元素的值分别存入不同的寄存器中,然后满足交换条件时,交叉存入数组中。假设这两个数为a,b。我将a存储在b原本的地址,将b存储在a原本的地址上。由于这两个数都存在寄存器中,所以不存在覆盖操作的情况。


以上内容皆为本人观点,欢迎大家提出批评和指导,我们一起探讨!


评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值