(1)数据处理指令的编码格式
cond: 指令的条件码
I: 用于区别operand2是立即数(I=1)还是寄存器(I=0)
opcode:指令操作码
S: 操作是否影响cpsr,S=0不影响,S=1影响
Rn: 包含第一个操作数的寄存器编码
Rd: 目标寄存器编码
operand2:第二操作数,有三种方式:立即数方式,寄存器方式,寄存器移位方式。每种方式下的编码格式不一样
立即数方式:
如图所示,在ARM的指令系统中,每个32位的立即数被编码成一个12位的数。这个32位的数是由一个8位的常数循环右移偶数位得到。其中循环右移的位数由一个4位二进制数的两倍表示,如图,8位常数加4位循环右移位数构成了一个12位数。
设立即数为immediate,8位常数便为immed8,4位的循环右移值为rotate,则:
immediate = immed8 循环右移 rotate*2
所以并不是每一个32位的常数都是合法的立即数,只有能通过上面的构造方法得到的才是合法的立即数。但是若当把一个数按位取反后,则得到一个合法的立即数时,这个数为有效数。此时将mov指令换成mvn指令执行
ARM汇编编译器按照下面的规则来生成立即数的编码
- 当立即数在0—0xFF范围时,令immediate = immed8 ,rotate = 0;
- 其他情况下,汇编编译器选择rotate数值最小的编码方式
例:MOV R0,#0xFC0
ADD R0,R1,#0x66
寄存器方式:
Rm:寄存器编码
例:MOV R3,R2(Rn)
ADD R0,R1,R2(Rm)
寄存器移位方式:
Rm:寄存器编码,
r:为1时,说明移位指令后面使用的是寄存器,为0时,说明移位指令后面使用的是立即数
shift:移位方式,00:LSL 01: LSR 10:ASR 11:ROR
shift_imm:要移动的位数大小。当r为1时,存放移动位数的寄存器的编码,当r为0时,为移位所使用的立即数大小。注:图中为立即数的方式,当为寄存器时,shift的范围是第8位—第9位
例: MOV R0,R0(Rm),LSL #6(shift_imm)
MOV R0,R0(Rm),LSL R1(shift_imm)
ADD R0,R1(Rn),R3(Rm),LSL #6(shift_imm)
ADD R0,R1(Rn),R3(Rm),LSL R6(shift_imm)
(2)Load/Store指令编码
cond: 指令的条件码
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操作
Rn: 基址寄存器
Rd: 目标寄存器
Address:地址偏移量。有三种方式:立即数方式,寄存器方式,寄存器移位方式。每种方式下的编码格式不一样
注:26,27位用来区别是批量Load/Store还是非批量的。当为10时,为批量的。为00时,非批量的
立即数方式:
offset12: 地址偏移量
例:LDR R1,[R0,#6]
LDR R1,[R0,# -6]
寄存器方式:
Rm:存放偏移量寄存器
例:LDR R0,[R1,R2(Rm)]
LDR R0,[R1,-R2(Rm)]
寄存器移位方式:
Rm:存放偏移量寄存器
shift:移位方式,00:LSL 01: LSR 10:ASR 11:ROR
shift_imm:要移动的位数大小
例:LDR R0,[R1,R2(Rm),LSL #6]
LDR R0,[R1,-R2(Rm),LSL #6]
(3)批量Load/Store指令编码
cond: 指令的条件码
P: P位表示基址寄存器Rn所指向的内存单元是否包含在指令所使用的内存块内。P=0时,不包含。P=1时,包含
U: U=1时,基址寄存器所指向的内存单元向地址增加的方向变化。U=0时,基址寄存器所指向的内存单元向地址减小的方向变化。
S: S对于不同指令有不同的含义。当LDMS指令的寄存器列表中包含PC寄存器时,S=1表示指令同时将SPSR的数值复制到CPSR中。对于寄存器列表中不包含PC寄存器的LDMS指令以及STMS指令,S=1表示当处理器模式为特权模式时,指令操作的寄存器时用户模式下的寄存器,而不是当前特权模式下的寄存器。
W: 表示指令执行后,基址寄存器Rn的值是否更新。当W=1时,指令执行后,基址寄存器的值会更新。
L: 当L=1时,指令执行Load操作。当L=0时,指令执行Store操作
Rn: 基址寄存器
reglist:
注:26,27位用来区别是批量Load/Store还是非批量的。当为10时,为批量的。为00时,非批量的
指令中寄存器和内存单元的对应关系满足这样的规则,即编号低的寄存器对应于内存中低地址单元,编号高的寄存器对应于内存中高地址单元。
地址变化方式有四种:
IA 事后递增方式
IB 事先递增方式
DA 事后递减方式
DB 事先递减方式
栈指针通常可以指向不同的位置。栈指针指向栈顶元素时称为FULL栈,栈指针指向于栈顶元素相邻的一个可用数据单元时称为EMPTY栈。
数据栈的增长方向也可以不同。当数据栈向内存地址减小的方向增长时,称为DESCENDING栈;当数据栈向内存地址增加的方向增长时,称为ASCENDING栈
综合这里两种特点,可以有以下四种数据栈:
FD 满堆栈递减
ED 空堆栈递减
FA 满堆栈递增
EA 空堆栈递增
不同数据栈对应的批量Load/Store指令的寻址方式如下表所示
(4)跳转指令
cond: 指令的条件码
L: 决定是否保存返回地址。当L=1时,当前PC寄存器的值会被保存到LR寄存器中
signed_24: 为指令跳转的目标地址。这个地址的计算方法是:将指令中的24位带符号的补码立即扩展到32位(扩展其符号位);并将此32位数左移两位,将得到的值与当前PC值相加,即得到跳转地址。
注:
- 因为24位数中有一位是符号位,所以可用为23位,跳转范围为8M。但是将其左移两位后,也就是乘以四,所以跳转范围变为32M。
- BX与BLX的编码格式于此有些不一样(详细看《ARM体系结构与编程》)
- 跳转指令为相对跳转,跳转时,是以PC为基址寄存器,然后将目标地址与PC的差值作为偏移量,将偏移量加到PC上,最后跳转