ARM常用汇编指令集
指令: 由CPU提供,最终生成机器码,由CPU执行.
伪指令: 由编译器提供,指导编译过程,编译后不产生机器码.
ARM汇编5个特点:
ldr/str架构
RISC架构的CPU不能直接操作内存,cisc可以直接操作内存.
LDR/STR架构:CPU和内存数据交换必须通过寄存器来读写.
ldr(load register):内存数据->通用寄存器
str(store register):通用寄存器数据->内存
八大寻址方式
寄存器和数据直接交换: 立即数寻址 #
mov r0,#0xffe // 把数据0xffe 存到r0,相当于C语言的r0=0xffe;寄存器之间交换数据:寄存器寻址 rx
mov r0,r1 //r1 数据存到r0,相当于C语言的r0=r1;寄存器和寄存器里的数据移位后进行交换:寄存器移位寻址 lsl, lsr
mov r0,r1,lsl #3 // mov r0,(r1 <<3) r1里的数据LSL 3位后存到r0,相当于C语言的r0=r1<<3;寄存器和内存之间交换数据: 寄存器间接寻址 []
ldr r0,[r2] //r2寄存器中地址所指的数据加载到r0中,[r2]表示内存,r2里存放内地地址
//r2相当于C语言的指针,r0=(r2); 解引用.寄存器和内存地址偏移后交换数据:基址变址寻址[rx,#x]
ldr r0,[r2,#3] //r2寄存器中地址偏移3后所指向的数据加载r0
//r2是基地址,#3是偏移量,相当于C语言r0=(r2+3);解引用.多个寄存器同时和内存交换数据:多寄存器寻址 rx!,{rx-rx,rx}
ldmia r1!,{r2-r7,r12} //r1所指向的内存地址开始的数据连续加载到r2至r7 和r12 寄存器中,r1类似数组首地址,数组有8个元素,分别把这8个元素加载到后面8个寄存器中.
//”!”作用,运算过程中增量值保存在r1中,没有则保存r1原始值(是否改变r1原始值)栈和寄存器之间交换数据:堆栈寻址sp!,{rx-rx,rx}
stmfd sp!,{r2-r7,r12} //栈指针sp所指地址中数据连续加载到r2至r7 和r12 寄存器中, sp栈基地址ldmfd sp!,{r2-r6,pc}^ //”^”作用,目标寄存器有PC时,会同时把spsr值写到CPSR中 ,从异常模式中返回到正常模式(中断返回,快速返回)
pc地址和pc偏移量之间交换数据:相对寻址 flag:
beq flag //跳转到flag标号地方,本质是通过PC和PC本身作为参考,加一个偏移量,PC当前执行的地址向前或向后偏移.
flag:
指令后缀
同一个指令附加不同后缀后衍生出很多不同的指令,常用如下:
- B(Byte)功能不变,操作长度变为8 //ldr ldrb
- H(Half)功能不变,操作长度变为16 //ldr ldrh
- S(Signed)功能不变,操作数变为有符号 //ldr ldrsh
- S(cpSr)影响CPSR标志位(NZCV) //mov movs r0,#0;执行后影响标志位
条件执行后缀
- 条件后缀是否成立不是取决本句代码,是本句之前代码执行后的结果是否影响标志位
- 条件后缀只影响本句代码是否执行,不影响前后一句代码是否执行
常用如下:(*号使用频率高)
条件码 标志 含义 *EQ Z=1 相等 *NE Z=0 不相等 CS/HS C=1 无符号大于或等于 CC/LO C=0 无符号小于 ML N=1 负数 PL N=0 正数或零 *VS V=1 溢出 VC V=0 没有溢出 *HI C=1,Z=0 无符号大于 LS C=0,Z=1 无符号小于或等于 GE N=V 有符号大于或等于 LT N!=V 有符号小于 *GT Z=0,N=V 有符号大于 LE Z=1,N!=V 有符号小于或等于 AL X 无条件执行(指令默认条件) NV X 从不执行
5 . 多级流水线
为了增加处理器指令流的速度.
ARM Thumb
执行 pc-8 PC-4
解码 pc-4 PC-2
取址 pc PC
汇编指令详解:
1. 数据处理指令:
1 .1 .数据传输指令
mov //mov r1,r0 寄存器和寄存器之间传输
//mov r1,#0xff 寄存器和数据之间传输
mvn //mvn r0,r1 按位取反后再存放
1.2. 算术指令
add
sub //sub r2, r1,r0 r2(目标)=r1-r0(源)
rsb
adc
sbc
rsc
1.3. 逻辑指令
and // 逻辑与
orr // 逻辑或
eor // 逻辑异或
bic //bic r0,r1,#0x1f 特定位清零,将r1中的数的bit0到bit4(0x1f=000.....11111)清零后赋值给r0
1.4. 比较指令(重在过程中影响标志位,不加后缀自动影响CPSR)
cmp // cmp r0,r1 等价于sub r2,r0,r1(r2=r0-r1)比较两个寄存器的数是否相等,
cmn // cmn r0,r1 等价于add r2,r0,r1(r2=r0+r1)两数相加是否为0(两数互补)
tst // tst r0,#0xf 测试某些位是否为0(0xf=1111)bit0-bit3,对特定数进行位与r0 and 0xf
teq // teq r0,r1 对2个数进行异或r0 eor r1
1.5. 乘法指令
mvl
mla
umull
umlal
smull
smlal
1 .6. 前导零计数
clz // 获取一个数前面几个零如0xf=00000000.....1111
2. cpsr spsr操作指令
cpsr: 1个,程序状态寄存器
spsr: 5个状态各1个,作用是当从普通模式进入异常模式时,保存之前普通模式下的cpsr,保证再返回普通模式时可以恢复原来的cpsr
mrs // mrs r0,cpsr 把CPSR的值读到r0中
msr // msr cpsr ,r0 把加工后的数据(r0)重新写到CPSR中
// cpsr_f 只是模式位
// cpsr_c 只是控制位
3. 跳转指令
b // b flag (绝对跳转)直接跳转,不保存返回地址,不打算返回
bl // bl flag (函数调用)跳转前保存返回地址到lr(r14)中,再跳转
bx // thumb下跳转,跳转同时切换到ARM态
4. 访存指令
ldr/str // 单字、半字、字节访问,每周期只能访问4个字节内存.
ldm/stm // 多字批量访问 单周期多寄存器读写,多字节批量操作,提高访问效率
swp // swp r1,r2,[r0] 内存和寄存器互换,把r0内存地址的数据放到r1中同时把r2的数据写回r0内存地址中
// swp r1,r1,[r0] 一条指令完成内存和寄存器互换
4 .1. 栈与ldm/stm的处理
stmx sp, {rx-rn} //x为后缀,rx-rn为通用寄存器
stmia sp,{r0-r12} //sp栈内存地址 r0-r12寄存器,存放方式按照ia后缀规则,后缀如下:
8种后缀:(*号使用频率高,ARM默认满减栈)
*ia:(increase after) 先传输数据 再地址+4 i:加 a:先 ib:(increase before) 先地址+4 再传输数据 da:(decrease after) 先传输数据 再地址-4 d:减 b:后 db:(decrease before) 先地址-4 再传输数据 ———————————————————————————————————————————————
*fd:(fulldecrease) 满栈递减 sp所指地址有数据 先向低地址移动合适位置再存储数据 f:满 d:递减 ed:(emptydecrease) 空栈递减 sp所指没有数据 先存储数据再向低地址移动合适位置 fa: 满栈递增 sp所指地址有数据 先向高地址移动合适位置再存储数据 e:空 a:递增 ea: 空栈递增 sp所指没有数据 先存储数据再向高地址移动合适位置 ———————————————————————————————————————————————
四种栈:
空栈: sp指向空位 存数据:直接存放 取数据:先移动后取 满栈: sp指向满栈 存数据:先移动后存放 取数据:直接取数据 增栈: 地址向高位 栈指针移动方向为地址增加方向 减栈: 地址向低位 栈指针移动方向为地址减小方向 ———————————————————————————————————————————————
5 . 软中断指令
swi(software interrupt) //软中断指令用来实现操作系统中系统调用
6 . 协处理器(coprocessor)
soc中另一个处理核心协助主处理器实现某些功能,被主处理器调用执行一定任务。
ARM架构支持多达16(0-15)个协处理器,一般SOC中只实现其中的第15个也就是CP15.协处理MMU\Cache\TLB等处理有关,功能上和操作系统的虚拟地址映射\cache管理等有关.
mrc //读协处理器
mcr //写协处理器
mcr{<cond>} p15, <opcode_1>, <Rd>, <Crn>, <Crm>, {<opcode_2>} //mrc p15 ,0, r0, c1, c0, 0 把CP15的C1寄存器值读到arm的R0寄存器中
opcode_1: 对于CP15永远为0
Rd: ARM的通用寄存器名字(不能为R15/PC)
Crn: CP15的寄存器,合法值c0~c15
Crm: CP15的寄存器,一般均为c0
opcode_2: 一般省略或为0
7 . 伪指令
伪指令由编译器提供,目的为了指导编译过程,编译后不产生机器码.
/* */ //注释
// //注释
@ //注释
: //标号
. //当前指令的地址 b . 相当于C语言while(1)
# //代表立即数
立即数:
ARM 32位指令,除了指令标记和操作标记外,本身只能附带很少位数的立即数,所以有合法和非法立即数
合法立即数:无限移位后非零位可用8位表示 //0x000000ff,0x000ff000,
非法立即数:无限移位后非零位无法用8位表示 //0x000f0f00,0x001ff000,
7 . 1. 常用伪指令:
.global _star //给_star 声明为外部链接属性(目的为了别的文件可以访问、引用)
.section .text //指定当前段位代码段(链接脚本中运用)
.ascii .byte .short.long .word //ascii字符、 byte字节、 short 2字节、 long 4字节、 word 4字节(相当于定义变量)
.quad.float.string //定义数据 quad 8字节、 float 浮点、 string 字符串
.align 4 //以16字节对齐 2^4=16 按照16字节(不填充)
.balignl 16 0xfff //16字节对齐加填充,b:位填充、align:要对齐、l:long以4字节为单位填充、16:16字节对齐、 0xfff:用fff填充中间的地址(填充原料)
.equ //类似C中的宏定义 #define
.end //文件结束
.include //文件包含
.arm/.code32 //arm 代码
.thumb/.code16 //thumb 代码
ldr //大范围的地址加载
//ldr r0,#0xff :指令 ,ldr r0,=0xffff :伪指令 (指令后面加#,需要考虑合法和非法立即数。伪指令后面加=,不需要考虑合法和非法立即数.)加载地址由链接脚本决定.
adr //小范围的地址加载
//adr以PC为基准表示地址(相对地址).加载地址由运行时决定.
adrl //中等范围的地址加载
nop //空操作
本文深入解析ARM汇编指令集的特点与应用,包括数据处理、寄存器操作、访存及栈处理等指令,并介绍伪指令的作用及合法立即数的概念。
1391

被折叠的 条评论
为什么被折叠?



