常用ARM汇编指令

转载:https://blog.csdn.net/neutionwei/article/details/82559248

一. 带点的(一般都是ARM GNU伪汇编指令)

1. “.text”、”.data”、”.bss”

依次表示的是

“以下是代码段”,

“以下是初始化数据段”,

“以下是未初始化数据段”。

2.”.global”

定义一个全局符号,通常是为ld使用。比如经常看到的

.global _start

3.”.ascii”、”.byte”、”.short”、”.int”、”.long”、”.word”、”.quad”

定义一个字符串,并为它分配空间

定义一个字节,并为它分配空间,占单字节,0x34

定义一个短整型,并为它分配空间,占双字节,0x1234

定义一个整型,并为它分配空间,占四字节,0x12345678

定义一个长整型,并为它分配空间,占四字节,0x12345678

定义一个字,并为它分配空间,

定义一个,并为它分配定义,占八字节,…

比如
.long 0x22011110//BWSCON
.long 0x00000700//BANKCON0

4.”.abort”

停止汇编

5.”.align”

.align absexpr1,absexpr2

以某种对齐方式,在未使用的存储区域填充值. 第一个值表示对齐方式,4, 8,16或32. 第二个表达式值表示填充的值

6.”.if .else .endif”

.if

.else

.endif:支持条件预编译

7.”.include”

.include “file”:包含指定的头文件, 可以把一个汇编常量定义放在头文件中

8.”.comm”

.comm  symbol, length:

在bss段申请一段命名空间,该段空间的名称叫symbol, 长度为length. Ld连接器在连接会为它留出空间

9.”.equ”

.equ symbol, expression: 把某一个符号(symbol)定义成某一个值(expression).该指令并不分配空间,相当于c语言中的#define。例如

.equ aaa,0x20000000

10.”.macro .endm”

.macro: 定义一段宏代码,.macro表示代码的开始,.endm表示代码的结束,.exitm跳出宏, 示例如下:

.macro SHIFTLEFT a, b.if \b < 0

mov \a, \a, ASR #-\b

.exitm

.endif

mov \a, \a, LSL #\b

.endm

11.”.req”

name .req register name: 为寄存器定义一个别名

12.“.code”

.code [16|32]: 指定指令代码产生的长度, 16表示Thumb指令, 32表示ARM指令

13.”.ltorg”

.ltorg: 表示当前往下的定义在归于当前段,并为之分配空间

二.带下滑线的

1._start

汇编程序的缺省入口,但是可以更改,想要更改其他标志,到相应的链接脚本中去用ENTRY指明其他入口标志。标号可以直接认为是地址。

三.不带点的

1.mov–数据传送指令

它的传送指令只能是把一个寄存器的值(要能用立即数表示)赋给另一个寄存器,或者将一个常量赋给寄存器,将后边的量赋给前边的量,比如

mov r1,r2

mov r1,#4096

这个立即数是小于0xff(65535)的数,如果大于65535,则用ldr指令赋值

2.b、bl–相对跳转指令

b只是跳转,而bl除跳转外还将返回地址(bl的下一条指令的地址)保存到lr寄存器中。其中跳转范围是当前指令的前后32M。

3.ldr、str LDRB、LDRH –内存访问指令

—  LDR     字数据加载指令

— LDRB    字节数据加载指令

—  LDRH    半字数据加载指令

1)     LDR指令有两种用法:

