文章目录
1、ARM指令集概述
特点
【特点】:
- RISC,译码机制简单;
- 程序的启动从ARM指令集开始,进入异常转化为ARM状态,运行ARM指令集指令;
指令格式
<opcode>{<cond>}{S} <Rd>, <Rn> {,<operand2>}
opcode:操作码(指令助记符)如B,STR;
cond:可选择的条件码,执行条件,如NE,EQ;
S:若有S后缀,则根据计算结果更新CPSR中的条件码;
Rd:目标寄存器;
Rn:存放第一个操作数的寄存器;
operand2:第二个操作数;
条件指令
2、ARM的寻址方式
2.1 立即寻址
操作数包含在指令的32位机器编码中;
- 在指令中,立即数作为操作数2出现,编码格式中仅安排12位空间(8位常数和4位循环右移植),32位立即数显然不能直接编码;
- 12位编码包括8位常数和4位循环右移值,由8位常数循环右移4位值的2倍得到最后的32位立即数;
#代表立即数;
2.2 寄存器寻址
操作符存放在寄存器中;
【注意】:
第二个操作数为寄存器时方可进行移位操作,移位数可以是五位立即数或某个寄存器内的数值,执行完毕后第二操作数寄存器中的数值并不改变;
【位移方式】:
LSL:逻辑左移(乘);
LSR:逻辑右移(除);
ASL:算数左移,和LSL一样;
ASR:算数右移,分正负来填充右移后的空余位,正0负1;
ROR:循环右移;
RRX:带扩展的循环右移,循环右移1位后左端用C填充,这种方式只移位1位,所以无须指定移位位数;
寄存器间接寻址
利用寄存器的值作为存储器指针,数据传送类的load/store类指令都使用寄存器间接寻址方式;
- 间接寻址加上[];
基址加偏移地址
2.3 多寄存器及块拷贝寻址
一条指令完成多字数据或数据块的传送;
- LDM/STM;
【基址寄存器变化】:
IA:操作完后地址递增;
IB:地址先增后完成操作;
DA:操作完后地址递减;
DB:地址先减后完成操作;
多寄存器用{}包含,连续寄存器使用-间隔,否则使用,分隔;
2.4 堆栈寻址
存储空间中的数据栈与寄存器组之间的批量数据传输,采用R13(SP)作为堆栈指针,采用FILO(先进后出)的方式工作,SP指向栈顶;
- LDM/STM;
【堆栈组织生长方式】:
- FD/ED:满递减/空递减;
- FA/EA:满递增/空递增;
2.5 相对寻址
将程序计数器PC作为基址寄存器,指令中的地址标号字段作为偏移量进行寻址,跳转指令采用相对寻址方式;
3、ARM指令集
3.1 存储器访问(L/S)指令
【常规】
LDR R2, [R5] ;将R5为地址的存储单元中数据加载至R2;
STR R1, [R0, #0x04] ;mem32[R0+4]<-R1
【传送数据类型】
LDRB R3, [R2], #1 ;以R2为地址读取一字节数据至R3
STRH R1, [R0, #2]! ;半字传送,传送R1中低两字节数据至R0+2为地址的存储单元,R0更新
3.2 数据处理类指令
数据传送指令
MOV R1, R0 ;R1<-R0
MOV R1, R0, LSL #3 ;R1<-R0*8
MVN R0, #0 ;立即数0取反传送至R0, R0=-1
算数逻辑运算指令
【64位整数加法】:
RO/R1与R2/R3分别存放两个加数的低/高32位,R4/R5存放结果的低/高32位︰
ADDS R4 ,RO ,R2 ;带S后缀结果影响CPSR中的标志位C
ADC R5 ,R1 ,R3 ;带进位的加法,C标志位参与运算
【64位整数减】:
SUBS R4, R0, R2 ;R0-R2->R4
SBC R5, R1, R3 ;R1-R3->R5
【逆向减法】:
RSB RO,R1,R2 ;RO=R2-R1
RSC RO,R1,R2 ;在上行指令基础上再减C标志位的反码
【逻辑运算】:
AND R0, R0, #3 ;保持R0的0、1位,其余清0 R0&3 -> R0
ORR R0, R0, #3 ;置位R0的0、1位,其余不变 R0|3 -> R0
EOR R0, R0, #3 ;反转R0的0、1位,其余不变 R0^3 -> R0
BIC, R0, #3 ;清0 R0的0、1位,其余不变 对应位清0
【比较指令】:
CMP R1,RO ;R1-RO ,结果影响CPSR中的标志位,但不保留运算结果
CMN RO,#1 ;判断RO的值是否为1的补码,是则Z置位
;CMN指令将操作数1寄存器减去操作数2的负值
【测试指令】:
TST R1,#3 ;按位与,结果影响CPSR中的标志位
TEO R1,R2 ;按位异或,结果影响CPSR中的标志位
【乘法指令】:
- MUL:32位乘法;
- MLA:三操作数乘法,将操作数1与操作数2相乘,结果加第三个操作数,存入目的寄存器;
MLA, Rd, Rm, Rs, Rn ;Rd<-Rm*Rs+Rn
- 规则:Rd和Rm不能是同一寄存器;
- 形成两个矢量的标量积例程:
MOV R11, #20 //立即数20给R11
MOV R10, #0 //初始化结果寄存器
loop:
LDR R0, [R8], #4 //读取矢量1指针
LDR R1, [R9], #4 //读取矢量2指针
MLA R10, R0, R1, R10 // R0*R1+R10->R10
subs R11, R11, #1 // R11-1->R11
bne loop // 条件跳转
【条件码】:
- N:补码表示的符号数运算结果,1负,0正;
- Z:1表示结果为0;
- C:加时1表示进位,减时0表示借位,移位操作时为移出值的最后一位;
- V:1为溢出;
跳转指令
跳转指令用于控制程序的走向,可完成从当前指令向前或向后的32MB的地址空间跳转,包括基本跳转指令B ,
带返回的跳转指令BL,带状态切换(ARM与Thumb之间)的跳转指令BX,带返回和状态切换的跳转指令BLX;
程序状态寄存器访问指令
当前程序状态寄存器可分为4个8位独立域:
CPSR[31:24] : _f(标志域);
CPSR[31:24] : _s(状态域);
CPSR[31:24] : _x(扩展域);
CPSR[31:24] : _c(控制域);
【清CPSR标志位】:
MRS R0, CPSR ;R0<-CPSR
BIC R0, R0, #0xF0000000 ;清高四位
MSR CPSR_f, R0 ;CPSR_f<-R0
GNU ARM汇编基础
1、GNU ARM汇编器
label: instruction or directive or pseudo-instruction @comment
instruction :机器指令,处理器中有特定硬件来执行;
directive :伪操作,没有对应机器指令,只起编译器指示作用;
pseudo-instruction :伪指令,会被编译为一条或多条机器指令;
@:注释
2、GNU编译环境构成
GNU编译工具主要包括汇编器as、编译器gcc、链接器ld、反汇编工具objdump等,
每种工具都有×86版本和ARM版本如arm-linux-gcc;
3、段及lds文件
GNU ARM以段为单位来组织程序,段是具有相同属性的一段内容,汇编所产生的目标文件至少具有text、 data . bss这三个段,
分别对应可执行代码、初始化数据及未初始化数据;
GNU ARM常用伪操作
符号定义伪操作
.equ symbol , expr @将symbol定义为expr
.set @与.equ相同
.global symbol @将symbol定义为全局标号
.extern symbol @声明symbol为一个外部变量
数据定义伪操作
.word expr {,expr}... @分配子内仔里兀开用expr 初始化
.byte expr {,expr}... @分配字节内存单元并用expr初始化
.long expr {,expr}... @同.word
.ascii expr{,expr}... @字符串,非零结束符
.string expr {,expr}... @字符串,零结束符,同.asciz
.zreo size @用О填充size个字节的内存