六-体系结构 Architecture
chapter 6 Architecture
MIPS Instruction Set — ECS Networking (pacific.edu)
6.1 Introduction
Four design principles:
-
simplicity favors regularity
-
make the common case fast
-
smaller is faster
-
good design demands good compromises
6.2 Assembly Language 汇编语言
MIPS Architecture - Microprocessor without interlocked piped stages architecture 简单易学,但不太实用
6.2.1 Instructions指令
add a, b, c
add
mnemonic助记符
a
destination operand目标操作数
b,c
source operands操作数
简单设计:simplicity favors regularity
多条指令
a = b + c - d
→add t, b, c sub a, t, d
加速常见情况:make the common case fast
编码长度:
RISC(Reduced instruction set computer)
精简指令集,拥有少量简单的指令
CISC(Complex instruction set computers)
复杂指令集
6.2.2 Operands操作数:Registers, Memory, and Constants
操作数的来源:寄存器/内存
寄存器
MIPS32有32个32位寄存器;比存储器快1000倍
越小越快:Smaller is faster
-
$0 always contains the value 0 because this constant is so frequently used in computer programs.
-
保存寄存器
-
临时变量寄存器
常数-立即数 存储在指令里
存储器-大但是慢
RISC的指令,只能作用在常数/寄存器上;MISC还能直接作用到寄存器中
字寻址存储器:每32位数据字对应一个唯一的32位地址
MIPS实际使用的是字节寻址
6.3 Machine Language机器语言
三种汇编指令
6.3.1 R-Type Instructions 寄存器类型
6.3.2 I-Type Instructions 立即数类型
6.3.3 J-Type Instructions 跳转类型
地址不是32位的吗?j类型里addr是26位的??
6.3.4 Interpreting Machine Language Code
机器→汇编
6.3.5 The Power of the Stored Program 存储程序 - 通用计算能力
6.4 Programming编程
6.4.1 Arithmetic/Logical Instructions 算数/逻辑指令
1 逻辑按位操作:
-
and: 用于掩码操作(Masking)
-
or: 用于组合操作(Combining)
-
nor: 或非,用于反相操作(Inverting)
2 移位指令
3对立即数操作:
- andi, ori, xori 0扩展
间接加载高位立即数: lui
32-bit constants using load upper immediate (lui) and ori:
4伪指令
-
nop: 不对处理器执行产生影响,仅占用一条指令的时间空间,仅将PC推进到下一条指令
-
mv: 在寄存器之间传递数据 mv $s0 $s7 → or $s0 $0 $s7
-
li: 加载立即数到目标寄存器:先判断位数,在决定多条执行指令
5 乘除法:用lo, hi存储结果
-
32*32乘法,得64位结果
mult $s0, $s1
结果保存在{hi, lo}
-
32位除法,得32位商与余数
div $s0, $s1
商保存在lo, 余数保存在hi
-
从lo/hi读数
6.4.2 Branching分支 Execute instructions out of sequence
分支发生:taken;不发生 not taken
Types of branches:
1 Conditional条件分支
branch if equal (beq) beq $s0, $s1, target
branch if not equal (bne)
2 Unconditional无条件分支 → 跳转指令jump
jump (j) 跳转
jump register (jr) 跳转寄存器
jump and link (jal) 跳转和链接
# MIPS assembly
addi $s0, $0, 4 # $s0 = 0 + 4 = 4
addi $s1, $0, 1 # $s1 = 0 + 1 = 1
sll $s1, $s1, 2 # $s1 = 1 << 2 = 4
beq $s0, $s1, target # branch is taken
addi $s1, $s1, 1 # not executed
sub $s1, $s1, $s0 # not executed
target: # label
add $s1, $s1, $s0 # $s1 = 4 + 4 = 8
6.4.3 Conditional Statements 条件
1 if
2 if/else
3 switch/case
6.4.4 Getting Loopy 循环
1 while
2 for
3 量值比较
6.4.5 Arrays 数组
1
搞清楚访问数据的大小
char (2bytes)或 longlong (8bytes)
操作字节:
100000 (32) lb rt, imm(rs) load byte [rt] = SignExt ([Address]7:0)
6.4.6 Function Calls 函数调用
约定:
调用函数caller
将参数传递给被调用者:存在$a0 ~ $a3
中
跳转到被调用者
jal
被调用函数callee
执行函数
返回(结果)到调用者:存在$v0 ~ $v1
中
返回到调用点
不能破坏调用者的寄存器或内存
jr
jal
指令:
-
将下一条指令的地址存储到返回地址寄存器$ra中(存下被调用函数要返回到的调用点)
-
跳转到目标指令
001001 (9) | jal label | jump and link 跳转并链接 | $ra = PC + 4, PC = JTA |
---|
jr
指令:
把rs的内容返回PC,即PC跳到rs存的地址
001000 (8) | jr rs | jump register 跳转到存在rs地址 | PC = [rs] |
---|
int main(){
simple();
...
}
void simple() return;
MIPS assembly code
0x00400200 main: jal simple #调用函数
0x00400204 ...
...
0x00401020 simple: jr $ra #返回
3 栈
但是破坏了调用函数的寄存器,因而要把寄存器原来的值存到内存中,当被调用函数返回后,才能够内存中恢复原来寄存器的值。可以使用后进先出(LIFO)的“栈”数据结构存储临时变量。
栈的扩展与缩小:
栈指针$sp
开始于高内存地址,通过地址递减来扩展栈空间
函数如何使用栈
在函数修改寄存器前,将寄存器保存在栈中,返回前从栈中恢复这些寄存器。
-
创建栈空间
-
存储寄存器
-
使用寄存器执行函数
-
从栈中恢复寄存器原始值
-
回收栈空间
栈帧stack frame:函数为自己分配的栈空间
# $s0 = result, $sp为栈顶
diffofsums:
//栈指针减少 3*4 位,用于存储
addi $sp, $sp, -12 # make space on stack
# to store 3 registers
//保存现场
sw $s0, 8($sp) # save $s0 on stack
sw $t0, 4($sp) # save $t0 on stack
sw $t1, 0($sp) # save $t1 on stack
add $t0, $a0, $a1 # $t0 = f + g
add $t1, $a2, $a3 # $t1 = h + i
sub $s0, $t0, $t1 # result = (f + g) - (h + i)
add $v0, $s0, $0 # put return value in $v0
//恢复现场
lw $t1, 0($sp) # restore $t1 from stack
lw $t0, 4($sp) # restore $t0 from stack
lw $s0, 8($sp) # restore $s0 from stack
//恢复栈,栈平衡
addi $sp, $sp, 12 # deallocate stack space
//清除痕迹!-> 计算机安全
jr $ra # return to caller
下图展示了上述汇编代码执行时栈变化的示意图
4 受/不受保护的寄存器
-
受保护寄存器(preserved):要么被调用函数不修改,若修改,则由被调用函数维护/ 保存(save)
$s0 ~ $s7
存有(调用函数的)局部变量,因此必须被调用函数保存
$ra
存有被调用函数要返回的地址,不能修改
$sp
栈指针,由被调用函数扩展与收缩,被调用函数保存
在$sp
之上的栈空间:其他函数的栈帧,不能修改 -
不受保护寄存器(nonpreserved):由调用函数维护/ 保存(save),可由被调用函数任意修改
$t0 ~ $t9
存放(调用函数的)临时变量,可由被调用函数任意修改,由调用函数保存
$a0 ~ $a3
一般存调用函数要传给被调用函数的参数,一般会由被调用函数修改,由调用函数保存
$v0 ~ $v1
存有被调用函数的返回值,会由callee修改,由调用函数保存
在$sp
之下的栈空间:callee自己分配的空间,有自己修改,由调用函数保存
被调用函数必须保存恢复任何要使用的受保护寄存器,可以随意改变不受保护寄存器。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-xcsFeIDo-1669634365736)(image/image_aG9a8E36K4.png)]
5 递归函数调用
High-level code
int factorial(int n) {
if (n <= 1)
return 1;
else
return (n * factorial(n-1));
}
MIPS assembly code
// $a0
0x90 factorial: addi $sp, $sp, -8 # make room on stack
0x94 sw $a0, 4($sp) # store $a0
0x98 sw $ra, 0($sp) # store $ra
0x9C addi $t0, $0, 2 # $t0 = 2
0xA0 slt $t0, $a0, $t0 # n <= 1 ?
0xA4 beq $t0, $0, else # no: go to else
0xA8 addi $v0, $0, 1 # yes: return 1
0xAC addi $sp, $sp, 8 # restore $sp
0xB0 jr $ra # return
0xB4 else: addi $a0, $a0, -1 # n = n - 1
0xB8 jal factorial # recursive call
0xBC lw $ra, 0($sp) # restore $ra
0xC0 lw $a0, 4($sp) # restore $a0
0xC4 addi $sp, $sp, 8 # restore $sp
0xC8 mul $v0, $a0, $v0 # n * factorial(n-1)
0xCC jr $ra # return
对齐:MIPS不支持跨边界访问
lw
对齐4字节边界
lb
不需要对齐,因为本身就以字节为单位
lh
对齐2字节边界
6.5 Addressing Modes寻址模式
The first three modes (register-only, immediate, and base addressing) define modes of reading and writing operands. The last two (PC-relative and pseudo-direct addressing) define modes of writing the program counter, PC.
1 Register-Only Addressing 寄存器寻址
Register-only addressing uses registers for all source and destination operands. All R-type instructions use register-only addressing.
2 Immediate Addressing 立即数寻址
Immediate addressing uses the 16-bit immediate along with registers asoperands. Some** I-type instructions**, such as add immediate (addi) and load upper immediate (lui), use immediate addressing.
16位有符号数:$ -2^{15} $~ 2 15 − 1 2^{15}-1 215−1
对于大立即数:用伪汇编指令
逻辑运算-零扩展
算数运算-符号扩展
3 Base Addressing 基地址寻址
Memory access instructions, such as load word (lw) and store word (sw),use base addressing. The effective address of the memory operand isfound by adding the base address in register rs to the sign-extended16-bit offset found in the immediate field.
基址+符号扩展的立即数
lw $s4, 72($s0)
地址 = $0 + 72
超大数组寻址:分步处理
4 PC-Relative Addressing PC相对地址
Conditional branch instructions use PC-relative addressing to specify the new value of the PC if the branch is taken. The signed offset in the immediate field is added to the PC to obtain the new PC; hence, the branch destination address is said to be relative to the current PC.
0x10 beq $t0, $0, else
0x14 addi $v0, $0, 1
0x18 addi $sp, $sp, i
0x1C jr $ra
0x20 else: addi $a0, $a0, -1
0x24 jal factorial
若要条很远很远的地方:中间设置跳板
5 Pseudo-Direct Addressing 伪直接寻址
6.6 Compiling, Assembling, and Loading
编译、汇编、加载
6.6.1 The Memory Map 内存映射
1 The Text Segment 代码段
2 The Global Data Segment 全局数据段
3 The Dynamic Data Segment 动态数据段
4 The Reserved Segments 保留段
6.6.2 Translating and Start a Program
转换成二进制代码(可执行文件) 开始执行程序