ARM汇编伪操作(二)

其他伪操作
还有一些其他的伪指令,在汇编程序中经常会被使用,包括以下几条:   
    — AREA   
    — ALIGN   
    — CODE16 、 CODE32   
    — ENTRY   
    — END   
    — EQU   
    — EXPORT (或 GLOBAL )   
    — IMPORT   
    — EXTERN   
    — GET (或 INCLUDE )   
    — INCBIN   
    —KEEP:告诉编译器将局部符号包含在目标文件的符号表中
    — NOFP:禁止源程序中包含浮点运算指令
    — REQUIRE:指定段之间的相互依赖关系
    — REQUIRE 8及PRESERVE8:指示当前代码中(要求)数据栈8字节对齐
    — RN   
    — ROUT   
    1、 AREA   
    语法格式:   
    AREA 段名 属性 1 ,属性 2 ,……   
    AREA 伪指令用于定义一个代码段或数据段。其中,段名若以数字开头,则该段名需用 “ | ” 括起来,如 |1_test| 。还有一些代码段具有约定的名称,如|.text|表示C语言编译器产生的代码段或者是与C语言库相关的代码段。
    属性字段表示该代码段(或数据段)的相关属性,多个属性用逗号分隔。常用的属性如下:   
    — CODE 属性:用于定义代码段,默认为 READONLY 。   
    — DATA 属性:用于定义数据段,默认为 READWRITE 。   
    — NOINIT 属性:指定本数据段仅仅保留了内存单元,而没有将各初始值写入内存单元,或者将各内存单元初始化为0.
    — READONLY 属性:指定本段为只读,代码段默认为 READONLY 。   
    — READWRITE 属性:指定本段为可读可写,数据段的默认属性为 READWRITE 。   
    — ALIGN 属性:使用方式为 ALIGN 表达式。在默认时, ELF (可执行连接文件)的代码段和数据段是按字对齐的,表达式的取值范围为 0 ~ 31 ,相应的对齐方式为 2 表达式次方。如表达式=3时为8字节对齐。
    —ASSOC=section。指定与本段相关的ELF段。任何时候连接section段也必须包括sectionname段。
    — COMMON 属性:该属性定义一个通用的段,不包含任何的用户代码和数据。连接器将其初始化为0。各源文件中同名的 COMMON 段共享同一段内存单元,连接器为其分配合适的尺寸。
    — COMDEF 属性:该属性定义一个通用的段,该段可以包含代码或数据。在各源文件中,同名的COMDEF段必须相同。
通常可以用AREA伪操作将程序分为多个ELF格式的段。段名称可以相同,这时这些同名的段被放在同一个ELF段中。一个大的程序可以包括多个代码段和数据段,一个汇编语言程序至少要包含一个段。   
    使用示例:   
    AREA Init , CODE , READONLY   
    该伪操作定义了一个代码段,段名为 Init ,属性为只读   

    2、 ALIGN   
    语法格式:   
    ALIGN { 表达式 { ,偏移量 }}   
    ALIGN 伪指令可通过添加填充字节的方式,使当前位置满足一定的对齐方式 。其中,表达式的值用于指定对齐方式,可能的取值为 2 的幂,如 1 、 2 、 4 、 8 、 16 等。若未指定表达式,则将当前位置对齐到下一个字的位置。偏移量也为一个数字表达式,若使用该字段,则当前位置的对齐方式为: 2 的表达式次幂+偏移量。   
下面的情况中,需要特定的地址对齐方式:
1) Thumb的宏指令ADR要求地址是字对齐的,而Thumb代码中地址标号可能不是字对齐的。这时就要使用伪操作ALIGN 4使Thumb代码中的地址标号字对齐。
2) 由于有些ARM处理器的CACHE采用了其他对齐方式,如16字节的对齐方式,这时使用ALIGN伪操作指定合适的对齐方式可以充分发挥该CACHE的性能优势。
3) LDRD以及STRD指令要求内存单元是8字节对齐的。这样在为LDRD/STRD指令分配的内存单元前要使用ALIGN 8实现8字节对齐方式
4) 地址标号通常自身没有对齐要求。而在ARM代码中要求地址标号是字对齐的,在Thumb代码中要求字节对齐。这样需要使用合适的ALIGN伪操作来调整对齐方式。
    使用示例:   
    在AREA伪操作中的ALIGN与ALIGN伪操作中表达式含义是不同的
