MIPS汇编自学 #1
MIPS本质上是3地址指令:源操作数1 或/和 源操作数2 (立即数、寄存器编号、内存地址)、目的操作数地址 (寄存器编号、内存地址);
内存地址的取决于操作数的存储的地方;
.data: 表示在其后的若干行存储data数据格式如下
.data
name1: .word 0x1,0x22...
name2:...
.text: 表示在其后才是指令区;
li $v0,XXX (告诉机器你需要的打印类型,整数是1,字符是4)
first program
.data
myMessege: .asciiz"Hello,World!\n"
.text
li $v0,4 #在该寄存器中存放一个值
la $a0,myMessage #load address
syscall #执行它
打印字符(与打印字符串类似)
.data
myChar: .byte 'x'
.text
li $v0,4 #存4
la $a0,myChar #load address
syscall
打印整数
.data
age: .word 5
.text
li $v0,1 #存1
lw $a0,age #load word
syscall #执行它
打印float
.data
PI: .float 3.1415
.text
li $v0,2 #存2
lwcl $f12,pI #call the system the messege
syscall #执行它
打印double
.data
PI: .double 3.1415926
zeroDouble .double 0.05
.text
ldc1 $f2,PI #load double
ldcl $f0,zeroDouble #load double
li $v0,3 #存3
add.d $f12,$f2,$f0 #$f12=$f2+$f0
syscall #执行它
addition
.data
Numa: .word 5
Numb: .word 9
.text
lw $t0,Numa($zero)
lw $t1,Numb($zero)
add $t2,$t1,$t0 #$t2=$t1+$t0
li $v0,1
add $a0,$zero,$t2 #将t2寄存器中的数据移到a0中,用来打印出来
syscall
subtract(与加法类似)
.data
Numa: .word 5
Numb: .word 9
.text
lw $t0,Numa($zero)
lw $t1,Numb($zero)
sub $t2,$t1,$t0 #$t2=$t1-$t0
li $v0,1
add $a0,$zero,$t2 #将t2寄存器中的数据移到a0中,用来打印出来,也可以用move $a0,$t2
syscall
使用乘法
有三种方式:1.mul(3个寄存器),2.mult(两个寄存器),3.sil(逻辑运算)
.data
.text
addi $s0,$zero,10 #直接存储在寄存器中而不是最开始在随机位置
addi $s1,$zero,5
mul $a0,$s0,$s1
li $v0,1
syscall
.data
.text
addi $t0,$zero,10 #直接存储在寄存器中而不是最开始在随机位置
addi $t1,$zero,5
mult $t0,$t1 #乘积得到的结果存储在低位和高位中
mflo $s0 #将低位的数据移动到$so寄存器中,move from low
#mfhi(move from high),移动高位数据
li $v0,1
add $a0,$zero,$s0 #将$s0的存储数据放入$a0中
syscall
.data
.text
addi $s0,$zero,4
sll $t0,$s0,2 #左移两位,并将结果存储在t0寄存器中
li $v0,1
add $a0,$t0,$zero
syscall
使用除法(有两种,和乘法相似)
- 在第二种方法中,除法得到的商存储在low,余数存储在high
.data
.text
addi $t0,$zero,10 #直接存储在寄存器中而不是最开始在随机位置
addi $t1,$zero,5
div $s0,$t0,$t1
li $vo,1
add $a0,$s0,$zer0
syscall
方法(函数)的创建及引用
.data
message:"xxxx"
.text
main: #主程序标签
jal PrintMessage #引用函数
li $v0,10 #告诉system程序完成
syscall
PrintMessage: #方法(函数)名
li $v0,4
la $a0,message
syscall
jr $ra #函数return寄存器
函数传参
.data
.text
main: #主程序标签
addi $a1,$zero,50
addi,$a2,$zero,100
jal addNum #引用函数
li $v0,1
add $a0,$v1,0
li $v0,10 #告诉system程序完成
syscall
addNum: #方法(函数)名
add $v1,$a1,$a2
jr $ra #函数return寄存器
存储寄存器,函数调用时不影响原来的内容
.data
message: .asciiz "\n"
.text
main: #主程序标签
addi $s0,$zero,50
jal addNum
li $v0,4
la $a0,message
syscall
move $a0,$s0
li $v0,1
syscall
li $v0,10 #告诉system程序完成
syscall
addNum: #方法(函数)名
addi $sp,$sp,-4
sw $s0,0($sp)
#调用堆栈
addi $s0,$s0,50
li $v0,1
move $a0,$s0
syscall
lw $s0,0($sp)
addi $sp,$sp,4
jr $ra #函数return寄存器
函数内部调用另一个函数
.data
message: .asciiz "\n"
.text
main: #主程序标签
addi $s0,$zero,50
jal addNum
li $v0,4
la $a0,message
syscall
move $a0,$s0
li $v0,1
syscall
li $v0,10 #告诉system程序完成
syscall
addNum: #方法(函数)名
addi $sp,$sp,-8
sw $s0,0($sp)
sw $ra,4($sp)
addi $s0,$s0,50
jal printValue
lw $s0,0($sp)
lw $ra,4($sp)
addi $sp,$sp,8
jr $ra #函数return寄存器
printValue:
li $v0,1
move $a0,$s0
syscall
jr $ra
得到用户的输入
- 整数:
.data
message: .asciiz "enter your age\n"
return: .asciiz "\nyour age is "
.text
li $v0,4
la $a0,message
syscall
li $v0,5 #告诉系统我们要写入一个整数,存储在$v0中
syscall
move $t0,$v0 #将$v0得到的输入转到$t0中
li $v0,4
la $a0,return
syscall
li $v0,1
move $a0,$t0
syscall
- float:
.data
message: .asciiz "enter your height\n"
return: .asciiz "\nyour height is "
zeroFloat: .float 0.0
.text
lwc1 $f4,zeroFloat #float没有zero寄存器
li $v0,4
la $a0,message
syscall
li $v0,6 #告诉系统我们要写入一个float,存储在$v0中
syscall
#add.s $f12,$f0,$f4 #float默认打印的寄存器是$f12
mov.s $f12,$f0 #移动float到$f12寄存器
li $v0,4
la $a0,return
syscall
li $v0,2 #打印float
syscall
- doubles:
.data
message: .asciiz "enter your height\n"
return: .asciiz "\nyour height is "
.text
li $v0,4
la $a0,message
syscall
li $v0,7 #告诉系统我们要写入一个double,存储在$v0中
syscall
li $v0,4
la $a0,return
syscall
li $v0,3 #打印double
add.d $f12,$f0,$f2 #double有默认值0.0
syscall
- TEXT:
.data
message: .asciiz "Hello,"
text: .space 20 #允许输入多少字节(字符)
.text
main:
li $v0,8 #告诉系统接下来输入字符串
la $a0,text
li $a1,20 #多长
syscall
li $v0,4
la $a0,message
syscall
li $v0,4
la $a0,text
syscall
li,$v0,10
syscall
分支结构(标签跳转)
- 判断是否相等:
.data
message1: .asciiz "Equal\n"
message2: .asciiz "Nothing\n" #允许输入多少字节(字符)
.text
main:
li $v0,5
syscall
move $t0,$v0
li $v0,5
syscall
move $t1,$v0
#addi $t0,5
#addi $t1,20
# compare+
#b Equal #不需要条件直接转到标签上
beq $t0,$t1,Equal #如果相等则跳到Equal标签
bne $t0,$t1,NotEqual #如果不相等则跳到NotEqual标签
li,$v0,10
syscall
NotEqual:
li $v0,4
la $a0,message2
syscall
Equal:
li $v0,4
la $a0,message1
syscall
- 判断两个数的大小:
.data
message1: .asciiz "The number is less than the other\n"
.text
main:
li $v0,5
syscall
move $t0,$v0
li $v0,5
syscall
move $t1,$v0
slt $s0,$t0,$t1 #如果$t0小于$t1,则让$s0为1,否则$s0为零
bne $s0,$zero,Message #判断是否等于零
li,$v0,10
syscall
Message:
li $v0,4
la $a0,message1
syscall
循环结构
.data
message1: .asciiz "Loop ends\n"
line:.asciiz "\n"
.text
main:
addi $t0,$zero,0 #i=0
while:
bgt $t0,10,exit #i>y10时退出循环
jal printNum
addi $t0,$t0,1 #i++
j while #loop
exit:
li $v0,4
la $a0,message1
syscall
li $v0,10
syscall
printNum:
li $v0,1
add $a0,$t0,$zero
syscall
li $v0,4
la $a0,line
syscall
jr $ra