一、指令格式
1、R格式中各字段数值的含义
例:add $8,$9,$10
想要把它表示位字的形式,则根据字段的划分,每个字段的值分别如下:
opcode=0 (参见附录) funct=32(参见附录) rd=8(目的)
rs=9(首操作数) rt=10(次操作数) shamt=0(非位移)
则字段的十进制数表示为:
转化成二进制表示为:
转化为十六进制表示为:012A4020(hex);转化成十进制表示为:19546144(ten),他们都称为机器语言指令
为什么R格式由两个6位字段来确定命令,而不是一个12位字段?
答:为了尽量与其他格式兼容,同时让立即数字段由更大的存储空间
2、I格式中各字段数值的含义
例:addi $21,$22,$-50
想要把它表示为字的形式,则根据字段的划分,每个字段的值分别如下:
opcode(参见附录) rs=22(包括源操作数的寄存器)
rt(结果寄存器) immediate=-50(缺省情况,这是十进制数)
则每个字段的十进制数表示为:
各字段的二进制表示为:
转化成十六进制表示为:22D5 FFCE(hex);转化成十进制表示为:584449998(ten),他们都称为机器语言指令
16位可以最多表示
个不同的值,这对于处理普通的lw和sw的偏移量来说是足够大,另外对于大多数slti指令中要使用的值也是可以的,但是数实在太大,如何处理呢?
如果需要一种办法来处理任意I格式所有32位立即数,这就需要增加新指令:lui register,immediate;
lui(Load Upper Immediate)表示装入立即数高位,即取立即数的高16位,并讲这些位放到指定寄存器的上半部(高位部分),而设置低半部分为0.
具体实现:
例如指令:addi $t0,$t0,0xABABCDCD
可改为:
lui $at,0xABAB
ori $at,$at,0x,CDCD
add $t0,$t0,$at
因此I格式指令仅取16位立即数
3、分支:PC相对寻址
由于立即数immediate仅有16位,而PCProgram Counter)保存当前要执行指令的字节地址,指向内存的32位指针,因此immediate无法指定整个跳转的地址。
解决方案:
PC相对寻址:令16位立即数字段为用补码表示的有符号数,在分支时,将其加上PC值得到要去的地址。那么,可以以PC为基点,分支字节,这对大多数
循环来说以及足够。
进一步优化:
指令是以字的形式存放的,因此是字对齐的(字节地址总是4的倍数,即2进制形式表示时,最后两位总是00)因此,加到PC上的字节数永远是4的倍数。如果把末尾的
00暂时忽略(使用时再补上),则以PC为节点可以分支个字节,这样可以处理的循环范围扩大为原来的4倍
如果进行分支:
PC=(PC+4)+(immediate*4)
其中,immediate字段指定跳转的字数,即要跳转多少条指令。immediate字段可正可负。由于硬件的原因,立即数是加到(PC+4)上,而不是加到PC。
例:
Loop: beq $9,$0,End add $8,$8,$10 addi $9,$8,$10 addi $9,$9,-1 j Loop End:
beq分支是I格式,其中,opcode=4(参见附录);rs=9(首操作数);rt=0(次操作数);immediate=3(加到或从PC中减去的指令条数)
则每个字段的十进制数表示为:
转化为二进制数表示为:
4、J格式指令
opcode字段与R格式保持兼容,并把其他所有字段合成为一个,形成一个大的目标地址空间。那么现在就可以指定32位地址中的26位,但仍可以进行优化,
由于最后两位总是00,因此可以默认最后两位为00。所以现在就指定了32位地址中的28位。
其他的4位如何得到呢?
①从PC处取得最高4位,从技术上讲,这意味着无法跳转到内存的任何地方,但对几乎所有情况是正确的,因为程序没那么长
②如果跨过256M边界,真的需要指定32位地址,可以把该地址放到寄存器中,然后使用jr指令
4、各指令格式的差别
I格式:用于有立即数的指令,指令lw和sw(偏移量也可看成立即数),分支语句(beq和bne),但不用于移位指令
J格式:用于指令j和jal
R格式:用于所有其他的指令