欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

ARM汇编

程序员文章站 2022-06-09 08:22:35
...

数据操作(ALU操作)

1、数学操作

Opcode Operands Deacription Function
ADC Rd,Rn,Op2 带进位的加 Rd=Rn+Op2+c
ADD Rd,Rn,Op2 Rd=Rn+Op2
MOV Rd,Op2 数据传送 Rd=Op2
MVP Rd,Op2 数据取反传送 Rd=~Op2
RSB Rd,Rn,Op2 翻转减 Rd=Op2-Rn
RSC Rd,Rn,Op2 反转减 Rd=Op2-Rn-!C
SBC Rd,Rn,Op2 带进位的减法 Rd=Rn-Op2-!C
SUB Rd,Rn,Op2 Rd=Rn-Op2
MUL Rd,RmRs 32位乘法 Rd=Rm*Rs
MLA Rd,Rm,Rs,Rn 32位累加乘法 Rd=Rm*Rs+Rn
UMULL RdLo,RdHi,Rm,Rs 64位无符号乘法 (RdLo,RdHi)=Rm*Rs

2、逻辑操作

Opcode Operands Deacription Function
AND Rd,Rn,Op2 逻辑与 Rd=Rn&Op2
BIC Rd,Rn,Op2 位清零 Rd=&~Op2
EOR Rd,Rn,Op2 逻辑或与 Rd=Rn^Op2
ORR Rd,Rn,Op2 逻辑或 Rd=Rn

3、比较操作

Opcode Operands Deacription Function
CMP Rn,Op2 比较 Rn-Op2
CMN RN,Op2 负数比较 Rn+Op2
TEQ Rn,Op2 测试相等 Rn&Op2
TST Rn,Op2 测试 Rn^Op2

ARM堆栈—先进后出

1、满堆栈
2、空堆栈
3、递增堆栈
4、递减堆栈

内存操作 - 读取内存


Opcode Operands Deacription Function
单寄存器读写指令
LDR Rn,Addr 按照字节读取长度
STR
LDRB
LDRH
STRB
LDRH
STRH
LDRBT
STRBT
LDRT
STRT
LDRSB
LDRSH
LDRSH
多寄存器内存访问指令
LDM LDMIA R0!,{R3-R9}
STM STMIA R1,{R3-R9}

地址模式:
数据块模式:IA(传输后地址加4),IB(传输前地址加4),DA(传输后地址减4),DB(传输前地址减4)

堆栈模式:满底层堆栈),EA(空递减堆栈),FD(满递减堆栈),ED(空递增堆栈),FA(满递增堆栈)


数据交换指令


SWAP Rd,Rn,[Rn2] 内存和寄存器字交换 [Rn2]->Rd,Rn1->[Rn2]:如果Rd和Rn1相同就是直接交换
SWPB 字节交换

跳转、状态操作


Opcode Operands Deacription Function
B 跳转指令 pc<-label
BL 带返回的连接跳转 pc<-label
BX 跳转并切换状态Thumb
BLX 待返回的跳转并切换状态Thumb
状态寄存器操作 把32位指令分为4个域:[7:0]控制位域c,[15:8]扩展位域x,[23:16]状态位域s,[31:24]:条件标志位域f
MRS 把程序状态寄存器的值传送到通用寄存器
MSR CPSR,R0,SPSR,R0,CPSR_c,R0 通用寄存器到程序状态寄存器
异常产生指令
SWI SWI 0x02 软中断指令
BKPT BKPT 断点中断指令

伪指令

伪指令作用及类别
————我们的指令已经可以做各类操作库,但我们操作起来太麻烦了。
比如我现在要设置一个值给寄存器R0,但下次我修改了寄存器R0之后又需要都出来刚才的值,那我们就要先临时保存值到SPSR or CPSR,然后不断切换。
再比如,我们要做一个循环,就要用label结合BL不断进行,但如果我们要循环很多次。
我们就定义了一些类似带参数的宏的操作数一样,来定义我们的伪指令,方便我们更好的实现汇编程序逻辑。伪指令只是在汇编之前作用,汇编之后就会翻译成为标准的汇编指令。
我们又分为ARM汇编伪指令和GUN汇编伪指令。

基本常用伪指令