a、ldr加载指令
LDR指令的格式为:
LDR{条件}  目的寄存器,<存储器地址>
LDR指令用亍从存储器中将一个32位的字数据传送到目的寄存器中。该指令通常用于从存储器中读取32位的字数据到通用寄存器,然后对数据迕行处理。当程序计数器PC作为目的寄存器时,指令从存储器中读取的字数据被当作目的地址,从而可以实现程序流程的跳转。该指令在程序设计中比较常用,丏寻址方式灵活多样,请读者认真掌握。
指令示例:
LDR R0,[R1]        ;将存储器地址为R1的字数据读入寄存器R0。
LDR R0,[R1,R2]  ;将存储器地址为R1+R2的字数据读入寄存器R0。
LDR R0,[R1,#8]   ;将存储器地址为R1+8的字数据读入寄存器R0。
LDR R0,[R1,R2]!;将存储器地址为R1+R2的字数据读入寄存器R0,并将新地址R1+R2写入R1。
LDR R0,[R1,#8]!  ;将存储器地址为R1+8的字数据读入寄存器R0,并将新地址R1+8写入R1。 
LDR R0,[R1],R2  ;将存储器地址为R1的字数据读入寄存器R0,并将新地址R1+R2写入R1。
LDR R0,[R1,R2,LSL#2]!  ;将存储器地址为R1+R2×4的字数据读入寄存器R0,并将新地址R1+R2×4写入R1。
LDR R0,[R1],R2,LSL#2  ;将存储器地址为R1的字数据读入寄存器R0,幵将新地址R1+R2×4写入R1。”

ARM是RISC结构,数据从内存到CPU间的移劢只能通过L/S指令来完成,也就是ldr/str指令。  
比如想把数据从内存中某处读取到寄存器中,只能使用ldr 
比如: 
ldr r0, 0x12345678 
就是把0x12345678返个地址中的值存放到r0中。

b、ldr伪指令
ARM指令集中,LDR通常都是作加载指令的,但是它也可以作伪指令。
LDR伪指令的形式是“LDRRn,=expr”。
例子:
COUNT EQU       0x40003100
……
LDR       R1,=COUNT
MOV      R0,#0
STR       R0,[R1]

COUNT是我们定义的一个变量,地址为0x40003100。这种定义方法在汇编语言中是很常见的,如果使用过单片机的话,应该都熟悉这种用法。
LDR       R1,=COUNT是将COUNT这个变量的地址,也就是0x40003100放到R1中。
MOV      R0,#0是将立即数0放到R0中。最后一句STR     R0,[R1]是一个典型的存储指令,将R0中的值放到以R1中的值为地址的存储单元去。实际就是将0放到地址为0x40003100的存储单元中去。

下面还有一个例子
;将COUNT的值赋给R0
LDR       R1,=COUNT
LDR       R0,[R1]
LDR       R1,=COUNT这条伪指令,是怎样完成将COUNT的地址赋给R1,有兴趣的可以看它编译后的结果。这条指令实际上会编译成一条LDR指令和一条DCD伪指令。

2)     LDRB指令

LDRB指令的格式为:

LDR{条件}B 目的寄存器,<存储器地址>

LDRB指令用于将存储器中低8位的字节数据传送到目的寄存器中,同时将寄存器的高24位清零,然后对数据进行处理。当程序计数器PC作为目的寄存器时,指令从存储器中读取的数据被当作目的地址,从而可以实现程序流程的跳转。

指令示例:

LDRB R0,[R1]         ;将存储器地址为R1的字节数据读入寄存器R0,并将R0的高24位清零。

LDRB R0,[R1,#8]    ;将存储器地址为R1+8的字节数据读入寄存器R0,并将R0的高24位清零。

3)     LDRH指令

LDRH指令的格式为:

LDR{条件}H 目的寄存器,<存储器地址>

LDRH指令用于将存储器中低16位的半字数据传送到目的寄存器中,同时将寄存器的高16位清零,然后对数据进行处理。当程序计数器PC作为目的寄存器时,指令从存储器中读取的字数据被当作目的地址,从而可以实现程序流程的跳转。

指令示例:

LDRH R0,[R1]         ;将存储器地址为R1的半字数据读入寄存器R0,并将R0的高16位清零。

LDRH R0,[R1,#8]    ;将存储器地址为R1+8的半字数据读入寄存器R0,并将R0的高16位清零。

LDRH R0,[R1,R2]    ;将存储器地址为R1+R2的半字数据读入寄存器R0,并将R0的高16位清零。

— STR     字数据存储指令

— STRB    字节数据存储指令

— STRH    半字数据存储指令

A、STR指令的格式为

STR{条件} 源寄存器,<存储器地址>

STR指令用于从源寄存器中将一个32位的字数据传送到存储器中。该指令在程序设计中比较常用,且寻址方式灵活多样,使用方式可参考指令LDR。

指令示例:

STR   R0,[R1],#8    ;将R0中的字数据写入以R1为地址的存储器中,并将新地址R1+8写入R1。

STR   R0,[R1,#8]    ;将R0中的字数据写入以R1+8为地址的存储器中。

B、STRB指令的格式为:

STR{条件}B 源寄存器,<存储器地址>

STRB指令用于从源寄存器中将一个8位的字节数据传送到存储器中。该字节数据为源寄存器中的低8位。

指令示例:

STRB R0,[R1]         ;将寄存器R0中的字节数据写入以R1为地址的存储器中。

STRB R0,[R1,#8]    ;将寄存器R0中的字节数据写入以R1+8为地址的存储器中。

C、STRH指令的格式为:

STR{条件}H 源寄存器,<存储器地址>

STRH指令用于从源寄存器中将一个16位的半字数据传送到存储器中。该半字数据为源寄存器中的低16位。

指令示例:

STRH R0,[R1]         ;将寄存器R0中的半字数据写入以R1为地址的存储器中。

STRH R0,[R1,#8]    ;将寄存器R0中的半字数据写入以R1+8为地址的存储器中
 

4.adr–小范围的地址读取(只有两个参数)

ADR指令将基于PC相对偏移的地址值读取到寄存器中,在编译源程序时ADR伪指令被编译器替换成一条合适的指令。通常,编译器用一条ADD指令或SUB指令来实现该ADR伪指令的功能,若不能用一条指令实现,刚产生错误,编译失败。比如

adr r0, delay//将标号delay的地址赋给r0

5.ldmia–多寄存器寻址

一条指令可以完成多个寄存器值的传递,可以完成最多16个通用寄存器值的传递。比如

ldmia r0, [r1, r2, r3, r4]

;r1 <- [r0]

;r2 <- [r0+4]

;r3 <- [r0+4*2]

;r4 <- [r0+4*3]

6.nop–空操作指令

什么都不做,可以用作延时。

7.add,sub–加法减法指令

共三个参数,将后边的两个参数操作并赋给第一个参数,比如

add r1, r1, r0//r1=r1+r0

sub r1, r1, r2//r1=r1-r2

//这两句的结果就是r1=r1+r0-r2

SUB R0, R2,R3,LSL#1 ; R0 = R2 - (R3 << 1)

8.asr,lsl,lsr,ror,rrx,type rs

对于arm指令的基本格式如下:

对于operand2参数,如果能灵活使用,代码效率会很高。

9.CMP 、TST、BNE、BEQ

CPSR

10.eq,ne,ce等–指令的条件域

所有的ARM指令都可以条件执行:指令的执行与否取决于CPSR寄存器的N,Z,C and V

每一条ARM指令包含4位的条件码位于指令的最高4位[31:28],条件码共16种,每个条件码可以用2个字符表示,这两个字符可以添加在指令助记符的后边和指令同时使用。指令最高4位代表的条件域如下表

条件码

助记符后缀

标志

含义

0000

EQ

Z置位

相等

0001

NE

Z清零

不相等

0010

CS

C置位

无符号数大于或等于

0011

CC

C清零

无符号数小于

0100

MI

N置位

负数

0101

PL

N清零

正数或零

0110

VS

V置位

溢出

0111

VC

V清零

未溢出

1000

HI

C置位Z清零

无符号数大于

1001

LS

C清零Z置位

无符号数小于或等于

1010

GE

N等于V

带符号数大于或等于

1011

LT

N不等于V

带符号数小于

1100

GT

Z清零且(N等于V)

带符号数大于

1101

LE

Z置位或(N不等于V)

带符号数小于或等于

1110

AL

忽略

无条件执行

对照普通的减法指令 SUB AX, BX,它们的区别就在于:
SUB指令执行过以后,原来AX中的被减数丢了,被换成了减法的结果。
CMP指令执行过以后,被减数、减数都保持原样不变。

TST:

逻辑处理指令,用于把一个寄存器的内容和另一个寄存器的内容或立即数进行按位与运算,并根据运算结果更新CPSR中条件标志位的值。当前运算结果为非0,则Z=0;当前运算结果为0,则Z=1

BNE:数据跳转指令,标志寄存器中Z标志位等于零时,跳转到BNE后标签处。特别要注意这里,通常我们说BNE是“不相等”或“不为零”时跳转,此处的“不相等”或“不为零”是指比较结果不相等或做减法不为零,不是指Z标志位。比较结果不相等或做减法不为零时,Z标志位是等于零的。

BEQ:数据跳转指令,标志寄存器中Z标志位不等于零时, 跳转到BEQ后标签处

11.R13,R14寄存器–sp,lr

sp是堆栈指针,lr是链接地址寄存器。R13作为sp,R14作为lr。
对于链接地址寄存器,它的作用有两个:

【1】当使用bl指令调用子程序时,系统会自动将 bl指令的下一条指令的地址存入lr中。

执行过程如下图

①,程序A正常执行到BL Lable然后转到程序B中去
②,系统将BL Lable的下一句NEXT的地址放到LR中去
③,执行完B的程序后,执行一个MOV PC,LR将NEXT的地址给到当前pc值
④,继续执行程序A下面的语句

2】当发生异常时,系统自动将异常的返回地址放入R14中(有些异常有一个小的固定的偏移量)。

12.逻辑运算指令–

;按位与

AND Rd, Rn                                 ; Rd &= Rn

AND.W Rd, Rn, #imm12           ; Rd = Rn & imm12

AND.W Rd, Rm, Rn                    ; Rd = Rm & Rn

;按位或

ORR Rd, Rn                                  ; Rd |= Rn

ORR.W Rd, Rn, #imm12            ; Rd = Rn | imm12

ORR.W Rd, Rm, Rn                     ; Rd = Rm | Rn

 

;按位清零

BIC Rd, Rn                                    ; Rd &= ~Rn

BIC.W Rd, Rn, #imm12             ; Rd = Rn & ~imm12

BIC.W Rd, Rm, Rn                      ; Rd = Rm & ~Rn

 

;按位或反

ORN.W Rd, Rn, #imm12          ; Rd = Rn | ~imm12

ORN.W Rd, Rm, Rn                   ; Rd = Rm | ~Rn

 

;按位异或

EOR Rd, Rn                                 ; Rd ^= Rn

EOR.W Rd, Rn, #imm12           ; Rd = Rn ^ imm12

EOR.W Rd, Rm, Rn                    ; Rd = Rm ^ Rn

 

;逻辑左移

LSL Rd, Rn, #imm5                  ; Rd = Rn<<imm5

LSL Rd, Rn                                 ; Rd <<= Rn

LSL.W Rd, Rm, Rn                   ; Rd = Rm<<Rn

 

;逻辑右移

LSR Rd, Rn, #imm5                ; Rd = Rn>>imm5

LSR Rd, Rn                               ; Rd >>= Rn

LSR.W Rd, Rm, Rn                  ; Rd = Rm>>Rn

 

;算术右移

ASR Rd, Rn, #imm5                 ; Rd = Rn>> imm5

ASR Rd, Rn                                ; Rd =>> Rn

ASR.W Rd, Rm, Rn                   ; Rd = Rm>>Rn

 

;循环右移

ROR Rd, Rn ;

ROR.W Rd, Rm, Rn ;

13、跳转指令B、BL、BX、BLX 和 BXJ的区别


跳转指令用于实现程序流程的跳转,在 ARM 程序中有两种方法可以实现程序流程的跳转:

(1) 使用专门的跳转指令。

(2) 直接向程序计数器 PC 写入跳转地址值。

通过向程序计数器 PC 写入跳转地址值,可以实现在4GB 的地址空间中的任意跳转,在跳转之前结合使用

MOV LR , PC

等类似指令,可以保存下一条指令地址作为将来的返回地址值,从而实现在 4GB 连续的线性地址空间的子程序调用。

专门的跳转指令:

B、BL、BX、BLX 和 BXJ

跳转、带链接跳转(带返回的跳转)、跳转并切换指令集、带链接跳转并切换指令集(带返回的跳转并切换指令集)、跳转并转换到 Jazelle 状态。

a)     、 B 指令

B 指令的格式为:

B{条件} 目标地址

B 指令是最简单的跳转指令。一旦遇到一个 B 指令,ARM 处理器将立即跳转到给定的目标地址,从那里继续执行。注意存储在跳转指令中的实际值是相对当前PC 值的一个偏移量,而不是一个绝对地址,它的值由汇编器来计算(参考寻址方式中的相对寻址)。它是 24 位有符号数,左移两位后有符号扩展为 32 位,表示的有效偏移为 26 位(前后32MB 的地址空间)。以下指令:

B Label ;程序无条件跳转到标号 Label 处执行

CMP R1 ,# 0 ;当 CPSR 寄存器中的 Z 条件码置位时,程序跳转到标号Label 处执行

BEQ Label

b) 、 BL 指令

BL 指令的格式为:

BL{条件} 目标地址

BL 是另一个跳转指令,但跳转之前,会在寄存器R14 中保存PC 的当前内容,因此,可以通过将R14 的内容重新加载到PC 中,来返回到跳转指令之后的那个指令处执行。该指令是实现子程序调用的一个基本但常用的手段。以下指令:

BL Label ;当程序无条件跳转到标号 Label 处执行时,同时将当前的 PC 值保存到 R14(lr) 中

c) 、 BLX 指令

BLX 指令的格式为:

BLX 目标地址

BLX 指令从ARM 指令集跳转到指令中所指定的目标地址,并将处理器的工作状态有ARM 状态切换到Thumb 状态,该指令同时将PC 的当前内容保存到寄存器R14 中。因此,当子程序使用Thumb 指令集,而调用者使用ARM 指令集时,可以通过BLX 指令实现子程序的调用和处理器工作状态的切换。

同时,子程序的返回可以通过将寄存器R14 值复制到PC 中来完成。

d)     、 BX 指令 

BX 指令的格式为:

BX{条件} 目标地址

BX 指令跳转到指令中所指定的目标地址,目标地址处的指令既可以是ARM 指令,也可以是Thumb指令。

14、STMFD和LDMFD指令


这两条指令分别是入栈和出栈的意思,因此先来讲一下堆栈的相关概念:

a)     满堆栈:即入栈后堆栈指针sp指向最后一个入栈的元素。也就是sp先减一(加一)再入栈。

b)     空堆栈:即入栈后堆栈指针指向最后一个入栈元素的下一个元素。也就是先入栈sp再减一(或加一)。

