汇编语言伪指令
在汇编语言程序里,有一些特殊的助记符,这些助记符与指令系统的助记符不同,它们没有对应的机器码。这些助记符在源程序中的作用是完成汇编程序的各种准备工作,包括定义变量、分配数据存储空间、控制汇编过程、定义程序入口等。它们仅仅在汇编的过程中起作用,一旦汇编过程结束,它们的使命也就完成了。这些助记符称为伪指令,它们所完成的操作称为伪操作。不同汇编器的伪指令可能存在少量的区别,并非所有的伪指令在任何编译器上都能被识别。
一、符号定义伪指令
符号定义(Symbol Definition)伪指令用于定义ARM汇编程序中的变量,对变量赋值和定义寄存器别名等,如表1所列。
表1 符号定义伪指令
助 记 符 | 指令功能描述 |
GBLA | 定义一个全局的数字变量,并初始化为0 |
GBLL | 定义一个全局的逻辑变量,并初始化为F(假) |
GBLS | 定义一个全局的字符串变量,并初始化为空 |
LCLA | 定义一个局部的数字变量,并初始化为0 |
LCLL | 定义一个局部的逻辑变量,并初始化为F(假) |
LCLS | 定义一个局部的字符串变量,并初始化为空 |
SETA | 用于给一个数字变量赋值 |
SETL | 用于给一个逻辑变量赋值 |
SETS | 用于给一个字符串变量赋值 |
RN | 用于给一个特殊的寄存器命名 |
CN | 用于给一个协处理器的寄存器命名 |
CP | 用于给一个协处理器命名 |
DN | 用于给一个双精度的VFP寄存器命名 |
SN | 用于给一个单精度的VFP寄存器命名 |
FN | 用于给一个FPA浮点寄存器命名 |
RLIST | 定义一个通用寄存器列表,根据寄存器编号由低到高访问 |
实例:
GBLL P_ON ; 定义全局逻辑变量P_ON
P_ON SETL {TRUE} ; 给全局逻辑变量P_ON赋值为真
LCLA NUM ; 定义局部数字变量NUM
NUM SETA 100 ; 给全局数字变量NUM赋值为100
RegList RLIST {R0-R5,R8,R10} ; 定义一个寄存器列表RegList,可用
; LDM/STM指令访问该列表
二、数据定义伪指令
数据定义(Data Denfinition)伪指令一般用于为特定的数据分配存储单元,同时完成对已分配存储单元的初始化工作。数据定义伪指令如表2所示。
表2 数据定义伪指令
助 记 符 | 指令功能描述 |
SPACE | 用于分配一片连续的存储单元,并初始化为0 |
MAP | 用于定义一个结构化内存表的首地址 |
FIELD | 用于定义一个结构化内存表的数据域 |
LTORG | 用于声明一个数据缓冲池的开始 |
DCI | 分配一段字节的存储单元,用指定表达式初始化,并指定存放的是代码 |
DATA | 在代码段中使用数据 |
DCB | 用于分配一段连续的字节存储单元,并用指定的表达式初始化 |
DCW(DCWU) | 用于分配一段连续的半字存储单元,并用指定的表达式初始化 |
DCD汇编指令有多少个(DCDU) | 用于分配一段连续的字存储单元,并用指定的表达式初始化 |
DCFS(DCFSU) | 用于为单精度浮点数分配连续字节存储单元,一个数分配1个字单元,并用指定的表达式初始化 |
DCFD(DCFDU) | 用于为双精度浮点数分配连续字节存储单元,一个数分配2个字单元,并用指定的表达式初始化 |
DCQ(DCQU) | 用于分配一段连续的双字存储单元,并用指定的64位整数初始化 |
DCDO | 用于分配一段连续的字存储单元,并将内容初始化为相对于静态基址寄存器的偏移量 |
从使用方法上来讲,数据定义伪指令可以分为以下3类。
1.SPACE
伪指令SPACE用于分配一片连续的存储区,并初始化为0。其中表达式中的数字表示分配的字节数。SPACE也可以用%代替。
实例:
DataSpace SPACE 100 ; 分配连续100字节的存储单元并初始化为0
2.MAP和FIELD
伪指令MAP和伪指令FIELD经常结合在一起使用。MAP用于定义一个结构化的内存表的首地址,可以用“^”替代。FIELD用于定义一个结构化的内存表中的数据域,可以用“#”代替。
FIELD与MAP配合使用能够定义结构化的内存表。首先用伪指令MAP定义表的首地址,再用伪指令FIELD定义表中的各个数据域,并为每个数据域指定一个标号以供其他指令引用。注意MAP和FIELD仅用于定义数据结构,并不实际分配存储单元。
实例:
MAP 0x1000 ; 定义结构化内存表首地址为0x1000
F1 FIELD 32 ; 长度为32字节数据域F1,起始位置0x1000
F2 FIELD 64 ; 长度为64字节数据域F2,起始位置0x1020
F3 FIELD 128 ; 长度为128字节数据域F3,起始位置0x1060
3.存储单元分配
伪指令DCB用于分配一片连续的以字节为最小单位的存储单元,并可以使用指定的表达式对其进行初始化。换句话说,初始化时数据的取值范围为0~255的数字或字符,每个数字或字符存储时占1字节。DCB也可以用“=”代替。
伪指令DCW用于分配一片连续的以半字为最小单位的存储单元,并可以使用指定的表达式对其进行初始化。DCWU与DCW的区别在于DCW分配存储单元时严格要求半字对齐,而DCWU则不严格要求半字对齐。DCD、DCFS、DCFD、DCQ与DCW类似并要求字或双字
对齐,而DCDU、DCFSU、DCFDU、DCQU与DCWU类似,不严格要求字或双字对齐。
实例:
hello DCB “Hello World\n\0” ; 用字符串初始化标号为hello的连续字节存储单元
DCD ((B0<<13)+(B1<<6)) ; 使用表达式初始化连续字存储单元
src DCD 1, 2, 3, 4, 5 ; 用数字常量初始化标号为src的连续字存储单元
三、汇编控制伪指令
汇编控制(Assembly Control)伪指令用于控制汇编程序的执行流程,可以让汇编器按照一定的条件选择性地编译汇编指令或多次编译一段指令,从而根据程序员设定的参数生成不同的映像文件,减少程序员的工作量。常用的汇编控制伪指令包括以下几条,如表3所列。
表3 汇编控制伪指令
助 记 符 | 指令功能描述 |
IF、ELSE和ENDIF | 根据条件成立与否决定是否编译某个指令序列 |
WHILE和WEND | 根据条件成立与否决定是否循环编译某个指令序列 |
MACRO和MEND | 将一段代码用一个标号替代,可在程序中多次调用该段代码 |
MEXIT | 从宏定义中跳转出去 |
汇编控制指令可以分为以下3类。
1.条件判断
条件判断指令包括IF、ELSE和ENDIF三条伪指令,其用法和高级语言中的if语句类似,指令书写格式如下。
IF logical expression
指令序列1
ELSE
指令序列2
ENDIF
IF,ELSE和ENDIF伪指令能根据条件的成立与否决定是否编译某个指令序列。若IF后面的逻辑表达式为真,则编译指令序列1,否则执行指令序列2。其中,ELSE及指令序列2可以
没有,此时当IF后面的逻辑表达式为真,则编译指令序列1,否则继续执行后面的指令。IF、ELSE和ENDIF伪指令可以嵌套使用。
实例:
GBLL Test ; 声明一个全局的逻辑变量,变量名为Test
……
IF Test = TRUE
指令序列1
ELSE
指令序列2
ENDIF
通过判断Test的值是否为真,汇编器决定编译哪一段指令序列。程序员可以通过设置Test的值,灵活地生成不同的映像文件。
2.循环控制
循环控制指令包括WHILE和WEND指令,指令书写格式如下所示。
WHILE logical expression
指令序列
WEND
WHILE和WEND伪指令能根据条件的成立与否决定是否循环编译某个指令序列。若WHILE后面的逻辑表达式为真,则编译指令序列。该指令序列编译完毕后,再判断逻辑表达式的值,若为真则继续再次编译,一直到逻辑表达式的值为假。WHILE和WEND伪指令可以嵌套使用。
实例:
GBLA Counter ; 声明一个全局的数学变量,变量名为Counter
Counter SETA 3 ; 由变量Counter控制循环次数
……
WHILE Counter < 10
指令序列
WEND
通过循环控制指令,可以将一段相同的代码多次编译,类似于把代码复制多次。通过对循环次数的控制可以灵活地控制代码复制次数,极大地减少了程序员的工作量。
3.宏指令
MACRO和MEND伪指令可以将一段代码定义为一个整体,这两条指令称为宏指令。程序员可以在程序中通过宏指令多次调用完成宏定义的代码。指令书写格式如下所示。
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论