ARM体系结构与编程学习(二)

时间:2022-09-08 19:07:56

第四章 ARM汇编语言程序设计

4.1 arm伪指令

包括6种伪指令:符号定义伪指令、数据定义伪指令、汇编控制伪指令、框架描述伪指令、信息报告伪指令、其他伪指令。

4.1.1 符号定义伪指令:用于定义arm汇编程序中的变量,对变量进行赋值以及定义寄存器名称。

  GBLA、GBLL、GBLS    声明全局变量

  LCLA、LCLL、LCLS     声明局部变量

  SETA、SETL、SETS     给变量赋值

  RLIST                         寄存器列表定义名称

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

  CP                             协处理器定义名称

  DN、SN                      为VFP(浮点体系结构)的寄存器定义名称

  FN                              为FPA的浮点寄存器定义名称

GBLA、GBLL、GBLS

GBLA         声明一个全局数字变量,并初始化为0

GBLL         声明一个全局逻辑变量,并初始化为{FALSE}

GBLS         声明一个全局字符串变量,并初始化为空串""

示例

GBLA  objectsize            ;声明一个全局的数字变量,初始化为0

objectsize SETA 0xFF     ;将变量objectsize赋值为0xFF

SPACE  objectsize          ;引用该变量

GBLL  statusB                 ;声明一个全局逻辑变量statusB

statusB    SETL  {TRUE}  ;给逻辑变量statusB赋值为TRUE

LCLA、LCLL、LCLS

LCLA         声明一个局部数字变量,并初始化为0

LCLL         声明一个局部逻辑变量,并初始化为{FALSE}

LCLS         声明一个局部字符串变量,并初始化为空串

SETA、SETL、SETS

SETA         给数字变量赋值

SETL         给逻辑变量赋值

SETS         给字符串变量赋值

GBLS   message              ;定义一个全局串变量

message   SETS  ”hello!" ;给该串变量赋值

RLIST 

RLIST         为一个通用寄存器列表定义名称

Context  RLIST   {R0-R6,R8,R10-R12,R15}   ;将寄存器列表名称定义为Context

CN

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

power   CN  6                   ;将协处理的寄存器6名称定义为power

CP

CP              为一个协处理器定义名称

Dmu   CP   6                      ;将协处理器6名称定义为Dmu

DN、SN

DN              为一个双精度的VFP寄存器(编号0~15)定义名称

SN              为一个单精度的VFP寄存器(编号0~31)定义名称

height    DN  6                   ;将VFP双精度寄存器6名称定义为height

width     SN   16                 ; 将VFP单精度寄存器16名称定义为width

FN

FN              为一个FPA浮点寄存器(编号0~7)定义名称

fat        FN   5                     ;将浮点寄存器5名称定义为fat

4.1.2 数据定义伪指令

LTORG                   声明一个数据缓冲池的开始

MAP                       定义一个内存表的首地址

FIELD                     定义内存表中的数据域

SPACE                    分配一块内存单元,并用0初始化

DCB                        分配一字节的内存单元

DCD及DCDU            分配一字的内存单元

DCDO                      分配一字的内存单元,初始化为偏移量

DCFD及DCFDU         分配一双字的内存单元,并用双精度的浮点数据初始化

DCFS及DCFSU          分配一单字的内存单元,并用单精度的浮点数据初始化

DCI                          分配一段字节的内存单元

DCQ及DCQU            分配一段双字的内存单元

DCW及DCWU           分配一段半字的内存单元

DATA                        在代码段中使用数据,现已不再使用。

LTORG

LTORG                     用于声明一个数据缓冲池的开始

AREA  Example ,CODE , READONLY

start   BL              func1

func1                                                ;子程序

;code