c)     递增堆栈:即堆栈一开始的地址是低地址,向高地址开始递增。就如同一个水杯(假设上面地址大)开口的是大地址,从杯底开始装水。

d)     递减堆栈:即堆栈一开始的地址是高地址,向低地址开始递增。就如同刚才说的那个水杯,现在开口的是小地址,从大地址开始用。

有这些类型就可以构成4种不同的堆栈方式,arm的栈一般我们用满堆栈、递减堆栈。

一开始,看到 STMFD sp!{R0-R5,LR} 这条命令时真是有点疑惑。STMFD的意思是:ST(store 存储) M(multiple 多次)F(full 满堆栈)D(decrease 递减堆栈),合起来就是按满的递减的方式把后面的寄存器里的值都存到sp中。

STMFD sp!{R0-R5,LR}就是把lr  r5-r0 依次存到sp中,并且sp会在存数据之前自动减一个数据的空间(因为arm栈是递减的)。至于最后一个问题,就是sp后为什么有一个“!”。如果有!号,表示在存入数据后sp会指向最后一个存入的数据的地址,否则sp会把自己的值加到一开始的地址。(就是sp在执行完这条指令之后sp指向的地址不变)。

例子:STMFD sp!,{r0} ;将r0中的值压入堆栈,压入过程是,由于r0中的值为32位的,首先将sp减去4(因为arm栈是递减的),将r0中的低八位放入sp这个位置,第九位到第十六位放入sp+1的地址,将第十七位到第二十四位放入sp+2的位置,将第二十五位到第三十二位放入sp+3的位置。

