《第4章伪指令(2016年3月3日)》由会员分享,可在线阅读,更多相关《第4章伪指令(2016年3月3日)(74页珍藏版)》请在金锄头文库上搜索。
1、共74页,1,第4章 伪指令 2学时,本章主要内容,1、伪指令概述;,2、与ARM指令相关的宏指令;,3、通用伪指令。,共74页,2,本章教学要求,目前汇编有 ARMASM 汇编和 GNUASM 汇编,本课程主要讲 ARMASM 汇编。,掌握:ARM 的伪指令、宏。,共74页,3,1、什么是伪指令,人们设计了一些专门用于 指导 汇编器进行汇编工作的指令,由于这些指令不形成机器码指令,它们只是在汇编器进行汇编工作的过程中起作用,所以被叫做 伪指令。,4.1 伪指令概述,伪指令用来对汇编程序进行控制,对程序中的程序实现:条件转移、列表、存储空间分配 等处理。,共74页,4,2、伪指令具有的两个特征
2、,(1)伪指令是一条指令;,(2)伪指令没有指令代码。,3、伪指令的作用,(1)程序定位的作用;,(2)为非指令代码进行定义;,(3)为程序完整性做标注;,(4)有条件的引导程序段。,共74页,5,4.2.1 宏,(1)MACRO 和 MEND,MACRO 和 MEND 宏指令可以为一个程序段定义一个名称。这样,在汇编语言应用程序中就通过这个名称来使用它所代表的程序段,即当程序做汇编时,该名称将被替换为其所代表的程序段。,4.2 与ARM指令相关的宏指令,共74页,6,MACRO $标号 宏名 $参数1, $参数2,. 程序段(宏定义体) MEND,$标号:为主标号,宏内的所有其它标号必须由主
3、标号组成;,宏名:宏名称,为宏在程序中的引用名;,$参数1,$参数2:宏中可以使用的参数。,共74页,7,宏中的所有标号必须在前面冠以符号“$”。,MACRO ;宏定义指令$MDATA MAXNUM $NUM1,$NUM2 ;主标号,宏名,参数 语句段$MDATD.MAY1 ; 宏内标号 语句段$MDATA.MAY2 ; 宏内标号 语句段 MEND ; 宏结束指令,共74页,8,(2)MEXIT,MEXIT 用于从宏定义中跳转出去。,MEXIT,4.2.2 宏指令,在ARM中,还有一种汇编器内置的无参数和标号宏宏指令。,在汇编时,这些宏指令被替换成一条或两条 真正的 ARM 或 Thumb 指
4、令。,共74页,9,(1)近地址读取宏指令 ADR,ADR 指令用于将一个 近地址值 传递到一个寄存器中。,ADRcond , ,reg 为目标寄存器名称;,expr 为表达式。该表达式通常是一个程序中表示一条指令存储位置的 地址标号。,共74页,10,该宏指令的功能是把标号所表示的地址传递到目标寄存器中。,汇编器在汇编时,将把 ADR 宏指令替换成一条真正的 ADD 或 SUB 指令,以当前的 PC值 减去或加上 expr 与 PC 之间的偏移量得到标号的地址,并将其传递到目标寄存器。,start MOV R0,#10 ADR R4,start,共74页,11,共74页,12,由于指令 AD
5、D 或 SUB 中对 立即数的限制,因此标号地址就不能距离当前指令的地址(PC)过远。对于非字对齐地址来说,其距离必须在 255 字节以内;而对于字对齐地址来说,距离必须在 1020 字以内。所以 ADR 叫做 近地址 读取指令。,(2)远地址读取宏指令 ADRL,类似于 ADR,但可以把 更远的地址 赋给目标寄存器。,共74页,13,ADRLcond , ,reg 为目标寄存器名称;,该指令只能在 ARM 状态下使用,在Thumb 状态下不能使用。汇编时,ADRL 宏指令由汇编器替换成 两条合适的指令。,Expr 为表达式,必须是 64KB 以内非字对齐地址,256KB 以内的字对齐地址。,
6、共74页,14,start MOV R0,#10 ADRL R4,start + 60000,其中 ADRL 将被替换为如下两条指令: ADD R4,PC,#0XE800 ADD R4,R4,#0X254,如果汇编器找不到合适的两条指令,将会报错。,共74页,15,LDRcond reg,=expr | label - expr,reg:目标寄存器名称; expr:32位常数; label expr:为基于PC地址表达式。,程序经常用这条指令把一个地址传递到寄存器 reg 中。汇编器在对这种指令进行汇编时,会根据指令中 expr 的值的大小来把这条指令替换为合适的指令。,(3)全范围地址读取宏
7、指令 LDR,共74页,16,当 expr 的值未超过 MOV 或 MVN 指令所限定的取值范围时,汇编器用 ARM 的 MOV 或 MVN 指令来取代宏指令 LDR;,当 expr 的值超过 MOV 或 MVN 指令所限定的取值范围时,汇编器将常数 expr 放在由 LTORG 定义的文字缓冲池,同时用一条 ARM 的装载指令 LDR 来取代宏指令 LDR ,而这条装载 LDR 指令则用 PC 加偏移量的方法到文字缓冲池中把该常数读取到指令指定的寄存器。,共74页,17,由于这种指令可以传递一个 32 位地址,因此被叫做 全范围地址读取指令。,(4)NOP,汇编器对 NOP 指令进行汇编时,
8、会将其转换为: MOV R0,R0,共74页,18,4.3 通用伪指令,在 ARM 汇编程序语言中,有如下 几种 伪指令:,段定义、符号定义、数据定义、数据缓冲池定义、数据表定义、数据空间分配、汇编控制伪指令 以及 其他伪指令。,共74页,19,(1)符号区分大小写,同名的大、小写符号会被编译器认为是两个不同的符号;,(2)符号在其作用范围内必须唯一;,(3)自定义的符号不能与系统保留字相同;,(4)符号不应与指令或伪指令同名。,符号的命名由编程者决定,但必须遵循以下约定:,4.3.1 为变量定义或赋值的伪指令,共74页,20,GBLA(GBLL和GBLS) ,variable 为变量名称;,
9、GBLA 定义一个 全局数字变量,其默认初值为 0 ;,GBLA、GBLL 和 GBLS 伪指令用于定义一个ARM程序中的 全局变量,并将其初始化。,(1)声明全局变量伪指令 GBLA、GBLL和GBLS,共74页,21,GBLS 定义一个 全局字符串变量,其默认初值为 空 ;,GBLA Test1 ;定义一个全局数字变量,变量名为 Test1,GBLL Test2 ;定义一个全局逻辑变量,变量名为 Test2,GBLL 定义一个 全局逻辑变量 ,其默认初值为 F(假);,共74页,22,GBLS Test3 ;定义一个全局字符串变量,变量名为 Test3,全局变量 的变量名在整个程序范围内必
10、须具有 唯一性。,(2)声明 局部变量 伪指令 LCLA、LCLL和LCLS,LCLA、LCLL和LCLS 伪指令用于定义一个 ARM 程序中的 局部变量,并将其初始化。,共74页,23,LCLA(LCLL和LCLS) ,variable 为变量名称;,LCLA 定义一个 局部数字变量,其默认初值为 0;,LCLL 定义一个 局部逻辑变量,其默认初值为 F(假);,LCLS 定义一个 局部字符串变量,其默认初值为 空。,共74页,24,LCLA Test4 ;定义一个局部数字变量,变量名为 Test4,LCLL Test5 ;定义一个局部逻辑变量,变量名为 Test5,LCLS Test6 ;
11、定义一个局部字符串变量,变量名为 Test6,局部变量 的变量名在变量作用范围内必须具有 唯一性。,共74页,25,在默认情况下,局部变量只在定义该变量的 程序段内有效。,(3)变量赋值伪指令 SETA、SETL和SETS,伪指令 SETA、SETL和SETS 用于给一个 已经定义 的 全局变量 或 局部变量 进行赋值。 注:要顶格写,Test1 SETA 0xAA ;将Test1变量赋值为0xAA。,共74页,26,Test2 SETL TRUE ;将 Test2 变量赋值为真。,Test3 SETS “Testing” ;将 Test3 变量赋值为“Testing” 。,Test4 SET
12、A 0xBB ;将 Test4 变量赋值为0xBB。,Test5 SETL TRUE ;将 Test5 变量赋值为真。,共74页,27,Test6 SETS “Testing” ;将 Test6变量赋值为“Testing” 。,4.3.2 定义寄存器列表伪指令,指令 LDM/STM 需要使用一个比较长的寄存器列表,使用伪指令 RLIST 可对一个列表定义一个统一的名称。, RLIST ,共74页,28,(8)LTORG,伪指令 LTORG 用来说明某个存储区域为一个用来暂存数据的数据缓冲区,也叫文字池或数据缓冲池。大的代码段也可以使用多个数据缓冲池。,4.3.3 数据定义伪指令,共74页,29
13、,下图为 LTORG 的作用。,共74页,30,当程序中使用 LDR 之类的指令访问数据缓冲池时,为防止越界发生,通常把数据缓冲池放在代码段的最后面,或放在无条件转移指令 或 子程序返回指令之后,这样处理器就不会错误地将数据缓冲池中的数据当作指令来执行。,共74页,31,AREA example, CODE, READONLY Start BL Func1 Func1 LDR R1,=0x800 MOV PC,LR LTORG ;定义数据缓冲池的开始位置 Date SPACE 40 ;数据缓冲池有40个被初 END ;始化为0的字节,共74页,32,在应用程序中经常使用一种如下图所示的表:,(
14、2)MAP 和 FIELD,共74页,33,MAP 可以用“” 代替。,MAP 用于定义一个结构化的内存表的首地址。语法格式如下:,MAP ,expr 为结构化表首地址。可以为 标号 或 数字表达式。,baseregister 为基址寄存器(可选项)。基址寄存器的值与 expr 的值之和就是表首地址。,共74页,34,MAP fun ; fun就是内存表的首地址 MAP 0x100,R9 ;内存表的首地址为R9+0X100,MAP 通常和 FIELD 伪指令相配合来定义一个结构化的内存表。,FIELD 伪指令用于定义一个结构化内存表中的数据域。, FIELD ,label 为标号。 要顶格写,
15、共74页,35,expr 为表达式。它的值为数据域所占的字节数。,FIELD 伪指令与 MAP 伪指令配合使用来定义结构化的内存表。 MAP 伪指令定义内存表的首地址; FIELD 伪指令定义内存表中各个数据域,并可以为每个数据域指定一个 标号 供其他指令引用。,共74页,36,MAP 0X100 ;定义结构化内存表首地址为 0X100 A FIELD 16 ;定义A的长度为16字节,位置为 0X100 B FIELD 32 ;定义B的长度为32字节,位置为 0X110 S FIELD 256 ;定义S的长度为256字节,位置为 0X130,注意:MAP 和 FIELD 伪指令仅用于定义数据结构,并不实际分配存储单元。 FIELD 也可用“#” 代替。,共74页,37,(3)SPACE,SPACE 伪指令用于分配一片连续的存储区域并初始化为 0。, SPACE ,表达式为要分配的 字节数,SPACE 也可用“%” 代替。,DataSpace SPACE 100 ;分配连续的100字节的存储单元并初始化为 0。,共74页,