• ARM伪指令与伪操作


    一、伪指令

      ARM伪指令有四个,分别是LDR、ADR、ADRL和NOP,下边对其分别介绍。

      1.1 LDR

      LDR 伪指令用于加载 32 位的立即数或一个地址值到指定寄存器 。形式如  LDR{cond} register,=[expr | label_expr],与 ARM 指令的 LDR 相比 , 伪指令的 LDR 的参数有“ =” 号 。LDR有三方面的应用:

      (1)用于加载常量,如 LDR R2, =0xFF0 其等同于MOV R2, #0xFF0 但需要注意的是LDR指令加载常量可以是合法的立即数也可以不是,但是MOV加载数时必须为合法的立即数。

      (2)设置GPIO

            GPIO-BASE EQU 0xe0028000
            ...
            LDR R0, =GPIO-BASE
            LDR R1,=0x00ffff00
            STR R1,[R0,#0x0c]

      (3)加载地址

            ...

            LDR R1,=InitStack

             ...

            InitStack

            MOV R0, LR

            ...

      1.2 ADR与ADRL

      两者都是将基于 PC 相对偏移的地址值或基于寄存器相对偏移的地址值读取到寄存器中 。形如 ADR{cond} register,expr 和LDR不同的是,这里没有等号。两者作用类似,区别在于两者可以加载的数的范围不同,当地址值是字节对齐时 , ADRL取值范围为- - 64K ~ 64K,ADR为- 255 ~ 255 。

      1.3 NOP

      空操作指令,就是什么也不干,静等时间流逝。

      1.4 ARM指令与伪指令的区别

      伪指令经过汇编编译后就不存在了,而指令依旧存在。伪操作只是汇编过程中起作用, , 一旦汇编结束, ,伪操作也就随之消失。另外,ARM 伪指令不属于 ARM 指令集中的指令,是为了编程方便而定义的。

      总结:其实LDR、ADRL、ADR的作用和用法基本类似,主要区别是加载数的范围大小不同,LDR加载范围最大,ADRL次之,ADR最小。另外,使用LDR伪指令时,操作数要带“=”号,ADRL和ADR则不需要。

    二、伪操作

      伪操作主要有符号定义、数据定义、指令集类型标识和其他类型四种,下边将进行一一介绍。

    2.1 符号定义伪操作

      符号定义伪操作用于定义 ARM 汇编程序中的变量、对变量赋值及定义寄存器的别名等操作。常见的符号定义伪操作有如下几种:

      (1)局部变量定义 LCLA 、 LCLL 及 LCLS

      (2)全局变量定义 GBLA 、 GBLL 及 GBLS

      (3)变量赋值伪操作 SETA 、 SETL 及 SETS

      (4)给通用寄存器列表定义名称RLIST

      A为Arithmetic的首字母,意为定义一个数字变量。L为Logic的首字母,意为定义一个逻辑变量(true或false)。S为String的首字母,意为定义一个字符串变量。举个例子:

            GBLA Test1             ;定义全局数字变量Test1
            Test1 SETA 0xaa          ;Test1=0xaa
            GBLL Test2              ;定义全局逻辑变量Test2
            Test2 SETL {TRUE}     ;Test2=True
            GBLS Test3             ;定义全局字符串变量Test3
            Test3 SETS “Testing”      ;Test3=“Testing”

      RLIST 形式如 name RLIST {registers_list} ,该伪操作用于给一个通用寄存器列表定义名称,使用该伪操作定义的名称可以在 LDM/STM 中使用。再举个例子:

            list RLIST {R0-R2,R6,R8}    ;当你定义一个列表后,以后再用就直接写列表名称就好

            LDMIA R3!,{R0-R2,R6,R8}      ;好处就是当需要多次加载同一寄存器列表时,极大地简化了书写

            LDMIA R3!,list            ;和上边的语句效果一样

     2.2 数据定义伪操作

      数据定义伪操作一般用于为特定的数据分配存储单元,同时可完成已分配存储单元的初始化。常见的数据定义伪操作有如下几种:

      (1)DCB 用于分配一片连续的字节存储单元并用指定的数据初始化。

      (2)DCD  用于分配一片连续的存储单元并用指定的数据初始化。

      (3)LTORG  用于声明一个数据缓冲池。

      (4)SPACE 用于分配一片连续的存储区域并将其初始化为0 。

      (5)MAP 用于定义一个结构化的内存表首地址。

      (6)FIELD 用于定义一个结构化的内存表的数据域。

      这六个伪操作中的DCB和DCD会在文末给出一个综合的示例来讲解其用法,这里先从LTORG开始讲。LTORG主要配合LDR伪指令一起使用,我们都知道用MOV指令时,由于ARM分配了12位用来存储立即数,所以并不是所有的立即数数都能被存储,这才有了合法与不合法的立即数之说,而LDR伪指令之所以能加载不合法的立即数的原因就是LTORG存在,使用LDR伪指令时,立即数有多大,你就可以声明一个相应大小的数据缓冲池来存放该立即数。当然你完全不用显式声明,当你不写时,ARM系统会在编译阶段自动为其补上,所以只需了解这个伪操作即可。这里给了一个例子,帮助你了解LTORG 的使用,看不懂可跳过,反正也不太重要。

            LDR  R0,  =0xAABBCCDD
            EOR R1 ,R1,R0
            B  SUB _pro
            LTORG            ;声明一个数据缓冲池用来存储0xAABBCCDD

      SPACE的作用就如上边所说,具体使用例子如下:

            AREA Data,DATA,READWRITE
            DataBuf SPACE 1000
            …

      MAP与FIELD也是一起使用的,它俩有点像C语言中的结构体,具体例子如下,自行理解。
            MAP 0x300         ;定义一个结构化的内存表,首地址固定为0x300,包含4个域
              Fdata1 FIELD 4      ;Fdata1 长度为4字节
              Fdata2 FIELD 8      ;Fdata2 长度为8字节
              Fdata3 FIELD 100    ;Fdata3 长度为 100 字节
              Fdata4 FIELD 200    ;Fdata4 长度为 200 字节

    三、指令集类型标识

      指令集类型标识伪操作用来告诉编译器所处理的是32 位的ARM 指令还是16 位的Thumb 指令,实现这一操作的操作符有ARM 、CODE32 、THUMB、CODE16。其中ARM CODE32指示编译器将要处理的是 32 位的 ARM 指令,而THUMB和CODE16指示编译器将要处理的是 16 位的 Thumb 指令。具体例子如下:

              AREA ToThumb,CODE,READONLY
              ENTRY
              ARM                ;注意这里
            start
              ADR R0,into_thumb+1
              BX R0
              THUMB               ;注意这里
              into_thumb
              MOVS R0,#10

              …

    四、其他类型伪操作

      下边主要讲四种相对常用又简单的伪操作,由于内容相对简单,具体示例统一在文末的综合示例中给出。

      (1)段属性定义伪操作AREA

      (2)源程序结尾标识END

      (3)声明程序的入口点ENTRY

      (4)定义常量或标号名称EQU

      AREA 用于定义一个代码段或数据段, AREA  伪操作指示汇编器汇编新的代码段或数据段。

      END 伪操作用于通知编译器已经到了源程序的结尾。相当于汉语中的句号吧。

      ENTRY 伪操作用于指定汇编程序的入口点。在一个完整的汇编程序中(一个程序可以包含多个源文件)至少要有一个ENTRY, 但在一个源文件里不能使用多个ENTRY。

      EQU 伪操作用于为程序中的常量、标号等定义一个等效的字符名称。

    五、综合示例

      该例子综了以上学习的伪指令和伪操作,主要作用是将src中内容复制到dst中。

     

    学习和码字过程难免出现疏漏,欢迎指正!QQ:1801888312
  • 相关阅读:
    Android应用程序组件Content Provider在应用程序之间共享数据的原理分析
    Android录制声音(二)录音输输出格式
    Firemacs:像垄断 Emacs 一样垄断 Firefox
    超棒的 KDE 面板小序次-Kirocker Music Display
    特征化设置你的linux环境
    软响铃 ── 把 beep 换成音乐
    简化 Picasa 图片上传
    Moonlight:Linux 平台上的 Silverlight
    Wine 0.9.39
    本钱与linux
  • 原文地址:https://www.cnblogs.com/liuguo/p/12919429.html
Copyright © 2020-2023  润新知