×
单片机 > 单片机程序设计 > 详情

基于ARM9的伪指令汇总

发布时间:2020-08-26 发布时间:
|

伪指令 
注意:不同的IDE,伪指令也会有很大差别;但是汇编指令是一样的; 
伪操作标识符: 
功能:为汇编程序完成各种准备工作; 
特点:特殊的指令助记符但与指令系统的助记符不同,没有对应的源操作码;

伪操作:伪操作符所完成的操作; 
特点:只在汇编(编译)的时候伪操作发生作用,计算机运行的时候并没有位操作的参与,一旦汇编(编译)结束,伪操作的使命就完成了;

常用伪操作的分类

符号定义伪操作 
功能:用来定义ARM汇编中的变量,对变量赋值以及定义寄存器的别名等操作。常用的有以下4种: 
定义全局变量:GBLA,GBLL,GBLS 
定义局部变量:LCLA,LCLL,LCLS 
对变量赋值:SETA,SETL,SETS 
为通用寄存器列表定义名称RLIST 
数据定义伪指令 
功能:为特定的数据分配存储单元,同时完成已分配存数单元的初始化 
常用的有9中: 
DCB:用于分配一片连续的字节存储单元并用指定的数据初始化; 
DCW(DCWU):用于分配一片连续的半字存储单元并用指定的数据初始化; 
DCD(DCDU):用于分配一片连续的字存储单元并用指定的数据初始化 
DCFD(DCFDU):用于双精度浮点数分配一片连续的字存储单元并用于指定的数据初始化; 
DCFS(DCFSU):用于分为单精度的浮点数分配一分连续的字存储单元并用指定的数据初始化 
DCQ(DCQU):用于分配一片以8字节 为单元的连续的存储单元并用指定的数据初始化; 
SPACE:分配一片连续的储存单元 
MAP:定义一个结构化的内存表首地址; 
FIELD:定义一个结构化的内存表的数据域;

汇编代码控制伪操作 
功能:控制汇编程序执行流程。 
常用的汇编控制伪指令如下: 
1. IF,ELSE,ENDIF这三个符号连用,进行条件汇编 
2. WHIL,WEND这两个符号连用,进行重复汇编 
3. MACRO和MEND这两个符号连用,定义一个宏定义; 
4. MEXIT用来在宏结束前退出宏定义。

信息报告伪指令 
功能:用于程序汇编指示,主要是在程序调用阶段使用。 
常用信息报告伪操作是: 
ASSERT 程序错误报告伪操作 
INFO 诊断信息报告伪操作 
OPT 列表选项设置伪操作 
TTL&SUBT 插入文件标题伪操作

指令集类型标识伪操作 
功能:告诉编译器所要处理的是32位ARM指令还是16位Thumb 
有两种: 
ARM或CODE32指示编译器将要处理的是32位ARM指令 
THUMB或CODE16只是将要处理的是16位的Thumb指令

其他伪操作指令 
AREA:定义一段代码段或数据段 
ALIGN:使程序当前位置满足一定的对齐方式 
ENTR:指定程序入口 
END:指定源程序结束 
EQU:用于定义字符名称 
EXPORT(或GLOBAL):用于声明符号可以被其他文件引用; 
EXPORTAS:向目标文件引入符号 
IMPORT:通知编一起当前符号不在本文件中 
EXTERN:通知编一起要使用的符号在其他的源文件中定义,但要在当前源文件中引用 
GET(INCLUDE):用于将一个文件包含到当前源文件中 
INCBIN:将一个文件包含源文件中

常见伪指令的用法 
这里谈到用法咱们用两种IDE来说:分别是linux环境下的GNU和ADS环境

定义常量或标号名称的伪操作 
功能:类似于C语言中的宏定义#define 
1)ADS环境下: 
语法格式:标号名称 EQU/SETA expr(,type) 
expr可以是32位整形变量,基于寄存器的地址值,程序相对的地址以及绝对地址。 
栗子:USERMODE EQU 0x10 
2)GNU环境 
语法格式:.equ/.set 标号名称 , 
value同expr,表示数字常量或程序中的标号。例如: 
.equ USERMODE ,0x10 //将符号常量0x10定义成USERMODE

段属性定义的伪操作 
功能:定义一个代码段或数据段,或者开始一个新的代码段或数据段 
1)ADS环境: 
语法格式:AREA 段名 (,属性) (…,属性)… 
栗子: 
AREA M1, DATA , READONLY ;定义数据段 
AREA M2,CODE , READONLY 定义程序段 
数据段DATA,代码段CODE ,属性是READONLY(只读),数据段名是M1,代码段名是M2