AREA Init ,CODE,READONLY, ALIEN = 3 ;指定后面的指令为 8 字节对齐。   
    指令序列   
    MOV pc,lr ;程序跳转后变成4字节对齐的
ALIGN 8 ;指定下面的指令是8字节对齐的
指令序列
END   

    3、 CODE16、CODE32   
    语法格式:   
    CODE16 (或 CODE32 )   
    CODE16 伪操作告诉编译器,其后的指令序列为 16 位的 Thumb 指令。   
    CODE32 伪操作告诉编译器,其后的指令序列为 32 位的 ARM 指令。   
    若在汇编源程序中同时包含 ARM 指令和 Thumb 指令时,可用 CODE16 伪操作通知编译器其后的指令序列为 16 位的 Thumb 指令, CODE32 伪操作通知编译器其后的指令序列为 32 位的 ARM 指令。因此,在使用 ARM 指令和 Thumb 指令混合编程的代码里,可用这两条伪操作进行切换,但注意他们只是告诉编译器其后指令的类型,本身并不能对处理器进行程序状态的切换。   
    使用示例:   
    AREA Init , CODE , READONLY   
    ……   
    CODE32 ;通知编译器其后的指令为 32 位的 ARM 指令   
    LDR R0 ,= NEXT + 1 ;将跳转地址放入寄存器 R0   
    BX R0 ;程序跳转到新的位置执行,并将处理器切换到 Thumb 工作状态   
    ……   
    CODE16 ;通知编译器其后的指令为 16 位的 Thumb 指令   
    NEXT LDR R3,=0x3FF   
    ……   
    END ;程序结束
  
    4、 ENTRY   
    语法格式:   
    ENTRY   
    ENTRY 伪操作用于指定汇编程序的入口点。在一个完整的汇编程序中至少要有一个 ENTRY (也可以有多个,当有多个 ENTRY 时,程序的真正入口点由链接器指定),但在一个源文件里最多只能有一个 ENTRY (可以没有)。   
    使用示例:   
    AREA Init , CODE , READONLY   
    ENTRY ;指定应用程序的入口点   
    ……   

    5、 END   
    语法格式:   
    END   
    END 伪操作用于通知编译器已经到了源程序的结尾。   
    使用示例:   
    AREA Init , CODE , READONLY   
    ……   
    END ;指定应用程序的结尾  

    6、 EQU (“ * ”)
    语法格式:   
    名称 EQU 表达式 { ,类型 }   
    EQU 伪操作用于为程序中的常量、基于寄存器的值和程序中的标号定义一个字符名称,其作用类似于 C 语言中的# define 。   
    名称为 EQU 伪操作定义的字符名称,表达式为基于寄存器的地址值、程序中的标号、32位的地址常量或者32位的常量。当表达式为 32 位的常量时,可以指定表达式的数据类型,可以有以下三种类型:   
    CODE16 、 CODE32 和 DATA   
    使用示例:   
    Test EQU 50 ;定义标号 Test 的值为 50   
    Addr EQU 0x55 , CODE32 ;定义 Addr 的值为 0x55 ,且该处为 32 位的 ARM 指令。   

    7、 EXPORT(或GLOBAL)   
    语法格式:   
    EXPORT 符号 {[WEAK]}   
    EXPORT 伪操作声明一个符号可以被其他文件引用,相当于声明了一个全局变量。 EXPORT可用 GLOBAL 代替。符号在程序中区分大小写, [WEAK] 选项声明其他的同名符号优先于该符号被引用。   
    使用示例:   
    AREA Init , CODE , READONLY   
    EXPORT DoAdd;下面的函数名称DoAdd可以被其他源文件引用
