一、汇编指令

1.1 指令与伪指令

汇编的指令

指令是CPU机器指令的助记符,编译后会得到一串二进制机器码,由CPU执行

汇编的伪指令

伪指令本质上不是指令,它是编译器环境提供用来指导编译过程,编译后伪指令不会生成机器码
伪指令的意义在于指导编译过程

区别

经过编译后会不会生成二进制机器码

1.2 gun汇编中的符号

符号 作用
@ 用来做注释,可以在行首也可以在代码后面同一行直接跟,和C语言中 // 类似
以冒号结尾的是标号
. 点号在gnu汇编中表示当前指令的地址
# 立即数前面要加#或$,表示这是个立即数

1.3 gun汇编中的伪指令

1、ARM中有一个ldr指令,还有一个ldr伪指令,一般都使用ldr伪指令而不用ldr指令

2、adr与ldr:
ldr和adr区别是ldr是长加载、adr是短加载
adr指令加载符号地址,加载的是运行时地址
ldr指令加载符号地址,加载的是链接地址

1、adr编译时会被sub或add指令替代,
2、ldr编译时会被mov指令替代或者文字池方式处理
3、adr总是以PC为基准来表示地址,指令本身和运行地址有关,用来检测程序当前的运行地址在哪里
4、ldr加载的地址和链接时给定的地址有关,由链接脚本决定
符号 作用
ldr 大范围的地址加载
adr 小范围的地址加载
adrl 中等范围的地址加载
nop 空操作
.global _start 给_start外部链接属性
.section .text 指定当前段为代码段
.align 4 以16字节对齐
.balignl 16 16字节对齐填充
.end 标识文件结束
.include 头文件包含
.arm / .code32 声明以下为arm指令
.thumb / .code16 声明以下为thubm指令
.ascii .byte .short .long 定义数据
.word.quad .float .string 定义数据

二、不同风格的ARM指令

ARM官方的ARM汇编风格
指令一般用大写、 Windows中IDE开发环境(如ADS、MDK等)常用。

LDR R0, [R1]

GNU风格的ARM汇编
指令一般用小写字母、 linux中常用。

 ldr r0, [r1]

三、ARM汇编的特点

3.1 LDR/STR架构

1、 ARM的CPU不能直接读取内存,需要先将内存加载到CPU通用寄存器中才能被CPU处理
2ldr(load register)指令将内存加载到通用寄存器
3str(store register)指令将寄存器内容保存到内存空间
4、 ldr/str组合用来实现 ARM CPU和内存之间数据的交换

3.2 8种寻址方式

寻址方式 例子
寄存器寻址 mov r1, r2
立即寻址 mov r0, #0xFF00
寄存器移位寻址 mov r0, r1, lsl #3
寄存器间接寻址 ldr r1, [r2]
基址变址寻址 ldr r1, [r2, #4]
多寄存器寻址 ldmia r1!, {r2-r7,r12}
堆栈寻址 stmfd sp!, {r2-r7, lr}
相对寻址 beq flag flag:

3.3 指令后缀

汇编指令中,同一指令经常附带不同后缀,变成不同的指令

经常使用的后缀有:

1、B(byte)功能不变,操作长度变为82、H(half word)功能不变,长度变为163、S(signed)功能不变,操作数变为有符号
4、S(S标志)功能不变,影响CPSR标志位
//	B    H    SB    SH
ldr ldrb ldrh ldrsb ldrsh
//mov和movs
 movs r0, #0

3.4 条件执行后缀

操作码 条件码助记符 标志 含义
0000 EQ Z=1 相等
0001 NE Z=0 不相等
0010 CS/HS C=1 无符号数大于或等于
0011 CC/LO C=0 无符号数小于
0100 MI N=1 负数
0101 PL N=0 正数或零
0110 VS V=1 溢出
0111 VC V=0 没有溢出
1000 HI C=1、Z=0 无符号数大于
1001 LS C=0、Z=1 无符号数小于或等于
1010 GE N=V 有符号数大于或等于
1011 LT N!=V 有符号数小于
1100 GT Z=0、Z=V 有符号数大于
1101 LE Z=1、Z!=V 有符号数小于或等于
1110 AL 任意 无条件执行(指令默认条件)
1111 NV 任意 从不执行(不要使用)

3.5 8种后缀

后缀 含义
ia 先传输,再地址+4
ib 先地址+4,再传输
da 先传输,再地址-4
db 先地址-4,再传输
fd 满递减堆栈
ed 空递减堆栈
fa 满递增堆栈
ea 空递增堆栈

3.6 4种栈

空栈:栈指针指向空位,存入时可直接存入然后指针移动一格;取出时需要先移动一格才能取出
满栈:栈指针指向栈中最后一格数据,每次存入时需要先移动栈指针一格再存入;取出时可以直接取出,然后再移动栈指针
增栈:栈指针移动时向地址增加的方向移动的栈
减栈:栈指针移动时向地址减小的方向移动的栈

注意:操作栈时使用相同的后缀就不会出错

四、ARM汇编的常用指令

4.1 数据处理指令

指令类型 指令
数据传输指令 mov mvn
算术指令 add sub rsb adc sbc rsc
逻辑指令 and orr eor bic
比较指令 cmp cmn tst teq
乘法指令 mvl mla umull umlal smull smlal
前导零计数 clz

4.2 CPSR访问指令

CPSR寄存器比较特殊,需要专门的指令进行访问

指令类型 指令
mrs 读取psr
msr 写入psr

4.3 跳转指令

指令 作用
b 直接跳转(跳转后不返回)
bl 跳转前把返回地址放入lr中,用于函数调用返回
bx 跳转同时切换到ARM模式,用于异常处理的跳转

4.4 访存、软中断指令

ldr/str每周期只能访问4字节内存,如果需要批量读取、写入内存时太慢

stm/ldm每周期可以批量读取、写入内存

指令 作用
ldr/str 单个字/半字/字节访问
ldm/stm 多字批量访问
swi(software interrupt) 软中断指令,用来实现操作系统中系统调用

4.5 协处理器操作指令

1、SoC内部另一处理核心,协助主CPU实现某些功能,被主CPU调用执行一定任务
2、ARM设计上支持16个协处理器,一般SoC只实现其中的CP15
3、协处理器和MMU、 cache、 TLB等处理有关
4、功能上和操作系统的虚拟地址映射、cache管理等有关
指令 作用
mrc 用于读取CP15中的寄存器
mcr 用于写入CP15中的寄存器

五、ARM汇编符号的作用

5.1 ! 的作用

ldmia r0   , {r2 - r3}
ldmia r0! , {r2 - r3}

!的作用

r0的值在ldm过程中发生的增加或者减少最后写回到r0去

也就是说ldm时会改变r0的值。

5.2 ^ 的作用

ldmfd sp!, {r0 - r6, pc}
ldmfd sp!, {r0 - r6, pc}^

^ 的作用:在目标寄存器中有pc时,会同时将spsr写入到cpsr,一般用于从异常模式返回

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