LDMFD sp!,{r2,r3};将堆栈中的内容出栈,出栈过程是,将sp这个位置的值放入r2中的低八位,将sp+1这个位置的值放入r2中的第九位到第十六位,将sp+2这个位置的值放入r2中的第十七位到第二十四位,将sp+3这个位置的值放入r2中的第二十五位到第三十二位;将sp+4这个位置的值放入r3中的低八位,将sp+5这个位置的值放入r3中的第九位到第十六位,将sp+6这个位置的值放入r3中的第十七位到第二十四位,将sp+4这个位置的值放入r3中的第二十五位到第三十二位。最后sp=sp+8。

此外,STR指令也可以用来入栈:strr1, [sp,#4] ,将r1中的值压入堆栈,压入过程是,由于r1中的值为32位的,将r0中的低八位放入sp+4这个位置,第九位到第十六位放入sp+5的地址,将第十七位到第二十四位放入sp+6的位置,将第二十五位到第三十二位放入sp+7的位置。

15、移位指令(操作)


a)     LSL(或ASL)操作

LSL(或ASL)操作的格式为:

通用寄存器,LSL(或ASL) 操作数     

LSL(或ASL)可完成对通用寄存器中的内容进行逻辑(或算术)的左移操作,按操作数所指定的数量向左移位,低位用零来填充。其中,操作数可以是通用寄存器,也可以是立即数(0~31)。

