MIPS汇编语言之常用指令介绍

2,385 阅读5分钟

「这是我参与11月更文挑战的第22天,活动详情查看:2021最后一次更文挑战」。

简介

咱们知道x86架构cpu用于PC端和工作站较多,ARM架构cpu常见于手机和单片机,那么MIPS架构的cpu主要在哪些设备可以找到它们的身影呢?

  • 中国龙芯
  • PS游戏机

学习环境搭建

寄存器

在mips中通用寄存器用$开头表示,一共有32个

寄存器编号寄存器名寄存器用途
$0$zero永远返回0
$1$at保留寄存器
22-3v0v0-v1一般用于存储表达式或者函数的返回值(value的简写)
44-7a0a0-a3参数寄存器(Argument简写)
88-15t0t0-t7一般用于存储临时变量(temp简写)
1616-23s0s0-s7存放子函数调用过程需要被保留的数据(saved values)
2424-25t8t8-t9属性同t0t0-t7
2626-27k0k0-k1一般存储中断函数返回值
$28$gpGlobalPointer简写
$29$sp栈指针,指向栈顶(Stack Pointer简写)
$30s8/s8/fp(Save / Frame Pointer)帧指针
$31$ra一般用于存储函数返回地址(return address简写)

寄存器编号和别名一一对应,同一个寄存器可以有两种不同表示方法:0或者0**或者**zero

  • program counter (PC) 无法直接修改,通过跳转指令可以改动
  • HI 和 LO :这两个寄存器特别用来保存乘法、除法、乘法累加的结果。

MIPS汇编中的分段处理

.data #数据段

.text #代码段

传送指令

  1. 加载立即数指令 li

li(load immediate) :用于将立即数传送给寄存器

li $t0,1  ;十六进制数据使用0x前缀表示
  1. 加载地址指令 la

la(load address) :用于将地址传送至寄存器中, 多用于通过地址获取数据段中的地址

.data 
msg: .ascii "hello world"

.text
la $a0,msg # 将字符串数据所在的地址赋值给$a0寄存器

  1. 寄存器数据传送指令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指令读写对照表

ServiceCode in $v0ArgumentsResult
print integer1$a0 = integer to print
print float2$f12 = float to print
print double3$f12 = double to print
print string4$a0 = address of null-terminated string to print
read integer5$v0 contains integer read
read float6$f0 contains float read
read double7$f0 contains double read
read string8a0=addressofinputbuffera0 = address of input buffer a1 = maximum number of characters to readSee 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 character11$a0 = character to printSee note below table
read character12$v0 contains character read
open file13a0=addressofnullterminatedstringcontainingfilenamea0 = address of null-terminated string containing filename a1 = flags $a2 = mode$v0 contains file descriptor (negative if error). See note below table
read from file14a0=filedescriptora0 = file descriptor 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 file15a0=filedescriptora0 = file descriptor 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 file16$a0 = file descriptor
exit2 (terminate with value)17$a0 = termination resultSee 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)30a0=loworder32bitsofsystemtimea0 = low order 32 bits of system time a1 = high order 32 bits of system time. See note below table
MIDI out31a0=pitch(0127)a0 = pitch (0-127) a1 = duration in milliseconds a2=instrument(0127)a2 = instrument (0-127) a3 = volume (0-127)Generate tone and return immediately. See note below table
sleep32$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 synchronous33a0=pitch(0127)a0 = pitch (0-127) a1 = duration in milliseconds a2=instrument(0127)a2 = instrument (0-127) a3 = volume (0-127)Generate tone and return upon tone completion. See note below table
print integer in hexadecimal34$a0 = integer to printDisplayed value is 8 hexadecimal digits, left-padding with zeroes if necessary.
print integer in binary35$a0 = integer to printDisplayed value is 32 bits, left-padding with zeroes if necessary.
print integer as unsigned36$a0 = integer to printDisplayed as unsigned decimal value.
(not used)37-39
set seed40a0=i.d.ofpseudorandomnumbergenerator(anyint).a0 = i.d. of pseudorandom number generator (any int). 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 int41$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 range42a0=i.d.ofpseudorandomnumbergenerator(anyint).a0 = i.d. of pseudorandom number generator (any int). 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 float43$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 double44$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
ConfirmDialog50$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
InputDialogInt51$a0 = address of null-terminated string that is the message to usera0containsintreada0 contains int read 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
InputDialogFloat52$a0 = address of null-terminated string that is the message to userf0containsfloatreadf0 contains float read 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
InputDialogDouble53$a0 = address of null-terminated string that is the message to userf0containsdoublereadf0 contains double read 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
InputDialogString54a0=addressofnullterminatedstringthatisthemessagetousera0 = address of null-terminated string that is the message to user a1 = address of input buffer $a2 = maximum number of characters to readSee 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.
MessageDialog55a0=addressofnullterminatedstringthatisthemessagetousera0 = address of null-terminated string that is the message to user 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
MessageDialogInt56a0=addressofnullterminatedstringthatisaninformationtypemessagetousera0 = address of null-terminated string that is an information-type message to user a1 = int value to display in string form after the first stringN/A
MessageDialogFloat57a0=addressofnullterminatedstringthatisaninformationtypemessagetousera0 = address of null-terminated string that is an information-type message to user f12 = float value to display in string form after the first stringN/A
MessageDialogDouble58a0=addressofnullterminatedstringthatisaninformationtypemessagetousera0 = address of null-terminated string that is an information-type message to user f12 = double value to display in string form after the first stringN/A
MessageDialogString59a0=addressofnullterminatedstringthatisaninformationtypemessagetousera0 = address of null-terminated string that is an information-type message to user a1 = address of null-terminated string to display after the first stringN/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

Mips内存结构图: