找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 4111|回复: 0
打印 上一主题 下一主题
收起左侧

从ARM汇编指令机器码解释一些问题

[复制链接]
跳转到指定楼层
楼主
本帖最后由 51黑tt 于 2016-3-6 15:28 编辑

从ARM汇编指令机器码解释一些问题

为什么MOV R0, #0×12345678这条指令无法编译,而MOV R0, #0x678却可以编译通过?
为什么芯片会有立即数寻址,寄存器寻址,间接寻址等多种寻址方式?一种寻址方式不可以么?
为什么B跳转指令只能跳转到±32MBytes的范围内?

下面,我们一起来看看ARM7的指令格式,从指令格式中找出这些问题的答案。

ARM7内核采用的是RISC精简指令集,所有的ARM指令都是32bits的,在这32bits里既包含了指令的指令码,也包含了指令需要运算的数据,以MOV指令为例,通过MOV指令的32bits可以识别出这是一个MOV指令,又可以在这32bits里找到源寄存器和目的寄存器。我们来看一下MOV指令的机器码格式:
图 6  MOV指令的机器码格式
28~31bitscond)是条件码,就是表明这条语句里是否有大于、等于、非零等的条件判断,这4bits共有16种状态,分别为:
二进制码指令符号含义二进制码指令符号含义
0000EQ相等0001NE不等
0010CS/HS进位/无符号数大于等于0011CC/LO清进位/无符号数小于
0100MI/负数0101PL/正数或0
0110VS溢出0111VC没溢出
1000HI无符号数大于1001LS无符号数小于等于
1010GE有符号数大于等于1011LT有符号数小于
1100GT有符号数大于1101LE有符号数小于等于
1110AL任何条件1111-未定义
表 1  汇编语言条件码
指令与条件码可以有多种组合,比如MOV指令可以有MOVMOVEQMOVLT等多种形式。前面我们说过状态寄存器里有NZCV的状态标志,当执行一条指令时,芯片就会将这条指令的条件码与状态寄存器中的状态标志做比较,如果状态寄存器中的状态标志满足这条指令的条件码时,则执行这条语句,如果不满足则不执行这条指令。状态寄存器中的状态标志是受某些指令影响的,因此在使用有条件码的指令进行判断前,必然会有其它指令配合使用,先修改状态寄存器中的状态标志,例如:
CMP    R1, #0
BEQ    GETNEXTTASKSP
第一条指令“CMP”是一个“比较”指令,如果R1等于0,那么它就将状态寄存器中的Z置为1,表示结果为真,否则,将状态寄存器中的Z置为0,表示结果为假。第二条指令其实是一条“B”指令,是“跳转”指令,B之后的“EQ”就是条件码,从表1中可以知道,条件是“相等”时才执行。
R1等于0时,CMP指令就将Z置为1,执行BEQ时满足条件,就执行了跳转。如果R1不等于0CMP指令就将Z置为0,执行BEQ时不满足条件,就不执行跳转。
同理,只有当状态寄存器中的标志为相等时,MOVEQ指令才会执行,这时其功能与MOV指令相同。而MOVLT指令则是当状态寄存器中的标志为有符号数,并且处于小于状态时才会执行的MOV指令。MOV指令的条件码是AL,因此MOV指令可以不管任何条件都去执行。其它指令也可以与条件码组合使用,具体情况请查阅参附录中的参考文档2
25bitI)是用来区别shifer_operand域是采用立即数寻址方式还是寄存器寻址方式,该bit0表示寄存器寻址方式,为1表示立即数寻址方式,这就涉及到了指令的寻址方式。
寻址方式的出现不是为了使指令能有多种写法,而是受指令长度限制被迫产生的产物。以MOV指令为例,如果采用立即数寻址,立即数的长度不可能超过shifer_operand域的长度(MOV指令可以采用移位的方式装下部分更长的立即数,这些不在讨论之内),因此我们就不可能使用
MOV R0, #0×12345678
这条指令。立即数#0×1234567832bits数据,已经超过了shifer_operand域所能装下的最长12bits数据,如果把0×12345678全部被存到指令中,那么该指令中将无法存储条件码等其它指令信息,因此,这条指令在编译时就会报错。
为了解决这个问题,芯片设计人员就设计了寄存器寻址方式,在ARM7中每种模式有16个通用寄存器,24次方等于16,因此只需要用4bits就可以为每个寄存器分配一个编号,R0~R15寄存器分别对应0~15的编号。4bits的寄存器编号完全可以存入shifer_operand域。采用寄存器寻址时,指令先查到寄存器的编号,然后再从寄存器中取出使用的数据,这样就解决了MOV指令受指令长度的限制而无法操作长立即数的问题。
从上述描述的过程来看采用寄存器寻址方式必须先将数据放入一个寄存器中,然后才能使用MOV指令采用寄存器寻址。对比立即数寻址方式,它增加了指令的执行时间,也增加了代码,还多用了一个寄存器,但它的优点是可以操作长的数据。
除了上面这两种寻址方式外,ARM7还有多种其它寻址方式,每种寻址方式都有其自身的特点,适用不同的场景,这里不介绍了。
21~24bitsopcode)是指令码,用来表明这条指令是什么指令,例如,MOV指令的指令码是0b1101,看到0b1101,芯片就将这条指令当做MOV指令来解析。
20bitS)就是指令中S标志的体现,该bits0表示指令不带S,为1表示指令带S,功能见上述指令介绍。
16~19bitsSBZ)手册中没查到是什么意思,SBZ应该是should be zero的意思,对比了几条指令发现该域果然全是0,应该是保留位。
12~15bitsRd)是指令中的目的寄存器,存放寄存器的4bits编号。
0~11bitsshifter_operand),指令的操作数。

