系统学习ARM之四 --GNU的伪指令集

转载自http://blog.csdn.net/qqliyunpeng/article/details/48791487

一、伪指令 的含义

    伪指令是 编译器支持的指令,不是硬件芯片支持的指令。
    编译器在编译时,会把伪指令转化对应的芯片支持的指令
        伪指令集包括: 伪操作和伪指令

二、伪操作

1. 数据定义(Data Definition)伪操作

    数据定义伪操作一般用于为特定的数据分配存储单元,同时可完成已分配存储单元的初始化。 
    常见的数据定义伪操作有如下几种:
          .byte                  字节定义                .byte     0x12,’a’,23
          .short                定义 2字节数据 .short    0x1234,65535
          .long /.word     定义 4字节数据 .word     0x12345678
          .quad                 定义 8字节 .quad     0x1234567812345678
          .float                  定义浮点数 .float    0f3.2
          .string/.asciz/.ascii   定义字符串   .ascii   “abcd\0”,
              注意:. ascii  伪操作定义的字符串 需要每行添加结尾字符 '\0',其他不需要

例子:
    int val = 0x11223344;
    val:
    .word  0x11223344
    注意:
        1--变量的定义放在,stop后,.end前
        2--标号是地址的助记符, 标号不占存储空间

2. 汇编控制伪操作


    (1).if .else .endif    ---- 类似c语言里的条件编译
            汇编控制伪操作用于控制汇编程序的执行流程

        .if、.else   .endif伪操作能根据条件的成立与否决定是否执行某个指令序列。
        当.if后面的逻辑表达式为真,则执行.if后的指令序列,否则执行.else后的指令序列;
         .if、.else、.endif伪指令可以嵌套使用。
 
          .if  logical-expressing
         …
          .else
            …
           .endif


    (2).macro,.endm   --- 类似c语言里的宏函数    
        macro伪操作可以将一段代码定义为一个整体,称为宏指令。
        然后就可以在程序中通过宏指令多次调用该段代码。
        其中,$标号在宏指令被展开时,标号会被替换为用户定义的符号。
        宏操作可以使用一个或多个参数,当宏操作被展开时,这些参数被相应的值替换。

   语法格式:
   .macro    {$label} 名字{$parameter{,$parameter}…}
    ……..code
   .endm

注意:先定义后使用
     .macro  func1
        mov r1,#1
        mov r2,#2
        mov r3,#3
    .endm
 
        func1
        func1
        func1

3.  杂项伪操作

    .arm           .arm                         定义一下代码使用ARM指令集编译
    .thumb      .thumb                    定义一下代码使用Thumb指令集编译
    .section     .section     expr       定义一个 。expr可以使.text   .data.   .bss
    .text           .text {subsection}   将定义符开始的代码 编译到代码段
    .data         .data {subsection}   将定义符开始的代码 编译到数据段,初始化数据段
    .bss           .bss {subsection}     将变量存放到 .bss段,未初始化数据段
    .align       .align{alignment}{,fill}{,max}  通过 用零或指定的数据进行填充来使当前位置与指定边界对齐
        .align  4     --- 16字节 2的4次
        .align  (4)   --- 4字节
    .org        .org offset{,expr}    指定从当前地址加上offset开始 存放代码
        并且从当前地址到当前地址加上offset之间的内存单元,用 零或指定的数据进行填充
    _start   汇编程序的缺省入口是_ start标号,用户也可以在连接脚本文件中用ENTRY标志指明其它入口点.
    .global/ .globl :用来声明一个全局的符号
    .end       文件结束

    .include 格式:.include “filename”
       包含指定的头文件, 可以把一个汇编常量定义放在头文件中

    .equ    格式:.equ    symbol,    expression
        把某一个符号(symbol)定义成某一个值(expression).该指令并不分配空间.( c语言的 #define)
     #define  PI  3.1415    ==     .equ   PI, 3.1415

 

三、伪指令 :

关键点:伪指令在编译时会转化为对应的ARM指令

    1. ADR伪指令 :    --把标签所在的地址加载到寄存器中

        ADR伪指令为小范围地址读取伪指令,使用的相对偏移
        范围:当地址值是 字节对齐 (8位) 时,取值范围为 -255~255
        当地址值是 字对齐 (32位) 时,取值范围为 -1020~1020

      语法格式:
          ADR{cond}   register,label
         ADR      R0,  lable

    2. ADRL伪指令: --将中等范围地址读取到寄存器中

        ADRL伪指令为中等范围地址读取伪指令。使用相对偏移
        范围:当地址值是 字节对齐时,取值范围为 -64~64KB
        当地址值是 字对齐时,取值范围为 -256~256KB

        语法格式: 
             ADRL{cond}  register,label
            ADRL        R0,lable

    3. LDR伪指令: LDR伪指令装载一个32位的常数和一个地址到寄存器。

        语法格式:
             LDR{cond}  register,=[expr|label-expr]
            LDR    R0,=0XFFFF0000
        注意: 
        (1)ldr伪指令和ldr指令区分
                ldr r1,=val  @ r1 = val    是  伪指令
                ldr r2,val   @ r1 = *val    是 arm 指令
                .val
               .word 0x11223344
        (2)怎么取 用ldr伪指令实现长跳转
                 ldr  pc,=32位地址

           (3)编码中解决立即数的问题
                用arm伪指令ldr
                0x999  不是立即数,
                ldr r0,=0x999


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值