DoAdd ADD r0,r0,r1
    END   

    8、 IMPORT   
    语法格式:   
    IMPORT 符号 {[WEAK]}   
    IMPORT 伪操作告诉编译器当前的符号不是在本源文件中定义的,而是在其他源文件中定义的,在本源文件中可能引用该符号,而且不论本源文件是否实际引用该符号,该符号均会被加入到本源文件的符号表中。(与下面的EXTERN的区别之处)   
    符号在程序中区分大小写, [WEAK] 指定这个选项后,如果符号在所有的源文件中都没有定义,编译器也不会产生任何错误信息,同时编译器也不会到当前没有被INCLUDE进来的库中去查找该符号。
使用IMPORT伪操作声明一个符号是在其他源文件中定义的。如果连接器在连接处理时不能解析该符号,而IMPORT伪操作中没有指定 [WEAK]选项,则连接器会报告错误。如果连接器在连接处理时不能解析该符号,而IMPORT伪操作中指定了[WEAK]选项,则连接器将不会报告错误,而是进行下面的操作:
1) 如果该符号被B或者BL指令引用,则该符号被设置成下一条指令的地址,该B或者BL指令相当于一条NOP指令
2) 其他情况下该符号被设置为0.
使用示例:   
    AREA Init , CODE , READONLY   
    IMPORT Main ;通知编译器当前文件要引用标号Main,但Main 在其他源文件中定义……
   
    END   

    9、 EXTERN   
    语法格式:   
    EXTERN 符号 {[WEAK]}   
    EXTERN 伪操作告诉编译器当前的符号不是在本源文件中定义的,而是在其他源文件中定义的,在本源文件中可能引用该符号。如果本源文件没有实际引用该符号,该符号将不会被加入到本源文件的符号表中。
注:与IMPORT的不同之处
    使用示例:   
    AREA Init , CODE , READONLY   
    EXTERN Main ;通知编译器当前文件要引用标号Main,但Main 在其他源文件中定义……   
    END   
    10、 GET(或INCLUDE)   
    语法格式:   
    GET 文件名   
    GET 伪操作用于将一个源文件包含到当前的源文件中,并将被包含的源文件在当前位置进行汇编处理。可以使用 INCLUDE 代替 GET 。可以使用路径信息(路径信息中可以包含空格)。   
    汇编程序中常用的方法是在某源文件中定义一些宏指令,用 EQU 定义常量的符号名称,用 MAP和 FIELD 定义结构化的数据类型,这样的源文件类似于C语言中的.H文件。然后用 GET 伪操作将这个源文件包含到其他的源文件中。使用方法与 C 语言中的 “ include *.h” 相似。   
    GET 伪操作只能用于包含源文件,包含目标文件需要使用 INCBIN 伪操作   
    使用示例:   
    AREA Init , CODE , READONLY   
    GET a1.s ;通知编译器当前源文件包含源文件a1.s   
    GET C:/project/file2.s ;通知编译器当前源文件包含源文件C:/project/file2.s
    END   

    11、 INCBIN   
    语法格式:   
    INCBIN 文件名   
    INCBIN 伪操作用于将一个目标文件、执行文件或任意的数据包含到当前的源文件中,被包含的文件不作任何变动(不进行汇编处理)的存放在当前文件中,编译器从INCBIN伪操作后面开始继续处理。这里所包含的文件名称及其路径信息中都不能有空格。
    使用示例:   
    AREA Init , CODE , READONLY   
    INCBIN a1.dat ;通知编译器当前源文件包含文件a1.dat   
    INCBIN C:/a2.txt ;通知编译器当前源文件包含文件C:/a2.txt……   
    END   

    12、 RN   
    语法格式:   
    名称 RN 表达式   
    RN 伪操作用于给一个寄存器定义一个别名。采用这种方式可以方便程序员记忆该寄存器的功能。其中,名称为给寄存器定义的别名,表达式为寄存器的编码。   
    使用示例:   
    Temp RN R0 ;将R0 定义一个别名Temp   

    13、 ROUT   
    语法格式:   
    { 名称 } ROUT   
    ROUT 伪操作用于给一个局部变量定义作用范围。在程序中未使用该伪操作时,局部变量的作用范围为所在的 AREA ,而使用 ROUT 后,局部变量的作用范围为当前 ROUT 和下一个 ROUT 之间。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值