ARM指令集

        由于RAM采用了流水线机制,当读取PC值时,该值为当前指令地址值加8,也就是PC指向当前指令的下2条指令。

        由于RAM指令是4字节对齐的,所以PC值的第0位和1位始终为0

        使用STR/STM保存R15时,保存的是当前指令地址加8字节或者12字节,所以对于用户来说,尽量避免使用STR/STM来保存R15的值

如果非要用STR/STM来保存R15,那可以这样判断是加8字节还是12字节:

        SUB  R0,PC,   #4

        STR  PC,   [R1]

        LDR  R0,   [R0]

        SUB  R0,  R1, R0

最后R0中的值就是offset偏移值

寄存器移位方式:

ASR:   算术右移      考虑正负符号,在移位过程中符号不变,适合 signed 类型

ASL: 算术左移

LSL:    逻辑左移      适合unsigned 类型

LSR: 逻辑右移      适合unsigned 类型

ROL:   循环左移

ROR:   循环右移       

RRX:   扩展的循环右移

循环移位也容易理解。比如我们有个1字节的数: x = 10111110。现在需要对其循环右移4位。也就是最后结果为x = 11101011。其实思路就是分离数据,我们需要提取出前四位1011,后四位1110。其实我们需要两个数的或操作,也就是00001011,11100000,我们只要得到这两个数然后让他们就行或操作:00001011|11100000 =11101011。把10111110 右移4位变为00001011(x>>4),把10111110左移4位变为11100000(x<<4),注意移位后的“空格”是用0填充的。最后执行或操作。

循环左移n位: (x>>(N - n) ) | (x<<n);

循环右移n位: (x<<(N - n) ) | (x>>n)

Load指令用于从内存中读取数据放入寄存器;Store指令用于寄存器中的数据保存到内存中。

【】里面默认作加法运算:

