WHIL 和WEND
WHILE 和WEND 伪指令用于根据条件重复汇编相同的或几乎相同的一段源程序。
伪指令格式:
WHILE logical_expr
;指令或伪指令代码段
WEND
其中:logical_expr 用于控制的逻辑表达式。若条件成立,则代码段在汇编源程序中有效,并不断重复这段代码直到条件不成立。
伪指令应用举例如下:
WHILE no<5
no SETA no+1
…
WEND
WHILE 和WEND 伪指令是可以嵌套使用的。
A.4.5 杂项伪指令
杂项伪指令在汇编编程设计较为常用,如段定义伪指令,入口点设置伪指令,包含文件伪指令,标号导出或引入声明等,该类伪指令如下:
边界对齐: ALIGN。
段定义: AREA。
指令集定义: CODE16 和CODE32。
汇编结束: END。
程序入口: ENTRY。
常量定义: EQU。
声明一个符号可以被其它文件引用:EXPORT 和GLORBAL。
声明一个外部符号:IMPORT 和EXTERN。
包含文件:GET 和INCLUDE。
包含不被汇编的文件:INCBIN。
保留符号表中的局部符号:KEEP。
禁止浮点指令:NOFP。
指示两段之间的依赖关系:REQUIRE。
堆栈8 字节对准:PEQUIRE8 和PRESERVE8。
给特定的寄存器命名:RN。
标记局部标号使用范围的界限:ROUT。
ALIGN
ALIGN 伪指令通过添加补丁字节使当前位置满足一定的对齐方式。
伪指令格式:
ALIGN {expr{,offset}}
其中:expr 数字表达式,用于指定对齐的方式。取值为2 的n 次幂,如1、2、4、8等,不能为0 其没有expr,则默认为字对齐方式。
offset 数字表达式,当前位置对齐到下面形式的地址处:offset+n*expr
在下面的情况中,需要特定的地址对齐方式:
(A)Thumb 伪指令ADR 要求地址是字对齐的。而Thumb 代码中地址标号可能不是字对齐的。这时就要使用伪指令ALIGN4 使Thumb 代码中地址标号为字对齐。
(B)由于有些ARM 处理器的Cache 采用了其他对齐方式。如16 字节对齐方式,这时使用ALIGN 伪指令指定合适的对齐方式可以充分发挥Cache 的性能优势。
(C)LDRD 和STRD 指令要求存储单元为8 字节对齐。这样在为LDRD/STRD 指令分配的存储单元前要使用伪指令ALIGN8 实现8 字节对齐方式。
(D)地址标号通常自身没有对齐要求,而在ARM 代码中要求地起标号对齐是字对齐的,Thumb 代码中要求半字对齐。这样可以使用ALIGN4 和ALIGN2 伪指令来调整对齐方式。
伪指令应用举例如下。
通过ALIGN 伪指令使程序中的地址标号字对齐:
AREA Example,CODE,READONLY ;声明代码段Example
START LDR R0,=Sdfjk
…
MOV PC,LR
Sdfjk DCB 0x58 ;定义一字节存储空间,字对齐方式被破坏
ALIGN ;声明字对齐
SUBI MOV R1,R3 ;其它代码
…
MOV PC,LR
在段定义AREA 中,也可使用ALIGN 伪指令对齐,但表达式的数字含义是同的
AREA MyStack,DATA,NOINIT,ALIGN=2 ;声明数据段
;MyStack,并重新字对齐
IrqStackSpace SPACE IRQ_STACK_LEGTH*4 ;中断模式堆栈空间
FiqStackSpace SPACE FIQ_STACK_LEGTH*4 ;快速中断模式堆栈空间
AbtStackSpace SPACE ABT_STACK_LEGTH*4 ;中止义模式堆栈空间
UndtStackSpace SPACE UND_STACK_LEGTH*4 ;未定义模式堆栈
…
将两个字节的数据放在同一个字的第一个字节和第四个字节中,带offset 的ALIGN对齐:
AREA offsetFxample, CODE
DCB 0x31 ;第一个字节保存0x31
ALIGN 4,3 ;字对齐
DCB 0x32 ;第四个字节保存0x32
…
AREA
AREA 伪指令用于定义一个代码段或数据段。ARM 汇编程序设计采用分段式设计,一个ARM 源程序至少需要一个代码段,大的程序可以包含多少个代码段及数据段。
伪指令格式:
AREA sectionname{,attr}{,attr}…
其中:sectionname 所定义的代码段或数据段的名称。如果该名称是以数据开头的,则该名称必须用“|”括起来,如|1_datasec|。还有一些代码段具有的约定的名称。如|text|表示C 语言编译器产生的代码段或者与C 语言库相关的代码段。
attr 该代码段或数据段的属性。
在AREA 伪指令中,各属性之间用逗号隔开。以下为段属性及相关说明:
ALIGN = expr。默认的情况下,ELF 的代码段和数据段是4 字节对齐的,expr 可以取0~31 的数值,相应的对齐方为2expr 字节对齐。如expr=3 时为字节对齐。对于代码段,expr 不能为0 或1。
ASSOC = section。指定与本段相关的ELF 段。任何时候连接section 段也必须包括sectionname 段。
DODE 为定义代码段。默认属性为READONLY。
COMDEF 定义一个通用的段。该段可以包含代码或者数据。在其它源文件中,同名的COMDEF 段必须相同。
COMMON 定义一个通用的段。该段不包含任何用户代码和数据,连接器将其初始化为此。各源文件中同名的COMMON 段共用同样的内存单元,连接器为其分配合适的尺寸。
DATA 为定义段。默认属性为READWRITE。
NOINIT 指定本数据段仅仅保留了内存单元,而没有将各初始写入内存单元,或者将内存单元值初始化为0。
READONLY 指定本段为只读,代码段的默认属性为READONLY。
READWRITE 指定本段为可读可写。数据段的默认属性为READWRITE。
使用AREA 伪指令将程序分为多个ELF 格式的段,段名称可以相同, 这时同名的段被放在同一个ELF 段中。
伪指令应用举例如下:
AREA Example ,CODE,READNOLY ;声明一个代码,名为Example