推荐入门教程:【十分钟教会你汇编】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原本的地址上。由于这两个数都存在寄存器中,所以不存在覆盖操作的情况。
以上内容皆为本人观点,欢迎大家提出批评和指导,我们一起探讨!