Opcode Operands Deacription Function
AREA AREA test,CODE,READONLY 声明区域段,数据区,代码区等等
CODE16,CODE32 CODE32 声明以下是32位还是16位指令,注意不是切换arm和thumb模式,只是告诉汇编器
ENTRY ENTRY伪指令用于指定汇编程序的入口点。在一个完整的汇编程序中至少要有一个ENTRY(也可以有多个,当有多个ENTRY时,程序的真正入口点由链接器指定),单在一个源文件里最多有一个ENTRY(可以没有)。
END END END伪指令用于通知编译器到了源程序的结尾
EQU UARTLCON0 EQU 0x3FFD000 EQU伪指令用于为程序的常量、标号等定义一个等效的字符名称,类似于c语言中的#define。其中EQU可用*代替
EXPORT .global EXPORT伪指令用于在该程序中声明一个全局的标号,该编号可在其他的文件中引用。EXPORT可用GLOBAL代替,标号在程序中区分大小写,【WEAK】选项声明其他的同名标号优先于该标号被引用
IMPORT 相当于静态引用 IMPORT伪指令用于通知编译器要使用的标号在其他的源文件中定义,但要在当前源文件中引用,而且无论当前源文件是否引用该标号,该标号均会被加入当前源文件的符号中
EXTERN 相当于动态引用 EXTREN伪指令用于通知编译器要使用的标号在其他的源文件中定义,但要在当前源文件中引用,如果但当前源文件实际并未引用该标号。该标号就不会被加入到当前源文件的符号中
GET 相当于引用文件 GET伪指令用于将一个源文件包含的源文件中,并将被包含的源文件在当前位置进行汇编处理。可以实用INCLUDE代替GET|
RN RN伪指令用于给一个寄存器定义一个别名。采用这种方式可以方便程序员记忆寄存器的功能。其中,名称为给寄存器定义的别名,表达式为寄存器的编码

在汇编语言程序中常用的符号

符号命名约定  
- - -符号区分大小写,同名的大,小写符号会被编译器认为是两个不同的符号

- - -符号在其作用的范围内会被编译器认为是两个不同的符号
- - -自定义的符号名不能与系统的保留字相同
- - - 符号名不应与指令或伪指令同名
- - -关于ADS里面可恶的Tab和顶行“ADS Style”

符号,变量

ARM(Thumb)汇编程序所支持的变量有数字变量,逻辑变量和字符串变量

Opcode Operands Deacription Function
GBLA/GBLL/GBLS GBLA Test3 定义全局数字/逻辑/字符串变量
LBLA/LBLL/LBLS LBLA Test3 声明局部变量
SETA/SETL/SETS Test SETA 0xaa 设置变量值 不能有Tab
RLIST RegList RLIST{R0-R5,R8,R10} 将寄存器立标名称定义为RegList ,可在ARM指令LDM/STM中通过该名称访问寄存器列表。 不能有Tab

FAQ ?
定义变量存储在寄存器中还是内存中?

**变量代换: ”Sample- -LCLS S1    - -LCLS S2  - -S1 SETS “Test!” - -S2 SETS  “This is a $S1”;字符串变量S2的值为“This is a Test!”
表达式和运算 : -“+” , ”-“,   ” *”,“ /”及MOD算数运算符///////////////////////”ROL“,”ROR“,”SHL“,及SHR移位运算符//////////////////////”AND“,”OR“,”NOT“及”EOR“按位运算符/////////////////////////////////////////////////////////////////////////////////////////”=“,”>“,”<“,”>=“,”<=“,”/=“,”<>“运算符”LAND“,”LOR“,”LNOT“,及”LEOR“运算符

变量:数字常量一般为32为的整数,当作为无符号数时,起取值范围为0~232-1,当作为有符号数时,其取值范围为-231~231.//逻辑常量只有两种取值情况:真或假//字符串常量为一个固定的字符串,一般用于程序运行时的信息提示
寄存器操作

数据定义伪指令

Opcode Operands Deacription Function
LDR R0,=0x12 某时候可以提到MOV,MVN 大范围寻址到寄存器-绝对寻址
ADR 小范围寻址到寄存器+-255-相对寻址
ADR 中范围寻ARM汇编ARM汇编

控制伪指令

ARM汇编