arm汇编程序编码格式
常用arm汇编指令
跳转
B指令
MOV PC,xxx,可以在任意4G的空间内做跳转
B 指令,类似于C 语言的jmp,直接向程序计数器PC写入下一跳的地址。
BL指令,类似于C语言的call,将当前位置保存在R14,即LR寄存器,然后在跳转代码结束后通过MOV PC ,LR
跳转回来。
B语句是只能在32M的空间跳转,因为其使用的是偏移量,这是一个有符号的26bit数值。
指令编码
跳转指令的编码格式为,前4个字节是指令的条件码,B指令是1110,即E。之后是3位固定的101,再然后是L标志位,决定是否要保留PC值到LR寄存器。(B和BL 的区别,B是0)。后面的24位是地址偏移,使用有符号的补码表示,然后乘以4(因为每条指令固定4字节)
偏移的计算为:对于目标地址B和当前地址A,[B-(A+8)]/4。如0x8454地址的B loc_8460指令则是0xEA000001
数据处理
MOV指令
将数据从寄存器或者立即数传给目标寄存器
MOV 指令,MOV R0,R1;将R1的值传给R0:0xE1A00001
MOV R0,#1;将立即数1传给R0:0xE3A00001
MVN指令,MVN R0,R1;将R1的值取反传给R0
指令编码
数据处理指令的编码格式为,前4个字节是指令的条件码,MOV为1110,即E。之后是2位固定的00,再然后是I标志位,区别opcode2是立即数还是寄存器(立即数的话I=1)。后面是4位的opcode1,然后是S标志位,区别该操作是否影响cpsr(S=0不影响)。再后面4位是Rn,第一个操作数的寄存器编码;再后面4位是Rd,目标寄存器编码。后面11位是opcode2,有三种方式:立即数方式,寄存器方式,寄存器移位方式。每种方式下的编码格式不一样 。
立即数方式
前4位是rotate循环右移位,后8位为immed8数值位。
立即数 = immed8在32位上循环右移rotate*2位。只有符合这种构造的才能表示,但是若当把一个数按位取反后,则得到一个合法的立即数时,这个数为有效数。此时将mov指令换成mvn指令执行
寄存器方式
前8位全为0,后4位为寄存器编码
寄存器移位方式
前5位为shift_imm,移动位数大小;后两位为shift,移位方式;然后是1位标志,区分后面Rm使用的是寄存器还是立即数;Rm。
支持5种移位方式,移位次数可由立即数或寄存器给出。
-
LSL:逻辑左移,低位补0
-
LSR:逻辑右移,高位补0
-
ASR:算术右移,高位补符号位
-
ROR:循环右移,移出的低位补入高位
-
RRX:带扩展的循环右移,带C位
如果指令带有S后缀,即S标志位为1,RRX后S标志为移位操作移出的最后一位。
Load/Store指令
LDR指令等,类似于lea指令,将某寄存器中值的某一偏移的位置
前4位为指令条件码,接下来两位用来区别是批量Load/Store还是非批量的。当为10时,为批量的。为00时,非批量的。然后是6位I、P、U、B、W、L,其他同上。
-
I: 用于区别operand2是立即数(I=1)还是寄存器(I=0)
-
P: 这个位基本在非批量中一直为1.具体内容不清楚
-
U: U=1时,要访问的地址为基址寄存器加上偏移量Address。U=0时, 要访问的地址为基址寄存器减去偏移量Address.
-
B: 当B=1时,指令访问的是无符号的字节数据;当B=0时,指令访问的是字数据
-
W: 当W=1时,将更新基址寄存器的内容(针对事先更新方式)
-
L: 当L=1时,指令执行Load操作。当L=0时,指令执行Store操作
前索引和后索引
LDR RO,[R1 ,#4] ;[R1+4]->RO
LDR R0,[R1 ,#4]! ;[R1+4]->R0,R1+4->R1
LDR RO,[R1],#4 ;[R1]->RO,R1+4->R1
依然需要+8,如第一条指令就是将R1寄存器中的数+4+8后,取该地址的数值放入R0,如
0x8188 <_start+24> ldr r0, [pc, #0x10]
这条指令,就是取0x8188(PC为当前指令)+0x10+8=0x81a0地址的数据。
注
对于CPSR标志位为:满足cond要求时指令执行,不满足不执行
对于条件码,属于满足条件执行的指令。
参考资料
https://blog.csdn.net/gameit/article/details/17464079