GNU ARM伪指令

一、.global 伪指令

该伪指令的含义是让.global 修饰的符号对连接器可见,也就是说,一个函数或变量通常情况下只在文本文件内有效,当需要在外部引用该文件里的某一个函数或变量时,必须首先将该函数或变量使用.global伪指令进行声明。

例如:

.gloabl _start

.global  main

_start :

    b main

这里的_start要被外部的链接脚本使用,所以声明为全局。这里的main符号是外面文件实现的main函数,main函数也是在外面实现的,所以声明为全局。

二、.equ 伪指令

该伪指令其实很简单,相当于C中的宏定义。使用格式如下:

.equ  名字,值

例如:

.equ MAX,100

其实就是等价于C语言的#defineMAX 100是一个意思。

三、.align伪指令

功能为使代码对齐到某一边界。

在ARM体系结构下,.align 后边的数以幂的形式出现的,例如:

.align 2 表示从此处开始代码要以4字节对齐,呵呵,有人经常会问什么意思呀。

它还有一个变体:.balign 这里的b就是byte的缩写。如果写成.balign4就是直接表示4字节对齐。

先来看一个实例代码:

.align 4表示,以16字节对齐。可以看到其前面只有一条指令,在ARM状态每条指令占用4字节,则还需要填充三条指令,就以达到16字节对齐了。

它反汇编的结果:



看完反汇编结果后我们得出如下规律:

从第一条ARM指令开始,到.align  4这个位置,要求总指令的条数是8的倍数,即.align 4所在的地址 + 4能整除8。如果不是则需要填充。从.align4开始,到最后一条指令,也要求总指令的条数是8的倍数,如果不是则需要填充。

那它什么时候会用到呢?我们先来看一下一下代码:

编译后的结果:

错误的意思是分支目标出现了偏差,即没有对齐了。ARM指令要求4字节对齐,由于.byte是占用一个字节,此时就没有对齐啦。怎么解决这个问题呢?加一个.align对齐一下就可以了。

修改后的代码:

编译成功后,反汇编的结果如下:



有些人常常写成这样,如下图所示:

 

四、.macro 伪指令

macro伪操作可以将一段代码定义为一个整体,称为宏指令,然后就可以在程序中通过宏指令多次调用该段代码。其中,$标号在宏指令被展开时,标号会被替换为用户定义的符号。宏操作可以使用一个或多个参数,当宏操作被展开时,这些参数被相应的值替换。宏操作的使用方式和功能与子程序有些相似,子程序可以提供模块化的程序设计、节省存储空间并提高运行速度。但在使用子程序结构时需要保护现场,从而增加了系统的开销,因此,在代码较短且需要传递的参数较多时,可以使用宏操作代替子程序。

语法格式:

  .macro 宏名 参数名列表   @伪指令.macro

定义一个宏 宏体 

.endm @.endm表示宏结束

 

实例:通过宏来实现memcpy功能

.global _start

.text

_start:

b reset

.macro memory_copysrc_addr,dest_addr,num

@保存r0,r1,r2,r3

@参数在使用的时候,前面要加上"\"

stmfd sp!,{r0,r1,r2,r3}

ldr r0,=\src_addr

ldr r1,=\dest_addr

ldr r2,=\num

loop:

ldr r3,[r0],#4

str r3,[r1],#4

sub r2,r2,#1

cmp r2,#0

@恢复r0,r1,r2,r3

ldmeqfd sp!,{r0,r1,r2,r3}

bne loop

.endm

reset:

memory_copy SRC_ADDR,DEST_ADDR,4

stop:

b stop

SRC_ADDR:

.word 0x0a

.word 0x0b

.word 0x0c

.word 0x0d

DEST_ADDR:

.word 0xff

.word 0xff

.word 0xff

.word 0xff

反汇编的结果如下:

asm.o:     file format elf32-littlearm

Disassembly of section .text:

00000000 <_start>:

  0: eaffffff  b 4

00000004 :

  4: e92d000f  push {r0, r1, r2, r3}

  8: e59f0040  ldr r0, [pc, #64] ; 50

  c: e59f1040  ldr r1, [pc, #64] ; 54

 10: e3a02004  mov r2, #4 ; 0x4

00000014 :

 14: e4903004  ldr r3, [r0], #4

 18: e4813004  str r3, [r1], #4

 1c:e2422001  sub r2, r2, #1 ; 0x1

 20: e3520000  cmp r2, #0 ; 0x0

 24: 08bd000f  popeq {r0, r1, r2, r3}

 28: 1afffff9  bne 14

0000002c:

 2c:eafffffe  b 2c

00000030 :

 30: 0000000a  .word 0x0000000a

 34: 0000000b  .word 0x0000000b

 38: 0000000c  .word 0x0000000c

 3c:0000000d  .word 0x0000000d

00000040 :

 40: 000000ff  .word 0x000000ff

 44: 000000ff  .word 0x000000ff

 48: 000000ff  .word 0x000000ff

 4c:000000ff  .word 0x000000ff

 50: 00000030  .word 0x00000030

 54: 00000040  .word 0x00000040

五、GNU 局部编号

局部标号:局部标号 主要在局部范围内使用而且局部标号可以重复出现。它由两部组成开头是一个0-99直接的数字局部标号后面加“:”         

F:指示编译器只向前搜索(front)

B:指示编译器只向后搜索(back)

你可能感兴趣的:(ARM体系结构)