操作码的长度可以变化,也可以是固定的。 扩展操作码技术,不同的地址数的指令(如三地址指令、二地址指令) 可以具有不同的操作码长度。
指令集:一台计算机的全部指令
存储程序:指令和数据都以数字形式存储于存储器中
MIPS体系结构中 寄存器大小为32位,字的大小为32位与寄存器相同。
所有MIPS指令都是32位长。
MIPS是按字节编址的,字的起始地址必是4的倍数。
MIPS采用大端编址。
大端编址和小端编址的字地址都是字的最低字节地址。
目录
指令是由操作码和地址码两部分组成的。
一、引言
1.MIPS操作数:
2.硬件设计的设计原则:
3.常用指令:
4.加速大概率事件的例子:
二、计算机硬件操作
1.计算机硬件的操作数
2.存储器操作数
3.常数或立即数操作数
三、寻址方式
伪直接寻址:
PC相对寻址:
寄存器寻址型:
基址寻址型:
立即数寻址型:
四、指令的表示
指令格式:二进制数 字段 组成的指令表示形式
1.R型MIPS指令(寄存器型):
2.I型MIPS指令(立即数和数据传送指令):
五、决策指令
1.条件分支指令
2.无条件分支指令
3.小于则置位
4.通过以上条件分支和小于则置位得到 小于则分支
六、计算机硬件对过程的支持(函数)
七、内存布局
八、MIPS中的32位立即数
九、分支和跳转中的寻址
跳转指令: jump
条件分支指令:bne,beq
32个寄存器:
$s0---$s7(16~23) 存放变量的寄存器
$t0---$t9 (8~15) 存放临时变量的寄存器
用于过程(函数)中:
$a0---$a3 用于传递参数的4个寄存器
$v0---$v1 用于返回值的两个值寄存器 (val)
$ra 用于返回起始点的返回地址寄存器 (register address,向PC返回调用点的地址)
$zero 存放常数0的寄存器
$gp: 静态数据的全局指针寄存器(reg 28) global pointer for static data (reg 28)
$sp: 堆栈指针寄存器stack pointer (reg 29)
$fp: 帧指针寄存器(frame pointer) ,保存过程帧的第一个字 (reg 30)
存储器字:
保存数据结构、数组 和 溢出的寄存器 数据
add $t0,$s0,$s1; //一条运算指令, $t0、b、c为操作数
①简单源于规整 : 每条指令只能执行一个操作,与加法类似的指令有且仅有三个操作数。
②越小越快 : 寄存器只有32个。
③优秀的设计需要适宜的折中方案:指令长度相同的情况下,不同类型的指令采用不同的指令格式。不同类型指令采用不同的解码方式,但都是32位相同的指令长度,尽可能保持相似的指令格式。
add (加法) : add $t0,$s0,$s1
sub (减法) :sub $t0,$s0,$s1
addi (加立即数):addi $t0,$s0,4
sll (逻辑左移):sll $t0,$s0,2
srl (逻辑右移): srl $t0,$s0,3
bne (不相等则分支):bne $s0,$s1,L1
beq (,相等则分支):beq $s0,$s1,L1
j(无条件跳转):j L1
slt(set on less than 小于则置位):slt $t0,$s0,$s1
slti(立即数版小于则置位):slti $t0,$s0,5
lw(数据传送指令,取数):lw $t0,120($s0) //存入t0
sw(数据传送指令,存数):sw $t0,120($s0) //存入120($s0)
jal(跳转和链接指令):jal fact //跳转到fact位置,并保存当前指令PC+4到$ra中
jr(寄存器跳转指令):jr $ra
lui(读取立即数高位指令):lui $s0,61 //将61的二进制代码放入s0的高六位
①根据使用频率来确定要定义的常数:如将$zero恒置为0
②寄存器约定:传递4个参数、2个寄存器返回结果、保存8个寄存器、10个暂存器对大多数过程调用来说足够使用
③寻址附近的指令:PC+4
————计算机必须能执行算术运算
————每条MIPS算术指令只执行一个操作。编译器将高级程序语言编译成汇编指令。
即 MIPS操作数。
由于MIPS的 算术运算指令只对寄存器进行操作而变量(包括数组的基址,对应成为基址寄存器)存放在寄存器中,数据结构 (如数组和结构)是存放在存储器中的。则必须要 数据传送指令 给出存储器中特定元素的地址进行读取操作(lw),放入临时寄存器%tx 中。(数组元素通过基址寄存器中的地址值和对应偏移量,可以在存储器中找到特定的数据)
————直接将立即数的大小放在算术运算指令中,指令中就携带了该常数的信息。
————对应的指令 为 addi。由于 MIPS 支持负常数,所以 MIPS 中不需要设置减立即数的指令
————将$zero 的值置为0。//可将add变为赋值操作
J型指令寻址方式
beq指令寻址方式
寄存器寻址(直接):在地址码字段直接指出寄存器的编号,操作数在寄存器内。
寄存器间接寻址:在地址码中指出寄存器的编号,寄存器内存储操作数在主存中的地址。
基址(基址寄存器)
立即寻址:指令中带有立即数
————所有MIPS指令都是32位长。
OP的值决定后面的字段分割数
//add 、sub 、and 、sll 、srl
必须有3个寄存器,两个用于运算,一个保存结果
op:操作码 //所有算术运算op是一样的,比如加、减、与、位移(addi与之不一样)
rs:第一个源操作数寄存器
rt:第二个源操作数寄存器
rd:存放结果的目的寄存器
shamt:(shift amount)位移量(不适用时,该字段内容为0)
funct:功能(码) //和op一起决定算术运算具体操作
执行过程:
PC取出指令,放入IR,放入CU对OP和funct译码,同时取出寄存器rs、rt中的值送入ALU,然后对rs和rt执行相应的运算,运算结果放入rd中。
对于逻辑操作:
OP和和其他算术运算一样都是0,但是funct变为0,位移量shamt决定rt的位移位数。
而rs未被利用,置0。
sll $t2,$s0,4 //shift left左移,指令中有三个寄存器,但是只需要用到两个。将$s0中的数据取出后对其左移4位,结果保存至$t2。($s0中数据本身没变)
//addi、lw、sw
当16bits为立即数时:addi
rs:源寄存器
rt:存放结果的目的寄存器
//constant+rs-> rt constant的范围为 -2^15~2^15-1
如: addi $t1,$s0,-300
当16bits为地址时:数据传送指令 lw/sw
rs: 基址寄存器
rt:存放结果的目的寄存器
//address 表示基址偏移量即offset,它的值是地址数值的增值
如: lw $t0,1200($s0)//其中1200表示的是 地址的值增加1200,而不是数组下标!且偏移量必须是常数。
/*若不是常数 如 save[i]设i存放在$s0中 save基址存放在$s1中
sll $t0,$s0,4 //按字节寻址,真实地址值应该加是i*4
add $t1,$s1,$t0 //将save的值+i*4 放入 临时寄存器中
lw $t2,(0)$t1 //根据临时寄存器的基址偏移0找到 save[i]*/
/*lui指令、分支指令的格式和它一样*//
定义:先比较两个值,然后根据比较结果决定是否从程序中的一个新地址开始执行指令序列。
①beq(branch if equal):
如果相等则分支
beq register1,register 2,L1//如果相等则跳转至L1处
②bne(branch if not equal)
如果不相等则分支
bne register 1,register 2,L1//如果不相等则跳转至L1处
j(jump):
无条件跳转
j L1//无条件跳转至L1处
①slt(set on less than)
slt $t0,$s3,$s4 //if s3
②slti (立即数版本)
slti $t0,$s3,4 //if s3<4 then t0=1;
if(a
a存在$s0,b存于$s1
slt $t0,$s0,$s1// s0
bne $zero,$t0,L1 //当zero和t0内容不一样时,跳转至L1处,也就是当t0置1时跳转。
L1:
cout<<1;
过程:根据提供的参数执行一定任务的存储的子程序。
过程运行的6个步骤:
1.将参数放在过程可以访问的寄存器里
2.将控制转移给过程
3.获得过程所需要的存储资源
4.执行过程的操作(请求的任务)
5.将结果的值放在调用程序可以访问到的寄存器
6.将控制返回到调用点
翻译:
调用者调用函数时,先将PC+4的值(调用点下一条指令的值)存入$ra,将参数的值存入$a0~$a3中,将控制转移给过程,运行过程的代码,为获得$s0~$s7寄存器的使用,将原来的数值压栈,若要进行递归调用,$ra和$t0~$t9的值也要压栈保存,然后可以利用寄存器进行过程的操作,得到的结果存入$v0~$v1(它们能被主程序直接访问),弹栈回复原寄存器的值,将$ra的值送入PC,被调用者将控制返回到调用点。
$a0---$a3:用于传递参数的4个寄存器
$v0---$v1:用于返回值的两个值寄存器 (val)
$ra:用于返回起始点的返回地址寄存器 (register address,向PC返回调用点的地址)
跳转和链接指令:
jal ProcedureAddress// jal Func();
跳转,跳转至过程处,链接是将PC+4的值存入$ra
寄存器跳转指令:
jr $ra// 无条件跳转至$ra中程序的指令处。
注:下图并非MISPS体系结构的一部分,而是一种软件规定。
Text(正文):存放指令,PC的高四位为0000
Stack:存放栈,从地址高位开始向下存放。
——根据I型寄存器指令知道,立即数最高只有16位。但有时候需要更大的常数。
读取立即数高位指令lui。
加载32位常数:
lui $s0,61
ori $s0,2304
先将61的二进制代码放入s0的高四位,ori 立即数逻辑或操作把0读到高16位,2304在低16位和s0进行或操作 就得到了61 2304 的二进制代码,即s0中的最终结果:
0000 0000 0011 1101 0000 1001 0000 0000。
跳转指令: jump
该指令过后PC的值为:
PC(31~28):address*4.
PC前四位 31~28 为0000,后28位变化,刚好为文本范围。
address表示的是指令的第几个位置,乘以4表示指令的真实地址。
因为指令地址的低2位都为0。
使得整个address的范围 变成了 28位,实际上真实地址后两位为恒为00,所以address表示的并不是真实地址值,而是地址值的前26位。
条件分支指令:bne,beq
分支寻址形式成为PC相对寻址,是在PC的基础上进行的。它们倾向于转到附近的指令,所以用PC的增值基本上很合适。
该指令过后PC的值为:
PC=PC+address*4
也就是说address本质上表示的是跳转了多少指令,而不是跳转了多少地址值,地址值体现在*4上。如果跳转的是地址值,address的后两位都是00,浪费空间。
注意:当PC取这条指令的时候,PC的值为先增加4。(具体与硬件有关)
所以图中80012的address值为2,表示跳转2个指令,因为此时PC值已经为80016了。
十、C语言转化成可执行文件
C语言程序------>汇编语言程序------>目标模块------>可执行文件:机器语言程序------>存储器
编译器 汇编器 链接器 加载器