ARM汇编伪指令笔记

伪指令作用:

 简单的指令拼凑起来,会很难理解,用伪指令可以简化代码结构。就如JAVA中的宏意义一样。例如有一段循环代码,我们可以定义一个常量表示。方便更好的实现程序逻辑。注意:只是在汇编器之前起作用,汇编之后,会翻译为标准的汇编指令集。

Arm汇编伪指令和GNU伪指令是有差别的。

ARM常用伪指令

http://blog.chinaunix.net/uid-13701930-id-336459.html

AREA

1、 AREA

语法格式:

AREA 段名 属性1,属性2,……

AREA伪指令用于定义一个代码段或数据段。其中,段名若以数字开头,则该段名需用“|”括起来,如|1_test|

属性字段表示该代码段(或数据段)的相关属性,多个属性用逗号分隔。常用的属性如下:

— CODE属性:用于定义代码段,默认为READONLY

— DATA属性:用于定义数据段,默认为READWRITE

— READONLY属性:指定本段为只读,代码段默认为READONLY

— READWRITE属性:指定本段为可读可写,数据段的默认属性为READWRITE

— ALIGN属性:使用方式为ALIGN 表达式。在默认时,ELF(可执行连接文件)的代码段和数据段是按字对齐的,表达式的取值范围为031,相应的对齐方式为2表达式次方。

— COMMON属性:该属性定义一个通用的段,不包含任何的用户代码和数据。各源文件中同名的COMMON段共享同一段存储单元。

一个汇编语言程序至少要包含一个段,当程序太长时,也可以将程序分为多个代码段和数据段。

使用示例:

AREA InitCODEREADONLY

EQU——常量声明

类似#define,用法:UARTCON EQU 0x3FFD000

表示UARTCON 和 0x3FFD000等效

参考注意事项.wps,伪指令要顶头书写,不然识别不了。

EXPORT——可用GLOBAL代替,GNU汇编中直接就是.global表示。意思是这段代码可以被全局使用。

EXPORT HELLO

HELLO

MOV R1,R2

对比GNU汇编

.global _hello

_hello:

MOV R1,R2

IMPORT——导入外部函数。相当于静态引用。不管是否被源文件引用,该标号都会被加入源文件中。

EXTERN——动态引用。如果当前源文件并没实际引用该标号,该标号就不会被加入源文件的符号表中。

GET——相当于引用文件,相当于C语言的#include

GET “hello.s”   ;就可以引用hello.s这个文件

RN——给寄存器定义别名;还可以给寄存器组定义别名,参照下面的RLIST

例:

START

SReg RN R0

MOV SReg,#0x12

变量操作

主要考虑作用域、变量类型、变量名称。

注意:都存在内存里,而不是寄存器。

作用域

GBL全局 在整个文件起作用,如果EXPORT了就整个项目起作用。

LBL 局部 在宏定义范围内起作用。

类型

数字 S字符串 逻辑

定义指令

GBLA/GBLS/GBLL  LCLA/LCLS/LCLL

用法——伪指令定义,要缩进

GBLA Var1

设置指令

SETA/SETS/SETL

用法——写在中间。伪指令操作,不能缩进。

ENTRY

START

GBLA Var1

GBLL Bit2

GBLS Name3

Name3 SETS “norton”

Bit2 SETL {TRUE}

Var1 SETA 0x03      ;立即数不能加标识##是常见指令使用的,伪指令不需要。

LDR R0,=Var1   ;常量用 号读取 等价于 LDR R0,=0x03

END

RLIST——给寄存器组定义别名

RegList RLIST {R0-R5,R8,R10}

例子:

ENTRY

START

MOV R3,#0x02

RegList RLIST {R0,R1,R2}

LDMIA R3,RegList

END

$变量替换符,类似shell命令

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   ——L表示Logic

寄存器操作

LDR(大范围寻址)取代MOV

GBLA Age

Age SETA 0x18

LDR R1,=Age   ;这样读取的是常量值,而不是对应的地址值(LDRop只允许Rn和常量,如果是Rn就看作地址,如果是常量,则LDR相当于MOV

ADR——小范围寻址(相对寻址/+-255)到寄存器,可以查看label的地址

ADR R2,START

ADRL——中范围寻址到寄存器

数据定义伪汇编

作用:开辟一片区域,并赋初值

DCB——按字节存储,当前地址赋值为0x01...

TestData DCB 0x01,0x02,0x03   

等价于 TestData = 0x01,0x02,0x03

DCW——按半字存储,当前地址赋值为0x01... 

DcControl DCW 0x01,0x02,0x03 

DCD——按全字存储,每个0x014byte。即保存为0x00000001

如果存放的是字符串,如

   DcData DCB “hello”

存放的是6个字节,且是ASC码 

SPACE——开辟一个连续区域,并初始化为0

TestData SPACE 100

初始化100个字节为0

MAP——定义结构化内存表首地址的值

MAP/FIELD=>可用^/#代替

MAP 0x100  ;表首地址为0x100

A FIELD 16  ;A长度为16字节,地址为0x10016字节相当于0x010

B FIELD 32 ;B长度为32字节,地址为0x100+0x010=0x11032字节相当于0x020

C FIELD 256  ; C长度为256字节,地址为0x110+0x20=0x130

控制伪指令

IF ELSE ENDIF 条件

WHILE WEND 循环

MACRO MEND 宏定义

MEXIT 跳出宏

IF ELSE纯伪指令操作实例:

GBLA Age

Age SETA 0x18

IF Age > 0

MOV R0,#0x04

ELSE

MOV R1,#0x04

ENDIF

对比:逻辑值操作

GBLL Bit

Bit SETL {TRUE}

IF Bit = {TRUE}

MOV R0,#0x04

ELSE

MOV R1,#0x04

ENDIF

WHILE纯伪指令操作实例:

WHILE Age < 20

  ADD R0,R0,#0x01

Age SETA 0x21

WEND

MACRO实例

格式:[$ label name] macro name $param1,$param2,...

MACRO

$OP hello $param1,$param2

MOV R0,#0x01

MEXIT ;这样就不会执行下面的语句

MOV R1,#0x02

MEND

OP hello AA,BB

上面例子没有使用param1param2

你可能感兴趣的:(ARM汇编与ARM基础)