本次笔记内容:
25.MIPS汇编初步-1
26.MIPS汇编初步-2
27.MIPS指令集与汇编程序设计
注:我找到了对应内容的课件,请见我于GitHub的CS笔记仓库。因此,为了节省时间,我只记录老师上课强调的内容与对应ppt页码。
本节课对应幻灯片:汇编语言程式设计-MIPS.pdf,第1页起。
本节课回到了张悠慧老师授课!
文章目录
- MIPS的由来与发展(最经典的RISC架构)
- MIPS32体系结构(系统程序员可见的部分)
- 指令集特点(与X86指令集对比)
- 程序员可见的流水线效果
- 简单总结
- MIPS汇编指令初步
- 访存指令
- 寄存器
- MIPS32寄存器命名与使用惯例
- 传统的MIPS32传递过程参数方式
- MIPS32体系结构下C过程的栈帧layout示意图
- 整数乘法与寄存器
- 程序地址空间布局
- 协处理器0:CP0
- CP0寄存器部分汇总
- CP0示例
- 参考书与工具书介绍
- MIPS32指令集
- 指令分类
- CLO CLZ
- 乘法
MIPS的由来与发展(最经典的RISC架构)
Microprocessor without Interlocked Pipeline
Stages (Millions of Instructions Per Second
的双关语)
尽量利用软件办法
避免流水线中的数据相关问题
1981年,斯坦福大学教授Hennessy领导团队,设计出第一个MIPS架构的处理器。
但是市场上, MIPS不是很火。MIPS已被被ARM收购:实际上,零零年代,MIPS与ARM在嵌入式/移动端/非x86领域是可以分庭抗礼的。
张老师当初也参与过“清华芯”的开发(基于MIPS),当然他们也是找教材、从官网下载"Soft Manual"来看、来学。
最后,把 Linux for MIPS、gcc for MIPS 输入板子,来调,让其工作。
当时遇到一个问题,显卡不工作:
- 显卡的信息是不公开的,显卡初始化代码无从得知;
- 板子要去执行显卡初始化代码,但是显卡是为x86写的,MIPS无法执行;
- 最后查资料,找无需x86的显卡,找到了 MATROX 显卡(2003~2004),当时已经不产个人显卡了,老师去 ebay 淘到了一些。
1984年, Hennessy教授离开斯坦福大学,创立MIPS科技公司。
- 于1985年,设计出R2000芯片,1988年,将其改进为R3000芯片, 1991年:R4000。
- 陆续推出R8000(于1994年)、R10000(于1996年)和R12000(于1997年)等型号。
- 后重点转向嵌入式领域——2000年,MIPS公司发布了针对MIPS32 4Kc的版本以及64位MIPS 64 20Kc处理器内核。
MIPS处理器是八十年代中期RISC CPU设计的一大热点:
- 在许多领域,如Sony, Nintendo的游戏机,Cisco的路由器和SGI超级计算机中使用。
索尼、任天堂的游戏机,有一段时间都是用 MIPS 。但是由于市场惯性,终究打不过 Intel 等厂家。
通用处理器指令体系历经MIPS I、MIPS II、MIPS III、MIPS IV到MIPS V的发展;嵌入式指令体系历经MIPS16、MIPS32到MIPS64的发展,已经十分成熟。
在设计理念上MIPS强调软硬件协同提高性能
,同时简化硬件设计
。
中国的龙芯
采用的是MIPS指令架构。申请了三个专利:
- MIPS的大小端是可以换的;
- 设计了两套指令,无需对齐操作数;
- 将 BLOCK 移至位前。
MIPS32体系结构(系统程序员可见的部分)
指令集特点(与X86指令集对比)
但是 MIPS 指令里编码常数的话,其长度是受限的。
续表如上。
对于 MIPS ,专门设有 31 寄存器保存过程调用。
程序员可见的流水线效果
Branch Delay Slot (跳转延迟):
- 条件跳转指令的目标地址计算需要在ALU段获得,而此时第二条指令已经进入流水线,存在一个延迟槽(delay slot)
- 需要程序员或编译器优化来填充这个slot
MIPS把应该由硬件做的事交给软件去做。
而现在的处理器已经不把加载延迟暴露出来了,这张不讲。
简单总结
- RISC的设计思想在于简化计算机指令功能、规格化指令设计,使得各个指令的流水线分段较为均匀,且操作相对简单规整,从而提高主频。
- 采用Load/Store结构:其它指令均在寄存器之间对数据进行处理,提高处理速度。
- 依赖软件(编译)实现优化及完成复杂功能。
MIPS汇编指令初步
如上,示例2中,move
这条指令位于 decay slot ,与上一条 jal
指令是一体的。执行完了才过去。
访存指令
lw $1, offset($2)
,任何寄存器都可以作为地址或者目标寄存器;offset 为16位的带符号整数。
寄存器
使用32个通用寄存器
- 0号寄存器的值永远是0
- 31号寄存器存放函数调用的返回地址(JAL指令)
- 其它寄存器都是“一样”的
- 没有指令寄存器(如x86-32中的eip)
?整数乘除法的专用寄存器:
- Hi / Lo
32个浮点寄存器(如果有浮点协处理器的话)
MIPS32寄存器命名与使用惯例
如果立即数比较长,那么汇编器自动把一条指令拆成两条指令,此时要用到 1 号寄存器。因此编程时不要人为使用。
MIPS没有栈,但是在软件编辑时,我们逻辑上是有栈的;习惯上用 SP 指向栈顶。
传统的MIPS32传递过程参数方式
MIPS32体系结构下C过程的栈帧layout示意图
整数乘法与寄存器
使用了专用的乘法部件(不是主流水线的一部分),? 两个32位数相乘得到64位结果:Hi / Lo寄存器:
- mfhi mflo ,mthi mtlo 用途?Hi / Lo 本身不做运算,将其保存到寄存器中,两条指令分别是
move from hi
,move from lo
。 - 也可存放除法结果:商(Lo)与余数(Hi)
乘除操作不产生异常,需要编译器判断
- 除0不会产生异常
程序地址空间布局
如上,用户只能访问2GB空间,高2GB空间用户没有权限访问,那里是给核心态用的。
任何的处理器地址的访问(包括指令与数据)都需要经过存储管理单元(MMU)的地址转换:
- 即“程序地址(或称虚拟地址)”转换为“物理地址”;也有一些嵌入式处理器没有MMU,但是一般也经过地址转换。
用户态\核心态\调试态*:
- 用户态下某些指令是非法的,且访存地址有限(最高位为0)
- 核心态下可以做任何事,访问任意空间
定义:
- kuseg 用户态可以使用的地址,需经过MMU转换
- kseg0 最高位清零后就是物理地址
经过缓存
- kseg1 最高三位清零后就是物理地址
不经过缓存
启动后期可使用,系统的启动地址就在这段
- kseg2 核心态使用,需经过MMU转换
协处理器0:CP0
支持虚拟存储、异常处理、运行状态切换等的系统控制协处理器。
- 从程序员的角度来看,就是一系列寄存器
-
- 指令:MFC0 MTC0
-
- 不能在用户态下访问
- 与下列处理功能密切相关:
- 处理器运行模式,如大小端模式、当前运行态等;
- 缓存控制
- 异常/中断处理
- 存储管理(MMU)
- 其它。。。。。。
CP0寄存器部分汇总
CP0示例
BD用于判断:
- 发生异常的指令,是否位于 delay slot 中;
- 如果位于,需要跳到其之前的转移指令中。
参考书与工具书介绍
See MIPS Run
这本书很好,但是太复杂了。
Assemblers, Linkers, and the SPIM Simulator
可以当作操作手册用,只有20多页。
现在没有 MIPS 机器了,你可以下载一个 MIPS 模拟器 SPIM
。
**MIPS32? Architecture … **
可以看 MIPS32 指令集,官网。相当于指令字典。
MIPS32 4K? Processor Core Family Software User’s Manual
这个很深。
MIPS32指令集
以经典的嵌入式处理器MIPS 4kc
系列为参照。
指令分类
主要观察与 x86 的不同之处。注意,MIPS中的ADD
处理带符号整数
。
CLO CLZ
MIPS中计算前导 0/1 个数,而x86是记录扫到的第一个 0/1 的位置。