指令:计算机硬件所能理解并服从的命令。
存储程序概念:多种类型的指令和数据均以数字形式存储于存储器中的概念。
字:计算机中的基本访问单位,通常是32位为一组,在MIPS体系结构中与寄存器大小相同。
数据传送指令:在存储器和寄存器之间移动数据的命令
地址:用于在存储器空间中指明某特定数据元素位置的值
对齐限制:数据地址与存储器的自然边界对齐的要求
程序计数器(PC):包含在程序中正在被执行指令地址的寄存器
基本块:没有分支(可能出现在末尾者除外)并且没有分支目标/分支标签(可能出现在开始者除外)的指令序列
1个字= 个字
MIPS指令集:
①按字节编址。 一个字4个字节,一个字节8bit。
②寄存器大小为32位
③地址值为32位
④采用大端编址
数据的低位保存在内存的高地址中,而数据的高位,保存在内存的低地址中
R型指令:
rd是目的寄存器
如:算术运算指令、逻辑操作
补码运算
add、sub、sll(逻辑左移)、and、or、slt(set on less than 小于则置位)
add $t0,$s0,$s1//$t0是目的寄存器
sub $t0,$s0,$s1//$t0是目的寄存器
sll $t0,$s0,4 //$t0是目的寄存器
and $t0,$t1,$t2//$t0是目的寄存器
slt $t0,$s3,$s4 //$t0是目的寄存器
I型指令:
rt是目的寄存器
立即数指令(addi)、数据传送指令(lw、sw):
注意16位立即数为有符号补码,进行计算时需要先进行符号扩展,此指令认为寄存器内的数据也为补码形式。由于这里是有符号数,所以没有subi指令.
决策指令(beq、bne):
PC相对寻址,这里的地址为字地址,需要将16位地址乘以4,得到18位的字节地址,再进行相加。这里同样是有符号数的补码形式,需要进行符号扩展。并且相对偏移的对象为PC+4
立即数逻辑操作指令(ori、andi)、取立即数高位指令(lui):
逻辑操作的立即数是通过变成32位数的低十六位,而高十六位补0形成的“无符号数”进行运算的;lui指令是直接把constant字段放入寄存器的高十六位,低十六位补0
lw $t0,23($s0) //$t0是目的寄存器
sw $t0,43($s0) //$t0是目的寄存器
beq $t0,$t1,L1//$t0和$t1地位等价
bne $t0,$t1,L1//$t0和$t1地位等价
addi $s3,$s0,4 //$s3是目的寄存器
J型指令:
无条件跳转 jump指令
PC+4的高四位与 Jump指令的立即数*4 的28位进行拼接。
基址寄存器:
g=h+A[8] ,其中变量h的值存放在$s2中,变量g的值存放在$s1中
编译为:
lw $t0,32($s3)
add $s1,$s2,$t0
$s3存放数组的首地址,即$s3为基址寄存器,32位偏移量,认为该数组的每个元素的大小为一个字,所以偏移量为8*4。
符号扩展:
需要符号扩展的是需要进行运算的立即数,如beq,lw,sw,addi他们的立即数都需要进行加法运算,beq的立即数需要与PC+4相加,lw和sw的立即数是需要与基址寄存器的地址相加,addi的立即数需要与指令中的源寄存器相加,这些都需要将立即数看作有符号数进行符号扩展再运算。
而对于lui,ori,jump不直接进行加法运算的 就不需考虑符号扩展。
例:
某条addi的机器码为:
0010 00 01 001 1 0011 1011 0000 0010 0000
若寄存器编号和寄存器数据值相同,则此指令为:
addi $19,$9,(1011000000100000)B
所以运算结果应该为:
0000 0000 0000 0000 0000 0000 0000 1001
+
1111 1111 1111 1111 1011 0000 0010 0000(有符号数16位符号扩展为32位)
=
1111 1111 1111 1111 1011 0000 0010 1001
此结果存入$19中
PC相对寻址:
beq $t2,$t0,10 ; 假设此时PC中的值为01000000H
则目标地址为:
(H表示16进制,D表示十进制)
即0 100002C H
无条件跳转:
Jump 10; 跳转到10*4=40D=28H
目标地址为:
0 0000028H
↑
PC高四位bit
32位立即数:
lui指令(读取立即数高位指令)+ori指令(立即数或)
lui指令将16位立即数常数放到寄存器高16位,低16位填充0
ori指令将16位立即数常数放到寄存器低16位,高16位填充0
立即数:
在逻辑操作中:立即数与、立即数或的16位立即数是高16位补0形成32位进行与或运算(相当于无符号数) 如ori;
在加法下:立即数进行符号扩展,再运算 如addi;
远距离分支:
实现其他跳转
为什么lw和sw的地址是字节地址(不乘以4),而beq和jump是字地址(偏移量*4)?
因为beq和jump都是程序计数器的跳转,是存放指令地址的,而指令是32位的,一条指令4个字节,所以指令的存储都是以4个字节为单位的,所以只需要字地址就可以找到一条指令。但是数据不一定是4个字节的,比如C语言中char类型是一个字节的,这样的话,为了使得lw和sw能取到具体的数据,需要具体到字节地址。
①简单源于规整 :
所有指令长度统一、算术指令总是需要三个寄存器操作数、寄存器字段在每种指令格式的位置相同②越小越快 :
寄存器只有32个。
③优秀的设计需要适宜的折中方案:
指令长度相同的情况下,不同类型的指令采用不同的指令格式。
不同类型指令采用不同的解码方式,但都是32位相同的指令长度,尽可能保持相似的指令格式。
一个 MIPS 例子是在指令中提供更大地址与常数,并且保持所有的指令具有相同的长度之间的折中。
寄存器寻址:操作数在寄存器中,如add
立即数寻址:操作数在指令的立即数字段,如addi
基址寻址:操作数在基址寄存器中,如lw,sw
PC相对寻址:PC作为操作数,如beq
伪直接寻址:无条件的跳转 jump
$gp的范围为1000 0000H 到 1000 ffffH (遍历十六进制低4位)
过程运行的6个步骤:
1.将参数放在过程可以访问的寄存器里
2.将控制转移给过程
3.获得过程所需要的存储资源
4.执行过程的操作(请求的任务)
5.将结果的值放在调用程序可以访问到的寄存器
6.将控制返回到调用点
跳转和链接指令:
jal ProcedureAddress// jal Func();
跳转,跳转至过程处,链接是将PC+4的值存入$ra
寄存器跳转指令:
jr $ra// 无条件跳转至$ra中程序的指令处。
记忆。
A
①简单源于规整 ②越小越快 ③优秀的设计需要适宜折中的方案
B
×。
遍历十六进制的低4位,所以访问空间是1000 0000~1000 ffff H