操作示例

MOV  R0, R1,LSL#2              ;将R1中的内容左移两位后传送到R0中。

b)     LSR操作

LSR操作的格式为:

通用寄存器,LSR 操作数     

LSR可完成对通用寄存器中的内容进行右移的操作,按操作数所指定的数量向右移位,左端用零来填充。其中,操作数可以是通用寄存器,也可以是立即数(0~31)。

操作示例:

MOV  R0, R1, LSR#2           ;将R1中的内容右移两位后传送到R0中,左端用零来填充。

c)     ASR操作

ASR操作的格式为:

通用寄存器,ASR 操作数     

ASR可完成对通用寄存器中的内容进行右移的操作,按操作数所指定的数量向右移位,左端用第31位的值来填充。其中,操作数可以是通用寄存器,也可以是立即数(0~31)。

操作示例:

MOV   R0, R1, ASR#2          ;将R1中的内容右移两位后传送到R0中,左端用第31位的值来填充。

d)     ROR操作

ROR操作的格式为:

通用寄存器,ROR 操作数     

ROR可完成对通用寄存器中的内容进行循环右移的操作,按操作数所指定的数量向右循环移位,左端用右端移出的位来填充。其中,操作数可以是通用寄存器,也可以是立即数(0~31)。显然,当进行32位的循环右移操作时,通用寄存器中的值不改变。

