MIPS模拟器MARS汇编入门
前言
B站有个入门视频,文中的例子来自MIPS汇编语言小科普
我会在代码中添加详细的注解,方便自己日后查看。这里使用的是MARS模拟器,很小巧方便。
三段小程序
####(1) Hello World! C语言的Hello World! 如何转变为汇编语言呢?
#include
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
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,记录了地址
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
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