全部博文(254)
分类: LINUX
2012-05-27 14:29:57
计算机与简单计算器不同的地方在于它能进行决策。根据不同的输入数据和计算结果,执行不同的指令。程序语言中,一般使用if语句代替决策,有时if语句和go to语句、标号配合使用。MIPS汇编语言包括两条决策指令,它们类似于带goto的if语句。第一条指令是
beq register1,register2,L1
这条指令的意思是:当register1的值和register2的值相等时,程序将跳转到标号为L1的语句。助记符beq表示“如果相等则跳转”。第二条指令是
bne register1,register2,L1
它的意思是:当register1的值和register2的值不相等时,程序将跳转到标号为L1的语句。助记符bne表示“如果不相等则跳转”。这两条指令通常叫做条件分支指令。
类型 格式 op rs rt 地址/立即数 解释
beq |
I |
4 |
17 |
18 |
25 |
beq $s1,$s2,100 |
bne |
I |
5 |
17 |
18 |
25 |
bne $s1,$s2,100 |
域宽 |
6位 |
5 位 |
5 位 |
5 位 |
5 位 |
6 位 |
所有MIPS指令都是32位 |
R-格式 |
op |
rs |
rt |
rd |
shamt |
funct |
算术指令格式 |
I-格式 |
op |
rs |
rt |
地址/立即数 |
数据传输,分支,立即数格式 |
||
J-格式 |
op |
目标地址 |
跳转指令格式 |
MIPS跳转指令所用的寻址方式是最简单的。它们使用MIPS指令的最后一种格式,我们称之为J-类型格式。该格式含有6位的操作域和26位的地址域。这样,指令
j 10000 #跳转到10000的地方
就被汇编成这种格式:
2 10000
6位 26位
其中,2是跳转操作码,10000是跳转地址。
与跳转指令不同,条件分支指令除了含有分支地址外,还有另两个操作数,因此指令:
bne $s0,$s1,Exit #如果$s0不等于$s1,则转移到Exit
被汇编成下面的形式,这里只有16位能用来表示分支地址:
5 16 17 Exit6位 5位 5位 16位
要使程序中的地址都满足16位长的限制,则程序的大小不能超过216,这对今天的程序要求来说实在是太小了。所以另一种方法是用分支指令中的地址加上指令的某寄存器来得到真正要跳转到的地址:
程序计数器=寄存器+分支地址
用PC作为分支地址要加的寄存器,这种分支寻址的方式叫做PC相对寻址。MIPS中相对PC寻址实际上是相对于下一条指令(PC+4)而不是相对于当前指令(PC)。
因为MIPS指令的长度都是4个字节,所以MIPS的分支指令用相对PC的字距离而不是字节距离来寻址。这样16位的地址域能表示的范围又扩大了4倍。 故上述表格中bne $s1,$s2,100地址域的值是25而不是100,就是因为是相对字寻址的。
实践:
定义结构体位域:
typedef struct tagMipsIType
{
UINT32 op : 6;
UINT32 rs : 5;
UINT32 rt : 5;
INT32 addr : 16;
}MIPS_I_TYPE;
UINT32 MipsGetNextPc(UINT32 *pulAddr)
{
UINT32 *puNextPc;
UINT32 *puInst;
puInst = (MIPS_I_TYPE*)(pulAddr - 4);
puNextPc = (UINT32)((INT32)((puInst.addr) * 4) +(INT32)ulAddr);-------------@
return puNextPc;
}
对于@行,注意
1、使用乘法,不是左移2位,因为获取的addr是有符号,直接移位丧失符号位,在由16位数据提示至32时,数据出错。
2、ulAddr进行强制转换,避免在类型混合运算时,使用无符号运算,导致结果出错。