操作示例:

MOV   R0, R1, ROR#2           ;将R1中的内容循环右移两位后传送到R0中。

e)     RRX操作

RRX操作的格式为:

通用寄存器,RRX 操作数     

RRX可完成对通用寄存器中的内容进行带扩展的循环右移的操作,按操作数所指定的数量向右循环移位,左端用进位标志位C来填充。其中,操作数可以是通用寄存器,也可以是立即数(0~31)。

操作示例:

MOV  R0, R1,RRX#2             ;将R1中的内容进行带扩展的循环右移两位后传送到R0中。

f)       SHL和SHR:逻辑移位指令。

SHL是逻辑左移指令,它的功能为:

(1)将一个寄存器或内存单元中的数据向左移位;

(2)将最后移出的一位写入CF中;

(3)最低位用0补充。

指令:
MOV AL,01001000b

SHL AL,1 ;将AL中数据左移一位

执行后(AL)=10010000b,CF=0。

注意:

如果移动位数大于1时,必须将移动位数放在CL中。

比如,指令:

MOV AL,01010001b

MOV CL,3

SHL AL,CL

执行后(AL)=10001000b,因为最后移出的一位是0,所以CF=0。LDRB

SHR是逻辑右移指令,它和SHL所进行的操作刚好相反

16、逻辑指令


a)     AND