2)GNU环境下 
语法格式:.setion .段名 {,“标志”} 
标志:各段有缺省标志,elf格式允许的标志段如下: 
—————————————————— 
| 含义 
A | 允许段 
W | 可写段 
X | 执行段 
—————————————————— 
栗子:.setion .text, “x” ;表示定义了一个代码段是可执行的

这里要解释一下GNU环境下的定义段名的两种方法: 
方法1:在GNU环境下,有些段名是汇编系统预定义的,例如.text为代码段,.data为初始化数据段,.bss为为初始化数据段等,每个段以段名开始,以下段名或者文件结尾为结束。 
方法2: 
例如:.setion .mysection ;自定义数据段,段名为.mysection

声明程序的入口点伪操作 
功能:指定程序的入口; 
1)ADS环境中 
语法格式: ENTRY …… 
2)GNU环境 
语法格式:_start:

源程序结尾标识伪操作 
功能:通知编译器,程序到此结束了; 
1)ADS环境 
语法格式:END 
2)GNU环境 
语法格式:.end ;常常省略不用

指令集类型标识伪操作 
功能:告诉编译器所处理的是32位的ARM指令还是16位的Thumb指令 
1)ADS环境 
语法格式: 
ARM(CODE32) 
…… 
THUMB(CODE16) 
…… 
2)GNU环境下 
语法格式: 
.arm或.code: .code32 …… 
.thumb或.code: .code16 ……

对齐方式设置伪操作 
功能:通过填充字节,使当前位置满足一定的对齐方式 
1)ADS环境 
语法格式:ALIGN {对齐表达式{,偏移量{,填充的字节}}} 
对齐表达式:指定对齐方式 
偏移量:是一个数字表达式,若使用该字段,则当前位置的对齐方式为n*expr+偏移量。 
栗子 
aa DCB 0x58 ;定义一字节名为aa的储存空间,字对齐方式被破坏 
ALIGN ;声明字对齐 
2)GNU环境 
.align/.balign {对齐表达式}{,填充的数据} 
对齐表达式用于对齐方式,取指为0~15之间;

声明全局标号伪操作 
在ARM和C语言混合编程中,经常用到全局标号声明,例如下面的代码: 
EXPORT FUNCNAME 
…… 
FUNCANME 
…… 
声明全局变量标号用于在程序声明中声明一个全局变量,该标号可以在其他文件中被引用,类似于C语言中的全局变量 
1)ADS环境下 
语法格式:EXPORT / GLOBAL{符号} {[WEAK],[attr]} 
[WEAK]选项声明其他的同名标号优先于该标号被引用 
[attr]符号属性用于定义所定义的符号对其他文件的可见性(visibility),attr可以是下面一些属性值: 
DYNAMIC符号可以被其他文件引用,并且可以在其他文件中被重新定义。 
PROTECTED符号可以被其他文件引用,但是可以重新定义; 
HIDDEN符号不能被其他文件引用; 
2)GNU中的用法 
语法格式:.global / .globl 符号 ;符号是要声明的全局变量名称 
举个栗子: 
.globel _start ;声明全局变量_start

声明外部全局变量伪指令 
功能:通知编译器要使用的标号在其他源文件中定义,但要在当前源文件中被引用,标号在程序中区分大小写。 
1)ADS环境 
语法格式:IMPORT/EXTEREN {符号} {[WEAK],[attr]}

[WEAK]选项表示当前所有源文件都没定义这个符号,编译器也不给出错误信息。在多数情况下将该标号置0,若该标号被B或者BL指令引用,则将B或BL指令置为NOP操作; 
[attr]符号属性用于定义所定义的符号对其它文件的可见性(visibility),用法同EXPORT中的attr

比较EXTERN和IMPORT的区别: 
1,IMPORT声明的符号无论当前源文件是否引用该标号,该标号均会被加入当前源文件的符号表中; 
2.EXPORT声明的符号,如果当前源文件实际未引用该标号,则该标号不会被加入到当前源文件中的符号列表;

2)GNU环境 
语法格式:.extern 符号 @符号是要声明的外部变量名称

声明数据缓冲池伪操作 
功能:哎呀,其实就是要声明数组; 
使用LDR伪指令时,要在适当的位置声明数据缓冲池,这样会把要加载的数据保存到缓冲池中,再寄存使用ARM加载指令读出。数据缓冲池类似于C中的数组,如果没有使用声明数据缓冲池的伪操作,则汇编器会在程序末尾自动声明; 
…… 
LTORG 
src 
DCD 1,2,3,4,5,6,7,8,1,2,3,4,5;字数据 
dst 
DCD 0,0,0,0,0,0,0,0,0,0; 
1)ADS环境 
语法格式:LTORG

