一、.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)