常用的寄存器(32个):
- $\$0(\$zero)$:零寄存器,值恒为 $0$
- $\$1(\$at)$:寄存器 $at$ ,保留给汇编器使用
- $\$2、\$3(\$v_0、\$v_1)$:函数返回值寄存器,调用时不保存
- $\$4-\$7(\$a_0-\$a_3)$:函数参数寄存器,调用时不保存
- $\$8-\$15、\$24-\$25(\$t_0-\$t_9)$:临时寄存器,调用时不保存
- $\$16-\$23(\$s_0-\$s_7)$:保留寄存器,调用过程中必须被保存,保用完毕需要恢复之前值
- $\$26-\$27(\$k_0-\$k_1)$:保留给异常处理函数使用
- $\$28(\$gp)$:全局指针寄存器,调用时需要保存
- $\$29(\$sp)$:栈指针寄存器,调用时需要保存
- $\$30(\$fp)$:帧指针寄存器,调用时需要保存
- $\$31(\$ra)$:返回地址寄存器,调用时需要保存
MIPS 进行算数运算指令的操作数必须来自寄存器
硬件设计的基本原则:
- 简单源于规整
- 越小越快
- 优秀的设计需要适宜的折衷方案
最高有效位指MIPS字中最左边的一位,最低有效位指最右边的一位,因为 MIPS 是 大端编址,即地址低位对应数据高位
对于任意一个二进制数 $x$ 有,$\overline{x}+x+1=0$ ,即 $-x=\overline{x}+1$ ,若 $x$ 是正数, $-x$ 的补码为 $\overline{x}+1$
指令格式
$R$ 型指令:
op rs rt rd shamt funct 6 5 5 5 5 6 $R$ 型指令由 $op$ 和 $funct$ 字段决定指令的功能
$rs,rt$ 指源操作数寄存器
$rd$ 目的操作数寄存器
$shamt$ 位移量
$I$ 型指令:
op rs rt imme 6 5 5 16 $rs$ 基址寄存器
$rt$ 目的寄存器
$imme$ 地址偏移量
$op$ 指令的功能
$J$ 型指令:
op address 6 26 $op$ 指令的功能
$address$ 跳转的地址
计算机基于两个重要的准则构建:
- 指令用数的形式表示
- 和数据一样,程序存储在存储器中,并且可以读写
and 操作和先左移再进行右移都可以将字中的一部分分离出来
基本块:
- 基本块是没有分支(可能出现在末尾者除外),并且没有分支目标/分支标签(可能出现在开始者除外)的指令序列
- 编译最初阶段的任务之一就是将程序分解为若干基本块
疑问
- $C$ 语言中有很多的决策和循环语句,而 $MIPS$ 中却很少,这样的不均衡是因为:
- 更多的决策语句使得代码更容易被阅读和理解(相比于 mips 而言)
- 更少的决策语句简化了负责执行的底层工作
- 更多的决策语句意味着更少的代码量,这节约了编程的时间
- 更多的决策语句意味着更少的代码量,这意味着执行更少的操作
- 注意 $C$ 语言中的 $\&$ 和 $|$ 表示按位的逻辑操作,$\&\&$ 和 $||$ 表示条件分支
过程:根据提供的参数执行一定任务的存储的子程序
过程运行中,程序必须遵守的步骤:
- 将参数放在过程可以访问的位置
- 将控制转交给过程
- 获得过程所需要的存储资源
- 执行需要的任务
- 将结果的值放在调用程序可以访问的位置
- 将控制返回初始点,因为一个过程可能由一个程序中的多个点调用
过程运行所需要的实体:
- 调用者:调用一个过程并为过程提供必要参数值的程序
- 被调用者:根据调用者提供的参数执行一系列存储的指令,然后将控制权返回调用者的过程
- 程序计数器$(PC)$ :包含在程序中正在被执行指令地址的寄存器
在一个过程中,如果需要用到更多的寄存器 (多于4个参数寄存器和2个返回值寄存器),则可能需要使用栈来保护调用过程中的寄存器,例如 $\$t_0-\$t_9$ 属于临时寄存器,可以不必被调用者保存,$\$s_0-\$s_7$ 为保留寄存器,需要被调用者保存,由于可能存在嵌套过程,$ra$ 和参数寄存器也可能需要压栈
全局指针$gp$ :指向静态数据区的保留寄存器
加载 32 位常量(假定高十六位为 a,低十六位为 b)到寄存器 $\$s_0$ 的操作:
$lui \quad \$s_0, \; a$
$ori \quad \$s_0,\; b $
保留寄存器 $\$at$ 通常用来创建长整数值
mips 中的条件分支寻址的形式为 PC 相对寻址,且是相对于 $PC+4$ 而不是当前指令 $PC$ ,并且寻址时的地址是字地址 而不是字节地址
$J$ 型指令的目标地址 $PC_{target}= \lbrace PC[31:28], addr << 4\rbrace$
远距离的分支转移替换:
- $beq \quad \$s_0,\; \$s_1,\; L1$ 可以转换为下述指令:
- $bne \quad \$s_0,\; \$s1, \; L2$
- $j \quad L1$
- $L2:\quad …$
MIPS 寻址模式
- 立即数寻址:操作数是位于指令自身的常数,如 (addi, subi等)
- 寄存器寻址:操作数是寄存器,如 (add, sub等)
- 基址寻址:操作数在内存中,其地址是指令中基址寄存器和常数的和,如 (lw, sw等)
- PC 相对寻址:地址是PC和指令中常数 (左移两位)的和,如 (beq, bne等)
- 伪直接寻址:地址是PC高4位和26位立即数字段 (左移两位)组成
数据竞争:假如来自不同线程的两个访存请求访问同一个地址,他们连续出现,并且至少其中一个是写操作,那么这两个存储访问形成数据竞争
翻译和执行程序的步骤:
- 编译:将高级语言转化为汇编语言
- 汇编:将汇编语言转化为机器语言
- 链接:将多个模块和库程序组合在一起解析所有的引用
- 加载:将可执行程序加载到内存的适当位置