前言
B站有個入門視頻,文中的例子來自MIPS彙編語言小科普
我會在代碼中添加詳細的註解,方便自己日後查看。這裏使用的是MARS模擬器,很小巧方便。
三段小程序
(1) Hello World!
C語言的Hello World! 如何轉變爲彙編語言呢?
#include<stdio.h>
int main(){
printf("Hello World!");
return 0;
}
彙編語言實際上是對寄存器進行操作,需要向外輸出時,應調用syscall指令,配合v0(2號寄存器)的值爲4時,輸出a0(4號寄存器)保存地址處的"字符串"。字符串需要保存在.data字段,程序保存在.text字段,相當於main確定程序開始的地方。(#爲註釋)
.data #數據字段,保存要打印的字符串
msg: .ascii "Hello World!\0" #msg記錄了數據的地址,.ascii告訴計算機編碼類型
#\0告訴計算機這裏字符串結束
.text #代碼字段,表示程序的入口,相當於main
la $a0,msg #$a0寄存器加載字段的地址,la表示load address加載地址指令
li $v0,4 # $v0寄存器加載4,表示要顯示字符串,li表示load immediate加載立即數指令
syscall # 調用字符串輸出
總體來看,彙編代碼分成兩段,數據段和代碼段。printf輸出函數需要兩個寄存器v0, a0配合syscall指令完成。
(2) IF-ELSE
輸入兩個數,如果前者大,輸出YES,反之NO。
#include<stdio.h>
int main(){
int a,b;
scanf("%d",&a);
scanf("%d",&b);
if(a>b)
printf("YES");
else
printf("NO");
return 0;
}
這裏同樣要定義數據字段保存“YES”,“NO”,但多了一個終端輸入部分,同樣需要用syscall,但需要改變v0加載的值,變爲5,輸入的數據會保存在v0中。另外需要一個比較跳轉語句bgt(greater 就跳)。最後需要一個程序結束命令,相當於return 0,同樣調用syscall,但v0改爲10。具體下
.data #數據段保存輸出字符串,注意加\0
msg_yes: .ascii "YES\0"
msg_no: .ascii "NO\0"
.text #程序段相當於main入口
li $v0,5 #scanf("%d",&a); t0保存a的值
syscall
move $t0,$v0
li $v0,5 #scanf("%d",&b); t1保存b的值
syscall
move $t1,$v0
bgt $t0,$t1,s1 #a>b就跳轉到標籤s1,記錄了printf("YES")程序的開始地址
la $a0,msg_no #printf("NO");
li $v0,4
syscall
j stop #直接跳轉到結束語句stop
s1:
la $a0,msg_yes #printf("YES");
li $v0,4
syscall
stop: #結束程序語句,類似return 0;
li $v0 10
syscall
這裏的j指令表示直接跳轉,一般跟某個標籤作爲跳轉地址,不會具體寫內存地址。如果希望預留空間指定某個地址寫程序,可以用.ktext 加地址。
.ktext 0x0100 #stop標籤的地址在內存0x100的位置上
stop:
li $v0 10
syscall
(3) WHILE
計算1+2+…+100並輸出
#include<stdio.h>
int main(){
int i=1;
int s=0;
while (i<=100){
s=s+i;
i=i+1;
}
printf("%d",s);
return 0;
}
我們需要兩個寄存器保存i,s的值,while循環通過跳轉指令,循環裏面用加法指令,最後輸出整型並返回,輸出整型需要讓v0=1,a0=s(和字符串不一樣v0=4,a0是地址):
.text #main 入口
li $t0,1 #t0表示i;t1表示s
li $t1,0
loop:
add $t1,$t1,$t0 #s=s+i
add $t0,$t0,1 #i=i+1
ble $t0,100,loop #while(i<=100) .ble=branch if less or equal
move $a0,$t0 #寄存器之間數據轉移用move
li $v0,1 #打印整數
syscall #printf("%d",s)
li $v0, 10 #return 0;
syscall
值得注意的是,這裏沒有數據段,不是必須的。
總結
- mips彙編代碼一般分兩端,數據段和代碼段。其他段詳情參見模擬器Help->MIPS->Directives
- 輸入輸出返回等指令需要調用syscall,配合v0和a0,其他詳情參加模擬器Help->MIPS->Syscalls
功能 | v0 | a0 |
---|---|---|
輸出整型 | 1 | 待輸出整型 |
輸出字符串 | 4 | 待輸出字符串地址 |
輸入整型 | 5 | 無 |
返回 | 10 | 無 |
- 用到的跳轉指令:bgt(branch if greater than),j(jump),ble(branch if less or equal)
- 用到的加載指令:move(寄存器間數據移動),li(加載立即數),la(加載地址)
- 用到的運算指令:add
更進一步的學習可以參看pdf:Introduction To MIPS Assembly Language Programming