赞
踩
如果只是需要看懂MIPS汇编程序的逻辑和内容其实相对简单,只需要对基本的MIPS指令了解、熟悉即可,部分少见的指令临时查看手册或者搜索即可,以下内容为基础的MIPS指令,完成以下内容的学习将可以读懂大部分简单的MIPS程序。
Register Number寄存器编号 | Alternative Name寄存器名 | Description寄存器用途 |
---|---|---|
0 | zero | the value 0永远返回零 |
1 | $at | (assembler temporary) reserved by the assembler汇编保留寄存器(不可做其他用途) |
2-3 | $v0 - $v1 | (values) from expression evaluation and function results(Value简写)存储表达式或者是函数的返回值 |
4-7 | $a0 - $a3 | (arguments) First four parameters for subroutine. Not preserved across procedure calls(Argument简写)存储子程序的前4个参数,在子程序调用过程中释放 |
8-15 | $t0 - $t7 | (temporaries) Caller saved if needed. Subroutines can use w/out saving. Not preserved across procedure calls(Temp简写)临时变量,同上调用时不保存 |
16-23 | $s0 - $s7 | (saved values) - Callee saved. A subroutine using one of these must save original and restore it before exiting. Preserved across procedure calls(Saved or Static简写?)静态变量?调用时保存 |
24-25 | $t8 - $t9 | (temporaries) Caller saved if needed. Subroutines can use w/out saving. These are in addition to $t0 - $t7 above. Not preserved across procedure calls.(Temp简写)算是前面$0$7的一个继续,属性同$t0$t7 |
26-27 | $k0 - $k1 | reserved for use by the interrupt/trap handler(breaK off简写?)中断函数返回值,不可做其他用途 |
28 | $gp | global pointer. Points to the middle of the 64K block of memory in the static data segment.(Global Pointer简写)指向64k(2^16)大小的静态数据块的中间地址(字面上好像就是这个意思,块的中间)* |
29 | $sp | stack pointer *Points to last location on the stack.**(*Stack Pointer简写)栈指针,指向的是栈顶 |
30 | $s8/$fp | saved value / frame pointer Preserved across procedure calls(Saved/Frame Pointer简写)帧指针 |
31 | $ra | return address返回地址,目测也是不可做其他用途 |
同C系语言
MIPS程序的基本模板如下:
# Comment giving name of program and description of function
# 说明下程序的目的和作用(其实和高级语言都差不多了)
# Template.s
#Bare-bones outline of MIPS assembly language program
.data # variable declarations follow this line # 数据变量声明
# ...
.text # instructions follow this line
# 代码段部分
main: # indicates start of code (first instruction to execute) # 主程序
# ...
format for declarations:
声明的格式:
name: storage_type value(s)
变量名:(冒号别少了) 数据类型 变量值
Note: labels always followed by colon ( : )
example
var1: .word 3
#create a single integer variable with initial value 3
#声明一个 word 类型的变量 var1, 同时给其赋值为 3
array1: .byte ‘a’,‘b’
#create a 2-element character array with elements initialized
#to a and b
#声明一个存储2个字符的数组 array1,并赋值 ‘a’, ‘b’
array2: .space 40
#allocate 40 consecutive bytes, with storage uninitialized
#could be used as a 40-element character array, or a
#10-element integer array; a comment should indicate which!
#为变量 array2 分配 40字节(bytes)未使用的连续空间,当然,对于这个变量到底要存放什么类型的值, 最好事先声明注释下!
load:
lw register_destination, RAM_source
#copy word (4 bytes) at source RAM location to destination register.从内存中 复制 RAM_source 的内容到 对应的寄存器中
(1lw中的’w’意为’word’,即该数据大小为4个字节)
lb register_destination, RAM_source
#copy byte at source RAM location to low-order byte of destination register,
# and sign-e.g.tend to higher-order bytes同上, lb 意为 load byte
store word:
sw register_source, RAM_destination
#store word in source register into RAM destination
#将指定寄存器中的数据 写入 到指定的内存中
sb register_source, RAM_destination
#store byte (low-order) in source register into RAM destination
load immediate:
li register_destination, value
#load immediate value into destination register
顾名思义,这里的 li 意为 load immediate
example: .data var1: .word 23 # declare storage for var1; initial value is 23 # 先声明一个 word 型的变量 var1 = 3; .text __start: lw $t0, var1 # load contents of RAM location into register $t0: $t0 = var1 # 令寄存器 $t0 = var1 = 3; li $t1, 5 # $t1 = 5 ("load immediate") # 令寄存器 $t1 = 5; sw $t1, var1 # store contents of register $t1 into RAM: var1 = $t1 # 将var1的值修改为$t1中的值: var1 = $t1 = 5; done
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
load address:
直接给地址
la $t0, var1
indirect addressing:
地址是寄存器的内容(可以理解为指针)
lw $t2, ($t0)
sw $t2, ($t0)
based or indexed addressing:
+偏移量
lw $t2, 4($t0)
sw $t2, -12($t0)
Note: based addressing is especially useful for:
不必多说,要用到偏移量的寻址,基本上使用最多的场景无非两种:数组,栈。
example:栗子: .data array1: .space 12 # declare 12 bytes of storage to hold array of 3 integers # 定义一个 12字节 长度的数组 array1, 容纳 3个整型 .text __start: la $t0, array1 # load base address of array into register $t0 # 让 $t0 = 数组首地址 li $t1, 5 # $t1 = 5 ("load immediate") sw $t1, ($t0) # first array element set to 5; indirect # addressing 对于数组第一个元素赋值 array[0] = $1 = 5 li $t1, 13 # $t1 = 13 sw $t1, 4($t0) # second array element set to 13 # 对于 数组第二个元素赋值 array[1] = $1 = 13 # (该数组中每个元素地址相距长度就是自身数据类型长度, #即4字节, 所以对于array+4就是array[1]) li $t1, -7 # $t1 = -7 sw $t1, 8($t0) # third array element set to -7 # 同上, array+8 = (address[array[0])+4)+ 4 = # address(array[1]) + 4 = address(array[2]) done
add $t0,$t1,$t2
# $t0 = $t1 + $t2;
# add as signed (2’s complement) integers
sub $t2,$t3,$t4 # $t2 = $t3 Ð $t4 addi $t2,$t3, 5 # $t2 = $t3 + 5; "add immediate" (no sub immediate) addu $t1,$t6,$t7 # $t1 = $t6 + $t7; add as unsigned integers subu $t1,$t6,$t7 # $t1 = $t6 + $t7; subtract as unsigned integers mult $t3,$t4 # multiply 32-bit quantities in $t3 and $t4, and store 64-bit # result in special registers Lo and Hi: (Hi,Lo)= $t3*$t4 # 运算结果存储在hi,lo(hi高位数据, lo地位数据) div $t5,$t6 # Lo = $t5 / $t6 (integer quotient) # Hi = $t5 mod $t6 (remainder) # 商数存放在 lo, 余数存放在 hi mfhi $t0 # move quantity in special register Hi to $t0: $t0 = Hi # 不能直接获取hi或lo中的值,需要mfhi, mflo指令传值给寄存器 mflo $t1 # move quantity in special register Lo to $t1: $t1 = Lo # used to get at result of product or quotient move $t2,$t3 # $t2 = $t3
jarl 使用寄存器的跳转指令,并且带有链接功能,指令的跳转地址在寄存器中,跳转发生时指令的放回地址放在R31这个寄存器中
BENZ R1,NAME R1不等于0,程序跳转以NAME为偏移地址,否则,执行下一条指令
BEQZ R1,NAME R1=0,程序跳转到以NAME为偏移地址,否则,执行下一条指令
前面框架部分转载修改优秀的参考文章:https://www.cnblogs.com/thoupin/p/4018455.html
https://blog.csdn.net/qq_41191281/article/details/85933985#1.%E6%8C%87%E4%BB%A4%E6%A0%BC%E5%BC%8F
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。