逻辑与操作指令。将operand2 值与寄存器Rn 的值按位作逻辑与操作,结果保存到Rd 中。指令格式如下:
        AND{cond}{S} Rd,Rn,operand2
        AND 指令举例如下:
        ANDS R0,R0,#x01 ;R0=R0&0x01,取出最低位数据
        AND R2,R1,R3 ;R2=R1&R3

b)     ORR
        逻辑或操作指令。将operand2 的值与寄存器Rn 的值按位作逻辑或操作,结果保存到Rd 中。指令格式如下:
        ORR{cond}{S} Rd,Rn,operand2
        ORR 指令举例如下:
        ORR R0,R0,#x0F ;将R0 的低4 位置1
        MOV R1,R2,LSR #4
        ORR R3,R1,R3,LSL #8 ;使用ORR 指令将近R2 的高8 位数据移入到R3 低8 位中

c)     EOR
        逻辑异或操作指令。将operand2 的值与寄存器Rn 的值按位作逻辑异或操作,结果保存到Rd 中。指令格式如下:
        EOR{cond}{S}Rd,Rn,operand2
        EOR 指令举例如下:
        EOR R1,R1,#0x0F ;将R1 的低4 位取反
        EOR R2,R1,R0 ;R2=R1^R0
        EORS R0,R5,#0x01 ;将R5 和0x01 进行逻辑异或,结果保存到R0,并影响标志位
 

四.汇编中的注释

(1) @ 表示注释从当前位置到行尾的字符.

(2) # 注释掉一整行.

(3) ; 新行分隔符.

 

五.汇编中的常数

(1)十进制数以非0数字开头,如:123和9876;

(2)二进制数以0b开头,其中字母也可以为大写; 

(3)八进制数以0开始,如:0456,0123;

(4)十六进制数以0x开头,如:0xabcd,0X123f;

(5)字符串常量需要用引号括起来,中间也可以使用转义字符,如: “You are welcome!/n”;

(6)当前地址以“.”表示,在汇编程序中可以使用这个符号代表当前指令的地址;

(7)表达式:在汇编程序中的表达式可以使用常数或者数值, “-”表示取负数, “~”表示取补,“<>”表示不相等,其他的符号如:+、-、*、/、%、<、<<、>、>>、|、&、^、!、==、>=、<=、&&、||跟C语言中的用法相似。

 

 

六.汇编程序较好的格式

 

1、  IMPORT和EXPORT
IMPORT ,定义表示这是一个外部变量的标号,不是在本程序定义的

EXPORT ,表示本程序里面用到的变量提供给其他模块调用的。

以上两个在汇编和C语言混合编程的时候用到。

2、AREA
语法格式:    
    AREA 段名 属性1 ,属性2 ,……    
    AREA伪指令用于定义一个代码段或数据段。其中,段名若以数字开头,则该段名需用“|”括起来,如:|1_test|。    
    属性字段表示该代码段(或数据段)的相关属性,多个属性用逗号分隔。常用的属性如下:    
    — CODE 属性:用于定义代码段,默认为READONLY 。    
    — DATA 属性:用于定义数据段,默认为READWRITE 。    
    — READONLY 属性:指定本段为只读,代码段默认为READONLY 。    
    — READWRITE 属性:指定本段为可读可写,数据段的默认属性为READWRITE 。    
    — ALIGN 属性:使用方式为ALIGN表达式。在默认时,ELF(可执行连接文件)的代码段和数据段是按字对齐的,表达式的取值范围为0~31,相应的对齐方式为2表达式次方。    
    — COMMON 属性:该属性定义一个通用的段,不包含任何的用户代码和数据。各源文件中同名的COMMON段共享同一段存储单元。 
    一个汇编语言程序至少要包含一个段,当程序太长时,也可以将程序分为多个代码段和数据段。    
    使用示例:    
    AREA Init ,CODE ,READONLY ;   该伪指令定义了一个代码段,段名为Init ,属性为只读。

 
 

发布了13 篇原创文章 · 获赞 2 · 访问量 3261

猜你喜欢

转载自blog.csdn.net/wangyangzhizunwudi/article/details/100558497