MIPS架构与汇编语言快速入门 ━ 译自伊利诺大学网页。有内容删减和增加。 原文链接为: http://logos.cs./366/notes/MIPS%20Quick%20Tutorial.htm 译者:Clark J Li 李久 日期:2009/9/5 1. 数据类型 1.1. 数据类型 字节(Byte)为8 Bits; 半字(Half-word) 为16 Bits 即2个字节; 字 (Word) 为32 Bits 即4个字节; 一个字符需要一个Byte的空间; 一个整数需要1个Word(4 Byte)的空间; 1.2. 指令长度 所有的指令都是32 Bits 的长度; 2. 寄存器 MIPS体系架构有32个通用寄存器。在汇编程序中,可以用编号 $0 到 $31来表示; 也可以用寄存器的名字来进行表示, 例如: $sp, $t1, $ra…. 有两个特殊的寄存器 Lo, Hi, 用来保存乘法/除法的运算结果; 堆栈(Stack)的增长方向是: 从内存的高地址方向, 向低地址方向; 寄存器编号 Register Number 寄存器名称 Register Alternative Name 寄存器描述 Description 0 Zero 第0号寄存器,其值始终为0 1 $at (Assembler Temporary) 是Assembler保留的寄存器 2 ~ 3 $v0 ~ $v1 保存表达式或函数返回的结果 4 ~ 7 $a0 ~ $a3 作为函数的前四个入参。在函数调用的过程中不会被保存。 8 ~ 15 $t0 ~ $t7 供汇编程序使用的临时寄存器。 其值在函数调用的过程中不会被保存。 16 ~ 23 $s0 ~ $s7 子函数在使用这类寄存器时, 必须保其初始值, 在子函数退出前, 必须恢复其原来的初始值. 其值在函数调用的过程中会被保存。 24 ~ 25 $t8 ~ $t9 与$t0 ~ $t7的用法相同. 26 ~ 27 $k0 ~ $k1 仅供中断(interrupt/trap)处理函数使用. 28 $gp 全局指针. 29 $sp 堆栈指针, 指向堆栈的栈顶。 30 $s8/$fp 保存的值/帧指针。 其值在函数调用的过程中会被保存。 31 $ra 返回地址 3. 程序结构 汇编源程序代码本质上是文本文件。由数据声明、代码段 两部分组成。 3.1. 数据声明 在源代码中,数据声明部分以 .data开始。声明了在代码中使用的变量的名字。同时,也在RAM中创建了对应的空间。 数据声明的格式: Name: storage_type value(s) 举例: Var1: .word 3 # 创建了一个占1 Word空间的变量, 并赋初值3 3.2. 代码段 在源代码中,以 .text开始。列出了汇编代码。 各个不同功能的代码段,用标签来标识。 3.3. MIPS 汇编程序例子 Example: .data # data declaration var1: .word 23 # declare storage for var1; initial value is 23 .text # Code section __start: # __start is a lable lw $t0, var1 # load contents of RAM location into register # it means $t0 = var1 li $t1, 5 # $t1 = 5 ("load immediate") sw $t1, var1 # store contents of register $t1 into RAM # it means var1 = $t1 done 4. 汇编指令 4.1. Load/Store指令 RAM访问相关 关于RAM的访问只能使用Load/Store指令。 分类 指令格式 注释 Load li register_destination, value 立即数加载。 把value 加载到目标寄存器 lw register_destination, RAM_source 从RAM源地址处 复制一个Word(4 Bytes)到目标寄存器 lb register_destination, RAM_source 从RAM源地址处 复制一个Byte到目标寄存器的低端处 Store sw register_source, RAM_ destination 把源寄存器中的值(4 Bytes)存储到RAM目的地址中 sb register_source, RAM_ destination 把源寄存器的低端1个Byte, 存储到RAM目的地址中 寻址相关指令 分类 指令格式与实例 注释 Load la $t0, val_1 复制val_1表示的地址到t0寄存器中 注: val_1是个Label lw $t2, ($t0) t0寄存器中的值作为地址,把这个地址起始的Word 复制到t2 中 lw $t2, 4($t0) t0寄存器中的值作为地址, 把这个地址再加上偏移量4后 所起始的Word 复制到t2 中 Store sw $t2, ($t0) 把t2寄存器中值(1 Word),存储到t0的值所指向的RAM中 sw $t2, -12($t0) 把t2寄存器中值(1 Word),存储到t0的值再减去偏移量12, 所指向的RAM 中 4.2. 算数运算指令 算数运算指令的所有操作数都是寄存器,不能直接使用RAM地址或间接寻址。 操作数的大小都为 Word (4-Byte) 指令格式与实例 注释 move $t5, $t1 $t5 = $t1; add $t0, $t1, $t2 $t0 = $t1 + $t2; 带符号数相加 sub $t0, $t1, $t2 $t0 = $t1 - $t2; 带符号数相减 addi $t0, $t1, 5 $t0 = $t1 + 5; addu $t0, $t1, $t2 $t0 = $t1 + $t2; 无符号数相加 subu $t0, $t1, $t2 $t0 = $t1 - $t2; 无符号数相减 mult $t3, $t4 $t3 乘以 $t4, 把64-Bits 的积,存储到Lo,Hi中。 即: (Hi, Lo) = $t3 * $t4; div $t5, $t6 Lo = $t5 / $t6 (Lo为商的整数部分) Hi = $t5 mod $t6 (Hi为余数) mfhi $t0 $t0 = Hi mflo $t1 $t1 = Lo 4.3. 分支跳转指令 分支指令 指令格式与实例 注释 b target 无条件的分支跳转,将跳转到target 标签处 beq $t0, $t1, target 如果 $t0 == $t1, 则跳转到target 标签处 blt $t0, $t1, target 如果 $t0 < $t1, 则跳转到target 标签处 ble $t0, $t1, target 如果 $t0 <=$t1, 则跳转到target 标签处 bgt $t0, $t1, target 如果 $t0 > $t1, 则跳转到target 标签处 bge $t0, $t1, target 如果 $t0 >= $t1, 则跳转到target 标签处 bne $t0, $t1, target 如果 $t0 != $t1, 则跳转到target 标签处 跳转指令 指令格式与实例 注释 j target 无条件的跳转, 将跳转到target 标签处 jr $t3 跳转到t3寄存器所指向的地址处(Jump Register) 4.4. 子函数调用指令 指令格式与实例 注释 jal sub_routine_label 执行步骤: 1. 复制当前的PC(Program Counter)到$ra寄存器中。 因为当前的PC 值就是子函数执行完毕后的返回地址。 2. 程序跳转到子程序标签sub_routine_label处。 注:子函数的返回,使用 jr $ra 如果子函数内又调用了其他的子函数,那么$ra的值应该被保存到堆栈中。 因为$ra的值总是对应着当前执行的子函数的返回地址。 |
|