推薦入門教程:【十分鐘教會你彙編】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原本的地址上。由於這兩個數都存在寄存器中,所以不存在覆蓋操作的情況。
以上內容皆爲本人觀點,歡迎大家提出批評和指導,我們一起探討!