LDR R0, [R1, R2, LSL  #2]      意思是将(R1 + R2 << 2)的值存到寄存器R0中

 

LDR R0, [R1, #4]!                    意思是将(R1 + 4)中的内容读到R0寄存器,同时R1 = R1 + 4

LDR R0,  [R1], #4                    意思是将R1寄存器中的值放入R0寄存器中,同时R1 = R1 + 4

LDR R0, [R1], R2, LSL #2       意思是将R1中的数据读取到R0中,同时R1 = R1 + R2 << 2

LDRSB R0, [R1,#3]                 意思是将(R1 + 3)中的有符号数据读取到R0中,R0中高24位设置成该字节数据的符号位

位B用于控制指令操作的数据类型,=1时指令访问的是无符号的字节数据; =0时访问的是字数据

位S用于控制半字访问的数据类型,=1时数据为带符号数; =0时数据为无符号数

STRH R0, [R1,R2]                   意思是将R0中的低16位数据保存到内存单元(R1 + R2)中

STRH R0,[R1], #8                   意思是将R0中的低16位数据读取到R1中,R1 = R1 + 8

LDRH R0, [R1,R2]!                 意思是将(R1 + R2)中的半字数据读取到R0中,R0高16位设置为0;R1 = R1 + R2

LDRSH R7, [R6, #2]                意思是将(R6 + 2)单元中的字节数据读取到R7中,R6中高16位设置成该半字的符号位;R6 = R6 + 2

 

IA    :     a++

IB    :     ++a

DA   :    a--

DB  :     --a

 

LDMIA R0, {R5 - R8} ;   将R0到(R0 + 12)寄存器中的值分别读取到R5 到 R8寄存器中

 BL   FUNC_1   ;     程序跳转到FUNC_1处执行,同时将当前PC值保存到LR中

 BCC    Lable   ;     当CPSR寄存器中的C条件标志位为1时,程序跳转到Lable处执行

 

数据处理指令:

MVN     数据求反传送指令

CMP     比较指令

CMN     基于相反数的比较指令

CMP Rn, #0   ;    (Rn) - 0没有发生借位。CPSR中的条件标志位C = 1

CMN Rn, #0  ;     (Rn) + 0没有发生溢出,CPSR中的条件标志位C = 0

TST      位测试指令

TEQ     相等测试指令

RSB     逆向减法指令

             RSB   Rd,  Rx, #0   ;   Rd = 0 - Rx

             RSB   Rd,  Rx, Rx, LSL #n  ;    Rd = Rx << n - Rx

ADC    带位加法指令

SBC     带位减法指令

RSC     带位逆向减法指令

AND     逻辑与操作

BIC      位清除指令

EOR    逻辑异或操作

ORR    逻辑或操作

 

SUBS    R4, R0, R2

SBC      R5, R1, R3

SUBS 和 SBC指令联合使用可以实现64位的操作数相减

R0中存放被减数的低32位,R2中存放减数的低32位,最后得到的结果是R4存放低32位,R5存放高32位

指令语法格式:  SBC{<cond>}  {S} <Rd> , <Rn>  , <shifter_operand>

S决定指令的操作是否影响CPSR中的条件标志位的值: 有S时指令更新CPSR中的条件标志位,没有就不更新

 

同样,ADDS 和ADC联合使用可以实现64位操作数相加

ADDS R4, R0, R2

ADC   R5, R1, R3

 

状态寄存器访问指令:

MRS       用于将状态寄存器的内容传送到通用寄存器

MSR       用于将通用寄存器的内容或一个立即数传送到状态寄存器

 

LDRB  R0, [R2, #3]    ;    将内存单元(R2 + 3)中的低8位数据读取到R0,R0中的高24位设置为0

LDRH  R0, [R1, #3]    ;    将(R1 + 3)中的低16位数据读取到R0中,R0中的高16位设置为0

LDRSB  R0, [R2, #3]    ;    将内存单元(R2 + 3)中有符号的字节数据读取到R0,R0中的高24位设置为该字节的符号位

LDRSH  R0, [R1, #3]    ;    将(R1 + 3)中的有符号的半字数据读取到R0中,R0中的高16位设置为该半字的符号位

LDRT  用户模式的字数据读取指令

STRT 用户模式的字数据写入指令

STRBT 用户模式的字节数据写入指令

 

乘法指令:

MUL 32位乘法指令

MLA 32位带加法乘法指令

SMULL 64位有符号数的乘法指令

SMLAL 64位有符号数带加法指令

UMULL 64位无符号数乘法指令

UMLAL 64位带加法的无符号数乘法指令

 

批量Load/Store指令:

 

SWP   交换指令

SWPB  字节交换指令

 

SWP R1, R2, [R3]  ;   将(R3)中的字数据读取到R1中,同时将R2中的数据写入(R3)中

SWPB  R1, R2, [R3]  ;   将(R3)中的字节数据读取到R1中,R1中高24位置0,同时将R2中的低8位数据写入(R3)中

 

条件码:

EQ     相等

NE     不相等

CS/HS    无符号数大于/等于

CC/LO    无符号数小于

MI        负数

PL        非负数

VS        上溢出

VC        没有上溢出

HI          无符号数大于

LS         无符号数小于等于

GE        带符号数大于等于

LT         带符号数小于

GT       带符号数大于

LE       带符号数小于/等于

AL       无条件执行

NV       该指令从不执行

 

符号定义伪操作:

GBLA    全局的算术变量    初始化为0

GBLL    全局的逻辑变量     初始化为{FALSE}

GBLS    全局的串变量        初始化为空串“”

 

LCLA     局部的算术变量

LCLL     局部的逻辑变量

LCLS    局部的串变量

 

RLIST    给寄存器列表定义名称

Context   RLIST     {r0 - r6.r8,r10 - r12, r15}

 

CN       为一个协处理器的寄存器定义名称

数据定义伪操作:

SPACE      分配一块内存单元,并用0初始化,%是同义词

DCB      分配一段字节的内存单元,并用指定的数据初始化,=是同义词

DCD/DCDU       分配一段字的内存单元,并用指定的数据初始化, &是DCD同义词

DCDO    分配一段字的内存单元,并将这个单元的内容初始化为该单元相对于静态基值寄存器的偏移量

 

MAP  用于定义一个结构化的内存表的首地址,^是同义词

FIELD  用于定义一个结构化内存表的数据域,#是同义词

MAP  和   FIELD 仅仅是定义数据结构,并不实际分配内存单元

DCD与DCDU的区别在于DCDU分配的内存单元并不严格字对齐

 

汇编控制伪操作:

IF   ELSE   ENDIF

WHILE  WEND

MACRO  标识宏定义的开始    MEND   标识宏定义的结束

MEXIT  用于从宏中跳转出来

 

信息报告伪操作:

ASSERT  汇编编译器对汇编程序的第二遍扫描中,如果logical   expression条件不成立,打印错误信息

ASSERT    logical   expression

 

INFO   伪操作支持在汇编处理过程中的第一遍扫描或第二遍扫描时报告诊断信息

INFO      numeric-expression,    string-expression

如果  numeric-expression = 0   第二遍扫描打印信息;如果  numeric-expression != 0   第一遍扫描打印信息;

INFO   0,   "Version   1.0"

IF   endofdata <= label1

INFO  4,   "Data   overrun   at   label1"

ENDIF

 

OPT   通过OPT可以在源程序中设置列表选项

 

其他伪操作:

ALIGN:     对齐

ALIGN  2   按2^2 = 4字节对齐

AREA     

CODE16    告诉汇编编译器后面的指令序列为16位的Thumb指令

CODE32    告诉汇编编译器后面的指令序列为16位的Thumb指令,它们本身并不进行程序状态的切换

EQU     * 是同义词       类似于c语言中的#define

abcd    EQU   2

addr1   EQU   0x1C,   CODE32      ;       该处为ARM指令

 

EXPORT及GLOBLE

GET/INCLUDE       include

INCBIN        包含编译好的文件,比如可执行文件

 

ARM汇编语言语句格式:

 在ARM汇编语言中,指令不能从一行的行头开始,在一行语句中,指令的前面必须有空格或者符号

当程序中的符号与指令助记符或伪操作同名时,用双竖线符号括起来,如||require||,这时双竖线并不是符号的组成部分。

 

posted @ 2018-10-08 20:35  一条水煮鱼  阅读(992)  评论(0编辑  收藏  举报