一、伪操作
伪操作:不会生成代码,只是在编译之前告诉编译器怎么编译 不同的编译器伪操作也不同
GNU(gcc)的伪操作一般都以 ‘.’ 开头
.global 全局
.global symbol
@ 将symbol声明成全局符号
.local 局部
.local symbol
@ 将symbol声明成局部符号
.equ 声明
.equ DATA, 0xFF
@ 似于#define DATA 0xFF
MOV R1, #DATA
.macro 子函数
.macro FUNC
MOV R1, #1
MOV R2, #2
.endm
FUNC
@ 调用FUNC函数
.if .endif 条件编译
.if 0
@ 如果条件 0-假, 1-真
MOV R1, #1
MOV R2, #2
.endif
.rept 重复操作
.rept 3
@ 将下面这两行代码重复执行三次
MOV R1, #1
MOV R2, #2
.endr
.weak 弱化
@.weak symbol
@ 弱化一个符号,即告诉编译器即便没有这个符号也不要报错
.weak func
B func
.word 申请一个字空间
@ .word VALUE
@ 在当前地址申请一个字的空间并将其初始化为VALUE
MOV R1, #1
.word 0xFFFFFFFF
MOV R2, #2
.byte 申请一个字节空间
@ .byte VALUE
@ 在当前地址申请一个字节的空间并将其初始化为VALUE
MOV R1, #1
.byte 0xFF
.align 地址对齐
@ .align N
@ 告诉编译器后续的代码2的N次方对其
.align 4
@ 下面这条指令将会从2^4 = 16,0x16地址空间开始存储
MOV R2, #2
.arm ARM指令
.arm
@ 告诉编译器后续的代码是ARM指令
.thumb Thumb指令
.thumb
@ 告诉编译器后续的代码是Thumb指令
.text 代码段
.text
@ 定义一个代码段
.data 数据段
.data
@ 定义一个数据段
.space 申请N个字节空间
@ .space N, VALUE
@ 在当前地址申请N个字节的空间并将其初始化为VALUE
MOV R1, #1
.space 12, 0x12
@ 32位的处理器,0x4 — 0x16 地址空间将会全部存储12
MOV R2, #2
二、C和汇编的混合编程
C和汇编的混合编程原则:在哪种语言环境下符合哪种语言的语法规则
- 在汇编中将C中的函数当做标号处理
- 在C中将汇编中的标号当做函数处理
- 在C中内联的汇编当做C的语句来处理
方式一:汇编语言调用(跳转)C语言
汇编中:
MOV R1, #1
MOV R2, #2
BL func_c @ 将会跳到C语言代码中
MOV R3, #3
C语言中:
void func_c() {
int a;
}
方式二:C语言调用(跳转)汇编语言
C语言中:
void func_c() {
int a;
FUNC_ARM(); //将会跳转到汇编指令中
}
汇编中:
MOV R1, #1
MOV R2, #2
.global FUNC_ARM @ 全局变量
FUNC_ARM:
MOV R3, #3
方式三:C内联(内嵌)汇编
asm( “汇编指令\n” );
C语言中:
void func_c(void)
{
int a;
// C内联(内嵌)汇编
asm
(
"MOV R6, #6\n"
"MOV R7, #7\n"
);
}
三、ATPCS协议
ATPCS协议(ARM-THUMB Procedure Call Standard)
ATPCS协议主要内容
-
栈的种类
1.1使用满减栈 -
寄存器的使用
2.1 R15用作程序计数器,不能作其他用途
2.2 R14用作链接寄存器,不能作其他用途
2.3 R13用作栈指针,不能作其他用途
2.4 当函数的参数不多于4个时使用R0-R3传递,当函数的参数多于4个时,多出的部分用栈传递
2.5 函数的返回值使用R0传递
2.6 其它寄存器主要用于存储局部变量