「这是我参与11月更文挑战的第22天,活动详情查看:2021最后一次更文挑战」。
简介
咱们知道x86架构cpu用于PC端和工作站较多,ARM架构cpu常见于手机和单片机,那么MIPS架构的cpu主要在哪些设备可以找到它们的身影呢?
- 中国龙芯
- PS游戏机
学习环境搭建
- 安装JDK, 主要用于运行mips模拟器mars
- MARS模拟器:courses.missouristate.edu/KenVollmar/…
寄存器
在mips中通用寄存器用$开头表示,一共有32个
| 寄存器编号 | 寄存器名 | 寄存器用途 | | :----------: | :------------------------------------------------------------ :|: -----------------------------------------------------------:| | zero | 永远返回0 | | at | 保留寄存器 | | 3 | v1 | 一般用于存储表达式或者函数的返回值(value的简写) | | 7 | a3 | 参数寄存器(Argument简写) | | 15 | t7 | 一般用于存储临时变量(temp简写) | | 23 | s7 | 存放子函数调用过程需要被保留的数据(saved values) | | 25 | t9 | 属性同 t7 | | 27 | k1 | 一般存储中断函数返回值 | | gp | GlobalPointer简写 | | sp | 栈指针,指向栈顶(Stack Pointer简写) | | s8/ 31 | $ra | 一般用于存储函数返回地址(return address简写) |
寄存器编号和别名一一对应,同一个寄存器可以有两种不同表示方法: zero
- program counter (PC) 无法直接修改,通过跳转指令可以改动
- HI 和 LO :这两个寄存器特别用来保存乘法、除法、乘法累加的结果。
MIPS汇编中的分段处理
.data #数据段
.text #代码段
复制代码
传送指令
- 加载立即数指令
li
li
(load immediate) :用于将立即数传送给寄存器
li $t0,1 ;十六进制数据使用0x前缀表示
复制代码
- 加载地址指令
la
la
(load address) :用于将地址传送至寄存器中, 多用于通过地址获取数据段中的地址
.data
msg: .ascii "hello world"
.text
la $a0,msg # 将字符串数据所在的地址赋值给$a0寄存器
复制代码
- 寄存器数据传送指令
move
用于将一个寄存器中的数据传送至另一个寄存器当中
move $t0,$t1 # 将寄存器$t1中的数据传送至$t0
复制代码
系统服务指令 syscall
在C语言中输出文本可以使用printf
函数,但是汇编中没有printf这么一说,如果想要输出文本,需要借助syscall
指令
如果想要输出一个数字1,那么**syscall
指令从$a0寄存器中取出需要输出的数据**
因此, 你在执行syscall
指令之前需要将数据提前放入$a0
之中:
li $a0,1
syscall
复制代码
同时,还需要指定输出的数据类型,数据类型的指定保存在$v0寄存器中
# $v0=1, syscall--->print_int
# $v0=4, syscall--->print_string
复制代码
$v0
存入1,表示syscall
将$a0
中的数据当做数字输出
$v0
存入4,表示syscall
将$a0
中的数据当做数据的地址,然后输出对应的数据
syscall指令读写对照表
Service | Code in $v0 | Arguments | Result |
---|---|---|---|
print integer | 1 | $a0 = integer to print | |
print float | 2 | $f12 = float to print | |
print double | 3 | $f12 = double to print | |
print string | 4 | $a0 = address of null-terminated string to print | |
read integer | 5 | $v0 contains integer read | |
read float | 6 | $f0 contains float read | |
read double | 7 | $f0 contains double read | |
read string | 8 | a1 = maximum number of characters to read | See note below table |
sbrk (allocate heap memory) | 9 | $a0 = number of bytes to allocate | $v0 contains address of allocated memory |
exit (terminate execution) | 10 | ||
print character | 11 | $a0 = character to print | See note below table |
read character | 12 | $v0 contains character read | |
open file | 13 | a1 = flags $a2 = mode | $v0 contains file descriptor (negative if error). See note below table |
read from file | 14 | a1 = address of input buffer $a2 = maximum number of characters to read | $v0 contains number of characters read (0 if end-of-file, negative if error). See note below table |
write to file | 15 | a1 = address of output buffer $a2 = number of characters to write | $v0 contains number of characters written (negative if error). See note below table |
close file | 16 | $a0 = file descriptor | |
exit2 (terminate with value) | 17 | $a0 = termination result | See note below table |
Services 1 through 17 are compatible with the SPIM simulator, other than Open File (13) as described in the Notes below the table. Services 30 and higher are exclusive to MARS. | |||
time (system time) | 30 | a1 = high order 32 bits of system time. See note below table | |
MIDI out | 31 | a1 = duration in milliseconds a3 = volume (0-127) | Generate tone and return immediately. See note below table |
sleep | 32 | $a0 = the length of time to sleep in milliseconds. | Causes the MARS Java thread to sleep for (at least) the specified number of milliseconds. This timing will not be precise, as the Java implementation will add some overhead. |
MIDI out synchronous | 33 | a1 = duration in milliseconds a3 = volume (0-127) | Generate tone and return upon tone completion. See note below table |
print integer in hexadecimal | 34 | $a0 = integer to print | Displayed value is 8 hexadecimal digits, left-padding with zeroes if necessary. |
print integer in binary | 35 | $a0 = integer to print | Displayed value is 32 bits, left-padding with zeroes if necessary. |
print integer as unsigned | 36 | $a0 = integer to print | Displayed as unsigned decimal value. |
(not used) | 37-39 | ||
set seed | 40 | a1 = seed for corresponding pseudorandom number generator. | No values are returned. Sets the seed of the corresponding underlying Java pseudorandom number generator (java.util.Random ). See note below table |
random int | 41 | $a0 = i.d. of pseudorandom number generator (any int). | $a0 contains the next pseudorandom, uniformly distributed int value from this random number generator's sequence. See note below table |
random int range | 42 | a1 = upper bound of range of returned values. | $a0 contains pseudorandom, uniformly distributed int value in the range 0 = [int] [upper bound], drawn from this random number generator's sequence. See note below table |
random float | 43 | $a0 = i.d. of pseudorandom number generator (any int). | $f0 contains the next pseudorandom, uniformly distributed float value in the range 0.0 = f 1.0 from this random number generator's sequence. See note below table |
random double | 44 | $a0 = i.d. of pseudorandom number generator (any int). | $f0 contains the next pseudorandom, uniformly distributed double value in the range 0.0 = f 1.0 from this random number generator's sequence. See note below table |
(not used) | 45-49 | ||
ConfirmDialog | 50 | $a0 = address of null-terminated string that is the message to user | $a0 contains value of user-chosen option 0: Yes 1: No 2: Cancel |
InputDialogInt | 51 | $a0 = address of null-terminated string that is the message to user | a1 contains status value 0: OK status -1: input data cannot be correctly parsed -2: Cancel was chosen -3: OK was chosen but no data had been input into field |
InputDialogFloat | 52 | $a0 = address of null-terminated string that is the message to user | a1 contains status value 0: OK status -1: input data cannot be correctly parsed -2: Cancel was chosen -3: OK was chosen but no data had been input into field |
InputDialogDouble | 53 | $a0 = address of null-terminated string that is the message to user | a1 contains status value 0: OK status -1: input data cannot be correctly parsed -2: Cancel was chosen -3: OK was chosen but no data had been input into field |
InputDialogString | 54 | a1 = address of input buffer $a2 = maximum number of characters to read | See Service 8 note below table $a1 contains status value 0: OK status. Buffer contains the input string. -2: Cancel was chosen. No change to buffer. -3: OK was chosen but no data had been input into field. No change to buffer. -4: length of the input string exceeded the specified maximum. Buffer contains the maximum allowable input string plus a terminating null. |
MessageDialog | 55 | a1 = the type of message to be displayed: 0: error message, indicated by Error icon 1: information message, indicated by Information icon 2: warning message, indicated by Warning icon 3: question message, indicated by Question icon other: plain message (no icon displayed) | N/A |
MessageDialogInt | 56 | a1 = int value to display in string form after the first string | N/A |
MessageDialogFloat | 57 | f12 = float value to display in string form after the first string | N/A |
MessageDialogDouble | 58 | f12 = double value to display in string form after the first string | N/A |
MessageDialogString | 59 | a1 = address of null-terminated string to display after the first string | N/A |
使用syscall指令输出helloworld示例:
.data
msg: .ascii "hello world\0" #类似于C语言中 char* msg="hello world"
.text
la $a0,msg
li $v0,4
syscall
复制代码
Mips汇编指令汇总表
类别 |
指令名称 |
实例 |
含义 |
注释 |
英文注解 |
算 数 |
加法 |
add $s1, $s2, $s3 |
$s1 = $s2 + $s3 | 三个寄存器操作数 |
addition 加法 |
减法 |
sub $s1, $s2, $s3 |
$s1 = $s2 - $s3 | 三个寄存器操作数 |
subtraction 减法 |
|
立即数加法 |
addi $s1, $s2, 20 |
$s1 = $s2 + 20 |
用于加常数数据 |
add immediate 立即加法 |
|
数 据 传 输 |
取字 |
lw $s1, 20 ($s2) |
$s1 = Memory[$s2 + 20] |
将一个字从内存中取到寄存器中 |
load word 加载字 |
存字 |
sw $s1, 20 ($s2) |
Memory[$s2 + 20] = $s1 |
将一个字从寄存器中取到内存中 |
store word 存储字 |
|
取半字 |
lh $s1, 20 ($s2) |
$s1 = Memory[$s2 + 20] |
将半个字从内存中取到寄存器中 |
load halfword 加载半字 |
|
取无符号半字 |
lhu $s1, 20 ($s2) |
$s1 = Memory[$s2 + 20] |
将半个字从内存中取到寄存器中 |
load halfword unsigned |
|
存半字 |
sh $s1, 20 ($s2) |
Memory[$s2 + 20] = $s1 |
将半个字从寄存器中取到内存中 |
stroe halfword 存储半字 |
|
取字节 |
lb $s1, 20 ($s2) |
$s1 = Memory[$s2 + 20] |
将一字节从内存中取到寄存器中 |
load byte |
|
取无符号字节 |
lbu $s1, 20 ($s2) |
$s1 = Memory[$s2 + 20] |
将一字节从内存中取到寄存器中 |
load byte unsigned |
|
存字节 |
sb $s1, 20 ($s2) | Memory[$s2 + 20] = $s1 |
将一字节从寄存器中取到内存中 |
store byte |
|
取链接字 |
ll $s1, 20 ($s2) |
$s1 = Memory[$s2 + 20] |
取字作为原子交换的前半部 |
load linked |
|
存条件字 |
sc $s1, 20 ($s2) |
Memory[$s2 + 20] = $s1; $s1 = 0 or 1 |
存字作为原子交换的后半部分 |
store conditional |
|
取立即数的高位 |
lui $s1, 20 |
$s1 = 20 * 216 |
取立即数并放到高16位 |
load upper immediate |
|
逻 辑 |
与 |
and $s1, $s2, $s3 |
$s1 = $s2 & $s3 | 三个寄存器操作数按位与 |
and |
或 |
or $s1, $s2, $s3 |
$s1 = $s2 | $s3 | 三个寄存器操作数按位或 |
or |
|
或非 |
nor $s1, $s2, $s3 |
$s1 = ~ ($s2 | $s3) | 三个寄存器操作数按位或非 |
not or |
|
立即数与 |
andi $s1, $s2, 20 |
$s1 = $s2 & 20 | 和常数按位与 |
and immediate |
|
立即数或 |
ori $s1, $s2, 20 |
$s1 = $s2 | 20 | 和常数按位或 |
or immediate |
|
逻辑左移 |
sll $s1, $s2, 10 |
$s1 = $s2 << 20 | 根据常数左移相应位 |
set left logical |
|
逻辑右移 |
srl $s1, $s2, 10 |
$s1 = $s2 >> 20 | 根据常数右移相应位 |
set right logical |
|
条 件 分 支 |
相等时跳转 |
beq $s1, $s2, 25 |
if ($s1 == $s2) go to PC + 4 + 25 * 4 |
相等检测: 和PC相关的跳转 |
branch on equal |
不相等时跳转 |
bne $s1, $s2, 25 |
if ($s1 != $s2) go to PC + 4 + 25 * 4 |
不相等检测: 和PC相关的跳转 |
branch on not equal |
|
小于时跳转 |
slt $1, $s2, $3 |
if ($s2 < $s3) $s1 = 1; else $s1 = 0 |
比较是否小于 |
set less than |
|
无符号数比较小时置位 |
sltu $1, $s2, $3 |
if ($s2 < $s3) $s1 = 1; else $s1 = 0 |
比较是否小于无符号数 |
set less than unsigned |
|
无符号数小于立即数时置位 |
slti $1, $s2, 20 |
if ($s2 < 20) $s1 = 1; else $s1 = 0 |
比较是否小于常数 |
set less than immediate |
|
无符号数比较小于无符号立即数时置位 |
sltiu $1, $s2, 20 |
if ($s2 < 20) $s1 = 1; else $s1 = 0 |
比较是否小于无符号常数 |
set less than immediate unsigned |
|
无 条 件 跳 转 |
跳转 |
j 2500 |
go to 2500 * 4 |
跳转到目标地址 |
jump |
跳转至寄存器所指位置 |
jr $ra |
go to $ra |
用于switch语句,以及过程调用 |
jump register |
|
跳转并链接 |
jal 2500 |
$ra = PC + 4; go to 2500 * 4; |
用于过程调用(方法) 正常的执行流程执行完A自然要执行B指令,现在要跳转执行C方法,这时就把B地址存入寄存器中,执行完C后跳转到B |
jump and link |