2)GNU环境 
语法格式: .ltorg 
.ltorg 在当前段的当前地址产生一个文字池

LDR R0 , =src 
…… 
.ltorg @定义数据缓冲池,存放在src开始的地址处 
src: 
.LONG 1,2,3,4,5,6,7,8,9 
dst: 
.LONG 0,0,0,0,0,0,0,0,0

数据定义伪操作 
功能:为特定的数据分配存储单元,也可以完成已分配储存单元的初始化

数据定义的数据类型: 
DCB(分配字节存储单元)-128~255之间的数字或字符串, 
DCW/DCWU(分配半字存储单元)-32768~65535间的数字表达式 
DCD/DCDU (分配字存储单元)是表达式 
DCFS(单精度浮点数) 
DCFD(双精度浮点数) 
DCQ(双字)

1)ADS环境 
语法格式:{标号} 数据类型 expr{ , expr}…

2)GNU环境 
GNU中的相应伪指令是: 
.byte/.hword/.long/.quad/.float/.string/.asciz/.ascii 
语法格式: 
.byte(.hword/.quad/.word/…) {,}…

两种环境下的对比 
.byte == DCB 
.hword或.short == DCW 
.word或.long == DCD 
.quad == 8字节 
.float 定义浮点数 
.string/.asciz/.ascii 定义多个字符串

固定填充字节内存储单元伪操作 
功能:分配一片连续的存储单元 
1)ADS环境下 
语法格式: 
{标号}SPACE 分配字节数 ;并且初始化为0 
栗子: 
dataS SPACE 100 ;分配100字节储存空间并且初始化为0

2)GNU环境下 
语法格式: 
.space/.skip 字节数 {,填充字节} 
分配number_of_bytes字节的存储空间,并填充其值为fill_byte,若未指定该值,缺省填充0; 
栗子:.space 100 , 0x55 @分配100字节内存单元,并用0x55初始化。

IF条件编译伪操作 
功能:同与C语言; 
1)ADS环境下 
语法格式: 
IF 逻辑表达式 
…… 
{ELSE 
……} 
ENDIF 
2)GNU环境下 
语法格式: 
.if 
…… 
{.else 
……} 
.endif

宏定义伪操作 
宏指令:将一段代码定义为一个整体,称为宏指令;然后就可以在程序中被反复调用。 
1)ADS环境 
ARM中宏定义伪指令:MACRO/MEND(宏停止)/MEXIT(宏跳出). 
语法格式:

MACRO
    { $ 标号}  宏名  { $ 参数{,$参数}}
   ……   MEND1234

栗子:

   MACRO                               ;宏定义伪操作    $HandlerLabel HANDLER  $HandleLablel

   $HandlerLablel
   sub sp,sp,#4                   ;sp-4(保存跳转地址)
   stmfd   sp!,(r0)               ;工作寄存器入栈             
   ldr  r0, = $HandleLabel  ;加载地址到HandleLableXXX到r0
   ldr  r0,[r0]                         ;加载处理例程起始地址
   str  r0,[sp,#4]                   ;HandleXXX(ISR)地址存储到堆栈
   ldmfd    sp!,{r0,pc}                       ;工作寄存器和PC出栈(跳出ISR)
   MEND                                   ;宏定义结束1234567891011

这里分享一位前辈的讲解: 
http://blog.csdn.net/zhoujiaxq/article/details/8127253

2)GNU环境下 
GNU中相关伪指令是.macro/.endm(宏结束)/.exitm(宏跳出) 
语法格式: 
.macro 宏名 {} {,}…{,} 
…… 
…… 
.endm 
参数可以通过“字符”直接使用,例如: 
MOV R0,\arg ; arg为宏参数 
例如: 
.MACRO HANDLER Handlelabel @宏定义伪操作 
@HandlerLabel: 
sub sp,sp,#4 
stmfb sp!,{r0} 
ldr r0,=\HandleLabel 
ldr r0,[r0] 
str r0,[sp,#4] 
ldmfd sp!,{r0,pc} 
.ENDM @宏定义结束

文件包含伪操作 
功能:类似于C语言中的#include ,将一个源文件包含在当前源文件中,并将包含的文件在其当前位置进行编译处理。 
有一类文件包含伪操作,对被包含文件不进行操作; 
1)ADS环境下 
语法格式: 
INCLUDE 文件名 ;文件名不用双引号等符号

提醒:可以用GET代替INCLUDE,GET只能用于包含源文件,,包含目标文件需要使用INCBIN伪操作。 
2)GNU环境下 
语法格式: 
.include 文件名





『本文转载自网络,版权归原作者所有,如有侵权请联系删除』

热门文章 更多
STM32中断向量表的位置.重定向