408 计组笔记
指令系统 基础知识 指令一般由 操作码op、寻址特征C、地址码A 组成 根据地址数的个数,一般分为 零、一、二、三地址指令
- ISA 规定了:数据类型及格式、指令格式、寻址方式和可访问地址空间大小、I/O 空间的编址方式、中断
结构、机器的工作状态定义和切换、输入输出结构和数据传送方式、存储保护方式等
- ISA 指的是软件可以感知的部分,称为软件可见部分
- 而指令具体在硬件上如何执行的,称为微体系结构、微架构,这是软件不可感知的,例如如何实现加法器
- 综上,不同微架构的机器可以使用相同的 ISA
定长操作码指令 操作码为固定位数 n 位,那么可以支持的指令个数只有
- 短op 不能是 长op 的前缀
- op 不能重复
- 一般频率较高的指令分配短 op,依次减少译码时间 做题策略:
- 从短 op 开始讨论,短 op 尽可能分配,但要留出 n 种用来扩展
- 如果是给了四地址,二地址,判断三地址的最多的个数:需要注意三地址码(短op)不能占据二地址码(长op)的,但是反过来可以,所以有可能出现指令操作码不完全分配干净情况。
- 例1:在一个指令系统中,指令字长为32,一个地址码为6位,指令分为4地址指令、3 地址指令和2地址指令,已知4地址指令有 254条,2地址指令有 4097条,则3地址指令至多有多少条?
- 法一:四地址留出了 10 和 11 用来扩展,这里2地址 op 有 20 位,高八位先用 1111 1111,后十二位全可以分配,共 4096 个,还有一个可以占据三地址的 10,所以再分配一个 1111 1110 | 1111 1111 1111,而三地址则高八位固定只能是 1111 1110,其还剩 6 位 op,只能是 000 000 ~ 111 110
- 法二:首先四地址留出了两个来扩展,所以三地址一共只有
种,但需要留出一部分给二地址;因为二地址要 4097 个,一共 20 位 op,其专属第三个字段部分可以有
种,所以前十二位的部分还得占用至少
向上取整为 65 种,故 128 - 65 = 63 个 - 例2:在一个指令系统中,指令字长为 32,一个地址码为 6 位,指令分为 4 地址指令、3 地址指令和 2地址指令,已知 4地址指令有 254 条,2 地址指令有 4095 条,则 3 地址指令至多有多少条?
- 法一:四地址留出了 10 和 11 用来扩展,这里2地址 op 有 20 位,高八位先用 1111 1111,后十二位全可以分配,共 4096 个,只需要 4095 个,多出来的一个三地址无法使用。而三地址则高八位固定是 1111 1110,其还剩 6 位 op 任意分配共
个 - 法二:首先四地址留出了两个来扩展,所以三地址一共只有
种,但需要留出一部分给二地址;因为二地址要 4095 个,一共 20 位 op,其专属第三个字段部分可以有
种,所以前十二位的部分还得占用至少
向上取整为 64 种,故 128 - 64 = 64 个 寻址方式 立即寻址 - 地址码为 立即数
- 获取操作数访存次数:0 直接寻址
- 地址码为 有效地址
- 获取操作数访存次数:1 寄存器寻址
- 地址码为 寄存器编号
- 获取操作数访存次数:0,由寄存器给出 间接寻址
- 地址码为 有效地址的地址(假设一次间接)
- 获取操作数访存次数:2
- 将操作码指向的内存中的数据传到 MAR,再进行访存,得到操作数,一共两次 寄存器间接寻址
- 地址码为 寄存器编号
- 获取操作数访存次数:1
- 从寄存器中获取有效地址,再访存得到操作数,共 1 次 基址寻址
- 地址码为 偏移量,为补码形式
- 有效地址 = 偏移地址 + 基址寄存器的值
- 面向 OS:基址寄存器只能由 OS(内核态)修改,可以实现动态重定位,有利于多道程序与程序浮动
- 一般分为有基址寄存器和无基址寄存器,如无,则可以在指令中加上一个寄存器编号 变址寻址
- 地址码为 基准地址,例如数组首地址,而偏移量由变址寄存器给出
- 有效地址 = 基准地址 + 变址寄存器的值
- 面向用户:这里的基准地址可以由用户(用户态)修改,便于实现线性表的遍历
- 变址寄存器可以由通用寄存器实现,也可以是专门的变址寄存器,存了偏移量(数组下标) [图片] 相对寻址
- 地址码为 偏移量,可正可负为补码形式
- 有效地址 = (PC) + 偏移量
- 注意这里的 PC 再取指后可能会加 “1”,具体看题目,且 PC 其指向了指令在内存中的首地址,且 + 1 的单位为一个指令字长
- 尤其是根据 jmp 计算相对寻址的偏移量,勿忘此时 PC 已经指向了下一条指令,所以偏移量得多个 2
- 例如:指令字长为 4B,1 字为 1 B,则向前跳 16 个指令下,新的地址 addr = PC + 1 * 4 - 16 * 4 = PC + (1 - 16) * 4
- 注意这里的 PC 再取指后可能会加 “1”,具体看题目,且 PC 其指向了指令在内存中的首地址,且 + 1 的单位为一个指令字长
- 常用于转移指令 jmp A
- 便于实现相对转移以及程序的浮动 指令设计风格 RISC vs. CISC
- 408 中:
- 出现:指令流水线、load / store,一定是 RISC
- 出现:采用微程序控制,一定是 CISC [图片] MIPS 指令 MIPS 为 RISC 风格的,采用 32 位定长指令字,32 位机器字长,故所有寄存器也为 32 位。操作码字段也是固定的长度,无专门的寻址方式字段。 访存指令只有 load 和 store 寄存器 MIPS 提供了 32 个寄存器,故一般寄存器编号占 5 bit [图片]
- a0 - a3:存非浮点数的调用入口参数。A 先存入 a 中再调用 B,若参数 > 4 个,则其余存入栈中。若 A 在 B 返回后也要使用 a,则 A 自己保存。
- v0 - v1:存从 B 返回的非浮点数的返回值。B 返回前先将返回值存入 v,再返回
- ra:存返回地址;A 调用 B 时通过 jal 自动将返回地址 PC + 4 存入 ra 寄存器;B 返回 A 时通过 jr ra 将 ra 寄存器中的值存入 PC
- s0 - s7:称为保存寄存器(被调用者保存),若里面 B 过程中需要使用 s,则在开始段中先将其存入栈,并在返回前恢复,其值回到 A 后仍能被继续使用
- t0 - t9:称为临时寄存器(调用者保存),若 t 中的值在 B 返回后 A 仍需使用,则 A 自己保存。其值无需由被调用者 B 保存,自由使用即可 [图片]
- R 型指令 [图片] R 型指令限定为寄存器之间操作的指令,rs、rt 为两个来源寄存器编号,rd 为目标寄存器编号;op 字段固定为 000 000,具体操作类型由 func 字段指明;shamt 为位移指令的位移字段
- 由于 R 型指令 op 固定为 000 000,所以 I 型 J 型指令一共只有 63 种操作码
- I 型指令 [图片] I 型指令是立即数指令,一般分为下面几种
- 双目运算类:rs + 立即数 —> rt
- load / store:寄存器在左边,内存在右边
- load:rt <— M[rs + 立即数]
- store:rt —> M[rs + 立即数]
- 条件转移(相对寻址):if (rs ? rt) PC <— (PC + imm)
- J 型指令 [图片] 常用指令 [图片] [图片]
- 赋值给寄存器:总是给最左边的
- 和主存交互,左边的是寄存器部分,右边的是主存部分 MIPS 的过程调用 过层调用,又称 函数调用、子程序调用。
- ra:存返回地址(在 jal 指令中会先 ra = PC + 4 再 jump)
- fp:存当前函数栈的栈桢(栈底),其指向的存储单元一般保存了返回地址 MIPS 所有寄存器均为 32 位长度,存储单元大小也为 4B,其地址 A,表示的是字节为 (A, A+1, A+2, A+3) 的存储单元,例如:fp 中存了 48,则表示(48,49,50,51)这个存储单元 【过程调用流程】假设函数 A,调用函数 B
- 寄存器:
- 保存寄存器 s0 - s7,如果从被调用过程返回后 A 还要用,被调用者 B 需要保存
- 临时寄存器 t0 - t9 ,其值在被调用过程返回后不需要被用。如果需要的话,由调用者 A 提前保存
- ra 寄存器,存了当前有用控制权的函数执行完后的返回地址
- fp 寄存器,存了当前函数的栈桢(一般保存了被调用者 B 执行完后的返回地址)
- A 调用 B 之前,先将 B 需要的参数保存进指定地方(如:a0、a1 寄存器)
- A 执行 jal,包括了保存 ra = PC + 4 以及 控制转移到 B 函数
- 被调用者 B 开始段:
- 计算并分配空间 sp - xxxx
- 先保存 A 的现场(A 的 ra,A 的 fp 共 8 B)
- 保存 保存寄存器 s0 - s7(有需要的话)
- 以 main 函数调用 set_array 函数为例,需要按顺序执行:
- 先计算需要分配的空间,并减小 sp,腾出空间
- 保存 ra(main 函数中 jal set_array 的下一条指令位置)
- 保存 main 的 fp,并设置 fp 寄存器为 set_array 的栈桢(其指向了上面刚保存的 main 的 ra)
- 保存 s1,并将要用的局部变量 数组 address 的首地址存入 s1 [图片]
- 执行过程 B
- 被调用者 B 将返回结果放到指定位置,例如:寄存器 v0 - v1
- 执行 exit 函数返回 A
- 将栈底的 ra 存入 ra 寄存器
- 将栈底的 fp 存入 fp
- 将栈底的 s1 存入 s1
- 释放分配的空间 sp + xxxx
- 函数返回:PC <— (ra)
Last Updated: 7/29/2024, 12:27:36 AM