下面我找了4条指令,将MOV指令做一个对比:
指令
机器码
指令格式
cond00IopcodeSSBZRdshifer_operand
MOV R1, #0×64E3A0106411100011101000000001000001100100
条件码为1110适用任何条件 立即数方式MOV的指令码指令没有S标志 目的寄存器为R1源操作数为立即数0×64
MOVS PC, R14E1B0F00E11100001101100001111000000001110
条件码为1110适用任何条件 寄存器方式MOV的指令码指令有S标志 目的寄存器为R15源操作数为寄存器R14
MOVLT R3, #0×1B3A0300110110011101000000011000000000001
LT的条件码为1011 立即数方式MOV的指令码指令没有S标志 目的寄存器为R3源操作数为立即数1
MOVEQ R0, R101A0000100000001101000000000000000000001
EQ的条件码为0000 寄存器方式MOV的指令码指令没有S标志 目的寄存器为R0源操作数为寄存器R1
表 2  MOV指令汇编格式对比

BL指令跳转到目的地址,同时将BL指令的下条指令地址存入LR寄存器供程序返回时使用,调用函数时可以使用BL指令,如:
0×00080398 EB0002E2  BL    0x00080F28
0×00080398BL指令所在的地址,EB0002E2BL指令的机器码,0x00080F28BL指令要跳转到的地址。从这个格式来看,BL指令好像是一个绝对跳转指令,直接跳转到0x00080F28这个地址,其实不然,BL指令是一个相对跳转指令,格式如下:



BL指令的0~23bits存放的是要跳转的相对地址,由于指令所在地址必须是4字节对齐的,因此跳转的地址最低2bits必然是0,因此BL指令0~23bits保存的是省略这最低2bits的地址,如果补全了这2bitsBL指令就可以表示26bits的跳转地址。在这26bits中需要使用1bit表示向前跳还是向后跳,那么剩下的25bits就可以表示32MByts的范围了,225=32M,因此,我们在很多文档上可以看到B跳转指令只能跳转到±32MBytes范围内的说明,就是这个原因。
上面这个BL指令要跳转的相对地址是0x2E2BL指令0~23bits),补充2个最低位后,跳转的相对地址为0xB88,由于ARM72级流水线,所以跳转到的指令需要多加8个字节,BL要跳转的实际地址为0×00080398+0xB88+8=0x00080F28
这条BL指令执行下面的操作:
LR = 0x0008039C
PC = 0x00080F28
在操作系统中我们没有使用BL指令,就是因为我们不知道我们所调用的函数是否会超出BL指令的跳转范围,但我们可以看到编译器编译出的很多程序都是使用BL指令调用函数的,编译器之所以不怕跳转超出±32MBytes的范围,是因为编译器在编译时就知道了程序所需要跳转的范围,它会为±32MBytes之内的跳转分配BL指令,保证BL指令不会超出范围。在这里以BL指令为例,介绍一下B指令的相关知识。



分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享淘帖 顶 踩
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表