MIPS汇编:冒泡排序

来源:互联网 发布:java文件流转文件 编辑:程序博客网 时间:2024/05/01 04:01

推荐入门教程:【十分钟教会你汇编】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 mainmain:    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 是循环变量jinput:               # 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    # 每次执行外层循环都将内层循环的循环变量置为0loop2:    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,loop1output:   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继续执行循环.dataarray:.space 1024input_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 0
原创粉丝点击