寄存器的寄存器用于数据处理及控制。
如内存中数据处理,需先从内存中加载数据到寄存器中,处理完毕后,再把寄存器的数据存放到内存中。
寄存器组拥有16个寄存器,R0R12是通用寄存器,R13R15是特殊寄存器。
寄存器 | 作用 | comment |
---|---|---|
R0~R7 | 通用寄存器-Low register | 16 bits 指令 |
R8~12 | 通用寄存器-Hig Register | 16 bits 指令 + 32 bits 指令 |
R13 | Stack Pointer-SP | MSP:(Main stack pointer) 复位默认的SP指针,PSP:(Process stack pointer):进入线程后的指针 |
R14 | Link Register-LC | 函数调用时,会首先将LC的值存入堆栈中,用于保存返回地址,当调用函数完毕后,将LC的值赋给PC。 |
R15 | Program conutner | 当前执行指令的地址 |
Thumb2 指令集:可以16bits指令与32位指令的混合使用。
label
mnemonic operand1, operand2, ....;comments
label
标签用以表示一个参考地址。
Label放在指令前,Label用以表达指令的地址。
Label也可以用以表达数据的地址。
mnemonic
助记符,助记符是指令的名字,。
operand
操作数有,操作可以是立即数,也可以是寄存器,操作数的个数视具体汇编指令。
;comment 注释
eg:
MOVS R0, #0x12 ; Set R0 = 0x12 (hexadecimal)
MOVS R1, #’A’ ; Set R1 = ASCII character A
ARM处理器汇编器中,一些指令支持带后缀,常用的后缀如下:
后缀简写 | 备注 |
---|---|
S | 需要更新APSR标志 |
EQ | Equal |
NE | Not Equal |
LT | Lesser Than |
GT | Great Than |
.N | 使用16位指令集 |
.W | 使用32位指令集 |
1 Moving data within the processor 数据拷贝
MOV R4, R0 ; 从R0拷贝数据到R4。
MOV R4,[R0]; 从R0数据指向的地址中读取数据到R4;
MOVS R4, R0; 从R0拷贝数据到R4,更新APSR。
MOVS R4, [R0}; 从R0数据指向的地址中拷贝数据到R4,更新APSR。
eg:
MOV R4, #0x34; R4的值设置为0x34
MOVS R4, #0x34; R4的值设置为0x34,更新APSR
(move word指令)
MOVW R4, #0x1234; 把16位立即数放到寄存器的低16位,高16位清零 。(若执行指令前R4的值为全为F,执行完毕后,R4的值为0x00001234)
MOVT R4, #0x1234; 把16位立即数放到寄存器的高16位,低16位不变。(若执行指令前R4的值为0x00001234,执行完毕后,R4的值为0x12341234)
MVN R4, R0; 对R0按位取反,然后放入R4中。
MSR CONTROL, R2; 把状态寄存器的值放到通用寄存器中。
MRS R2, CONTROL; 把通用寄存器的值放到状态寄存器中。
Notes:
移动8bits内的数据使用MOV指令;
移动8bits~16bits的数据使用MOVW/MOVT指令
移动32bits的数据;使用LDR指令;如LDR R0. 0x12345678;Set R0 to 0x12345678
2 Memory access 内存访问
预锁引寻址
数据的传输的内存地址是寄存器的值与立即数的值的总和。
这个立即数的值可正可负。
LDRB R0,[R1,#0x1234]; 从内存地址Ro+0x1234中读取一个byte,然后放入RO寄存器中。
LDRB R0, [R1,#0x1234]! 从内存地址Ro+0x1234中读取一个byte,然后放入RO寄存器中。同时R1的值更新为R1+0x1234
Note:指令中!表明指令完成后,地址需要被更新。
LDRD R0, R1,[R2,#0x5]; 从内存地中R2+0x5中读取2个bytes,然后放入R0,R1寄存器中。
STRD R0,R1,[R2,#0x05]; 把R0,R1的值写入内存R2+0x05中
寄存器寻址
LDR R0, [R1,R2, LSL #2]; 从内存地址R1 + (R2<<2)中读取一个字到R0中。
STR R0,[R1,R2]; 把R0的值写入地址R1+R2中。
LDR R0, R1,#0x05; 从内存地址为R1的值的内存中读取数据到R0中,并更新R1 = R1+5.
连续读/写多个寄存器从一个连续的地址空间内。
LDM指令 Load multiple registers
STM指令 Store multiple register
LDR R4,=0x8000; 设值R4的值为0x8000.
LDMIA R4, {R0-R3}; 读取4个words并且把他们依次存取到R0,R1,R2,R3中。
寄存器组的设置是灵活的;如{R1,R3,R5-R7,R9,R10-R12}.
堆栈操作:
PUSH {R0, R4-R7, LC}; push R0,R4,R5,R6,R7进去堆栈
POP {R2, R3};POP R2,R3从堆栈里。
通常PUSH与POP指令是成对出现,且寄存器列表是一致的。
如
PUSH {R0, R4-R7, LC}; push R0,R4,R5,R6,R7进去堆栈
POP{R0, R4-R7, PC}; 恢复R4_R7,直接把LC的值赋给PC。
LC返回的是函数执行的地址,返回的LC会直接赋值给PC,所以可以直接POP LC的值给PC
3 Arithmetic operations 算数操作
算数加 addition
ADD R0, R0, R2 ; R0 = R0 + R2
ADDS R0, R0, R2 ; R0 = R0 + R2,更新APSR
ADD RO, R1,#0x5; RO = R0 +5;
ADDS RO, R1,#0x4‘ RO = R0 +5;更新APSR
ADC(ADD with carry)
ADC RO,R1, R2; R0 = R1 + R2 + carry
ADC R0, #0x3; R0 = R0 + 3 + carry
算数减 subtraction
SUB R0, R1, R2; R0 = R1 - R2
SUB R0, #3; R0 = R0 -3
SUB R0, R1, #5; R0 = R1 -5
SBC R0, R1, R2; R0 = R1 - R2 - borrow
逆向算数减 Reserve subtraction
RSB R0, R1, R2; R0 = R2 - R1
RSB R0, R1, #0x55; R0 = 0x55 - R1
算数乘 multiply
MUL RO, R1, R2 ; R0 = R1 * R2
算数除法 divide
UDIV R0, R1, R2; R0 = R1/R2 (unsigned)
SDIV R0, R1, R2; R0 = R1/R2 (Signed)
4 Logic opeations 逻辑操作
逻辑按位与 & and
AND R0, R1; R0 = R0 & R1
AND R0, R1, R2; R0 = R1 & R2
AND R0, R1, #3; R0 = R1 & 3
按位或 | or
ORR R0, R1; R0 = R0 | R1
ORR R0, R1, R2; R0 = R1 | R2
ORR R0, R1, #3 R0 = R1 | 3
按位清除 bit clear
BIC R0, R1; R0 = R0 & ~R1
BIC R0, R1, R2; R0 = R1 & ~R2
BIC R0, R1, #3; R0 = R1 &~3
按位异或 bitwise exclusive or
EOR R0,R1; R0 = R0 ^ R1;
5 Shift and rotate instruction 移动旋转操作
算术右移 Arithmetic shift right
ASR R0, R1; R0 = R0 >> R1
ASR R0, R1, R2 R0 = R1 >> R2
ASR R0, R1, #0x3 R0 = R1 >> 0x3
逻辑右移动 Logic shift right
LSR R0, R1; R0 = R0 >> R1
LSR R0, R1, R2; R0 = R1 >> R2
LSR R0, R1, #0x3 R0 = R1 >> 3
逻辑左移动 Logic Shift Left
LSL R0, R1; R0 = R0 << R1
LSL R0, R1, R2; R0 = R1 << R2
LSL R0, R1, #0x3 R0 = R1 << 0x03
6 Bit-Filed operation instruction 位操作指令
6.1 BFC(Bit filed cler)
LDR R0, = 0x1234FFFF
BFC R0,#4,#8; #4代表其实的bit,#8代表c户里的bit长度;指令完毕后 R0 = 0x1234F00F
6.2 BFI(Bit filed insert)
命令格式: BFI R0, R1, #lsb, #width
该命令会从R1中拷贝width指定的bit到R0的LSB指定的位置。
LDR R0, = 0x12345678
LDR R1, = 0x3355AACC
BFI R0, R1, #8, #16;命令执行完毕R0 = 0x335678CC;
7 Compare and Test instruction 比较与测试指令
7.1 CMP - compare
CMP R0, R1; 计算R0-R1,更新APSR
CMP R0,#0x5; 计算R0-3,更新APSR
7.2 CMN- Compare negtive
CMP R0, R1; 计算R0+R1;更新APSR
CMP R0,#0x3; 计算R0+3;更新APSR
7.3 TST-bitwise AND
TST R0, R1;
TST R0,#0x3;
7.4 TE!-bitwise XOR
TEQ R0, R1;
TEQ R0,#0x3;
比较与测试指令会更新APSR的标志位,用于选择分支或者条件执行。
8 Program flow control 程序流程控制
用于条件分支;函数调用;条件执行
8.1 函数调用
BL Label; Branch and link instruction-跳转到Label指定的地址并且保存返回值在LR中
函数调用时,如果函数有三个参数,会把参数依次放进R0,R1,R2中,如果函数有返回值会把返回值放进R0中。
eg:
8.2 条件分支
B<Conditon> Label; 跳转到Label如果满足条件。
8.3 用于循环的 指令
CBZ Compare and Branch if Zero
CBNZ Compare and branch if not Zero
8.4 IT If-Then 指令
待更新
函数调用流程:
C语言定义如下代码
BL Label; Branch and link instruction-跳转到Label指定的地址并且保存返回值在LR中 函数调用时.
调用带参的函数时,如果函数有三个参数,会把参数依次放进R0,R1,R2中,如果函数有返回值会把返回值放进R0中。
如果有俩个参数,会把参数依次放进R0,R1中。