LDR  R1 ,=0x55555555                     ;LDR  R1,[PC,#offest to literal pool 1]

;code

MOV PC ,LR                                       ;子程序结束

LTORG                                               ;定义数据缓冲池&55555555

DATA  SPACE   4200                          ;从当前位置开始分配4200字节的内存单元

END                                                   ;默认的数据缓冲池为空

MAP 

MAP    定义内存表的首地址,与FIELD配合使用来定义结构化的内存表结构。^为MAP的同义词

MAP   0x80, R9                                 ;内存表的首地址为R9+0x80

FIELD

FIELD  定义内存表中的数据域。#是FIELD的同义词。MAP与FIELD仅是定义数据结构,不分配内存单元。

MAP  0                                                  ;内存表的首地址为0

consta              FIELD           4              ;consta长度为4字节,相对位置为0

constb              FIELD         4              ;constb长度为4字节,相对位置为4

x                       FIELD         8              ;x长度为8字节,相对位置为8

y                       FIELD         8              ;y长度为8字节,相对位置为16

string                FIELD         256          ;string长度为256字节,相对位置为24

LDR           R6,consta                         ;引用内存表中的数据域

MAP  4096                                          ;内存表的首地址为4096(0x1000)

consta              FIELD         4              ;consta长度为4字节,相对位置为0

constb              FIELD         4              ;constb长度为4字节,相对位置为4

x                       FIELD         8              ;x长度为8字节,相对位置为8

y                       FIELD         8              ;y长度为8字节,相对位置为16

string                FIELD         256          ;string长度为256字节,相对位置为24

MOV     R9 ,#4096

LDR   R5 ,[R9,constb]                        ;将内存表中的数据域constb读取到R5中。  

在arm-thumb指令中,通常将R9作为静态基址寄存器。

MAP  0,R9                                          ;内存表的首地址为R9+0

consta              FIELD          4              ;consta长度为4字节,相对位置为0

constb              FIELD          4              ;constb长度为4字节,相对位置为4

x                       FIELD          8              ;x的长度为8字节,相对位置为8

y                       FIELD          8              ;y的长度为8字节,相对位置为16

string                FIELD         256           ;string长度为256,相对位置为24

可以通过下面的指令方便地寻址超过4KB的数据

ADR      R9, DATASTART                      ;ADR指令将PC值或者寄存器的值读取到寄存器,它是基于PC值进行计算

LDR       R5,constb                             ;相当于LDR  R5 ,[R9,#4] 

Datastruc         SPACE          280          ;分配280字节的内存单元

MAP          Datastruc                             ;内存表的首地址为Datastruc内存单元

consta              FIELD          4              ;consta长度为4字节,相对位置为0

constb              FIELD          4              ;constb长度为4字节,相对位置为4

x                       FIELD          8              ;x的长度为8字节,相对位置为8

y                       FIELD          8              ;y的长度为8字节,相对位置为16

string                FIELD         256           ;string长度为256,相对位置为24

LDR      R5 ,constb                                ;相当于LDR    R5, [PC, offest]

当FIELD 伪指令中的操作数为0时,其中的标号即为当前内存单元的地址

SPACE

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

Datastruc     SPACE        1000               ;分配1000个字节单元,并将内存单元内容初始化为0

DCB  用于分配一片连续的字节内存。  =是DCB 的同义词

{label} DCB expr{,expr}{,expr}…

其中:
label 内存块起始地址标号。
expr可以为-128~255 的数值或字符串。内存分配的字节数由expr 个数决定。

Nullstring   DCB        "Null  string“ ,0   ;构造一个以NULL结尾的字符串

DCD及DCDU、DCDO,DCFD及DCFDU、DCFS及DCFSU、DCI、DCQ及DCQU、DCW及DCWU可以参照。

4.1.3汇编控制伪指令

IF、ELSE及ENDIF

WHILE及WEND

MACRO及MEND

MEXIT

IF、ELSE及ENDIF

IF、ELSE及ENDIF  用于选择

IF  Version =”1.0“

;指令

;伪指令

ELSE

;指令

;伪指令

ENDIF

WHILE 及WEND

WHILE及WEND 循环

count   SETA   1                           ;设置循环计数变量count初始值为1

WHILE  count <=4                        ;由conut控制循环次数

count   SETA   count+1                 ;将循环计数变量加1

;code                                           

WEND

MACRO及MEND

MACRO及MEND 定义宏

MACRO                                                       ;宏定义开始

$label                    xmac      $p1 ,$p2          ;宏的名称为xmac,有两个参数$p1、$p2

                                                                    ;宏的标号$lable可用于构造宏定义体内的其他标号名称

;code

$lable.loop1       ;code                                   ;$lable.loop1为宏定义体内的内部标号

;code

BGE     $label.loop1

$label.loop2       ;code

BL     $p1                                                     ;参数$p1为一个子程序的名称

BGT  $label.loop2               

;code

ADR      $p2

;code

MEND                                                            ;宏定义结束

;在程序中调用宏

abc   xmac    subr1 ,de                                  ;通过宏的名称xmac调用宏,其中宏的标号为abc,

                                                                      ;参数1为subr1,参数2为de

;程序被汇编后,宏展开的结果

;code

abc.loop1  ;code                                            ;用标号$label实际值abc代替$label

;code

BGE  abc.loop1

abc.loop2  ;code

BL  subr1                                                        ;参数1的实际值为subr1

;code

ADR  de                                                           ;参数2的实际值为de

MEXIT

MEXIT 用于从宏中跳转出去

MACRO

$abc       macroabc    $p1 ,$p2

;code

WHILE  condition1

;code

IF  condition2

;code

MEXIT                                               ;从宏中跳转出去

ELSE

;code

ENDIF

WEND

;code

MEND

4.1.4 信息报告伪指令

ASSERT    条件不成立时显示告警信息

INFO        报告信息

OPT          设置列表选项

TTL及SUBT 插入标题及子标题

4.1.6 其他伪指令

ALLGN

AREA

CODE16及CODE32

END

ENTRY

EQU

EXPORT或GLOBAL

EXTERN

GET或INCLUDE

IMPORT

INCBIN

KEEP

NOFP

REQUIRE

REQUIRE8及PERSERVER8

RN

ROUT

ALLGN

ALLGN 指定对齐方式

AREA   cacheable ,CODE, ALLGN=3     ;指定下面的质量是8字节对齐

rout1          ;code

;code

MOV  PC ,LR                                           ;程序跳转后变成4字节对齐

ALLGN  8                                                ;指定下面的指令是8字节对齐

rout2           ;code

AREA

AREA    定义一个代码段或者数据段

AREA    Example  ,CODE ,READONLY     ;定义一个代码段,名称为Example,属性为READNOLY

CODE16及CODE32

CODE16 表明后面的指令为thumb指令

CODE32表明后面的指令为arm指令

END

END 表示源程序结尾

ENTRY

ENTRY 指定程序入口点

EQU

EQU 用于取别名,*为其同义词,相当于C语言中的#define。

abcd  EQU   2                                 ;定义abcd代表2

addr1  EQU   0x1c ,CODE32          ;定义addr1符号值为绝对地址0x1c,而且该指令为arm指令

EXPORT及GLOBAL

EXPORT 声明一个符号可以被其他文件引用,相当于声明了一个全局变量。GLOBAL是EXPORT的同义词

AREA   Example  ,CODE ,READONLY  

EXPORT  Doadd                                     ;下面的函数名称Doadd可以被其他源文件引用

Doadd    ADD  R0,R0,R1             

EXTERN

EXTERN  声明一个符号是在其他源文件中定义的。

AREA  Example  ,CODE ,READONLY

EXTERN   _CPP_INITIALIZE[WEAK]         ;如果连接了C++库则读取函数_CPP_INITIALIZE地址

LDR    R0 ,_CPP_INITIALIZE

CMP   R0 ,0                                              ;

BEQ   nocplusplus                                   ;如果没有连接C++库,则跳转到nocplusplus

GET及INCLUDE

GET 将一个文件包含到当前文件中,INCLUDE是GET同义词

AREA  EXAMPLE ,CODE, READNOLY

GET    file1.s                                           ;包含源文件file1.s

GET    C:/project file/file2.s                     ;包含源文件file2.s,可以包含路径中的空格

IMPORT

IMPORT 引入外部定义符号

INCBIN

INCBIN将文件包含到当前文件中,但是被包含的文件不进行汇编处理

AREA  Example ,CODE,READONLY

INCBIN          file1.dat                               ;包含文件file1.dat

INCBIN          C:/projecfile/file2.txt            ;包含文件file2.txt,路径中不能有空格

KEEP

KEEP将局部符号包含到目标文件的符号表中

NOFP

NOFP 禁止浮点运算

PREQUIRE

PREQUIRE 指定段之间的依赖关系

REQUIRE8及PRESERVER8

REQUIRE8 要求当前代码中数据栈8字节对齐

PRESERVE8要求当前代码中数据栈8字节对齐

RN

RN  为某一个寄存器定义名称,即更改名称

ROUT

ROUT 定义局部变量的有效范围