目录
一、伪操作
不会生成代码,只是在编译之前告诉编译器怎么编译
不同的编译器伪操作的语法不同,这里讲的是gcc编译器的伪操作语法
.GNU的伪操作一般都以 ‘.’ 开头
.global symbol
@将symbol声明成全局符号
.local symbol
@ 将symbol声明成局部符号
.equ DATA, 0xFF
@ MOV R1, #DATA
@代码封装
.macro FUNC
MOV R1, #1
MOV R2, #2
.endm
FUNC
@条件编译
.if 0
MOV R1, #1
MOV R2, #2
.endif
.rept 3 @重复执行被包裹的语句3次
MOV R1, #1
MOV R2, #2
.endr
@.weak symbol@ 弱化一个符号,即告诉编译器即便没有这个符号也不要报错
.weak func
B func
@.word VALUE 在当前地址申请一个字的空间并将其初始化为VALUE
MOV R1, #1
.word 0xFFFFFFFF
MOV R2, #2
@ .byte VALUE 在当前地址申请一个字节的空间并将其初始化为VALUE
MOV R1, #1 @0X00
.byte 0xFF @0x04
MOV R2, #2 @ 加这句报错,因为这条指令的起始地址不是4的整数倍,0x05
@.space N, VALUE @ 在当前地址申请N个字节的空间并将其初始化为VALUE
MOV R1, #1
.space 12, 0x12
MOV R2, #2
.align N @告诉编译器后续的代码2的N次方对齐,后面的地址要是2的N次方的倍数
.align 4 @告诉编译器后续的代码2的4次方对齐
MOV R2, #2
.arm @告诉编译器后续的代码是ARM指令
.thumb @ 告诉编译器后续的代码是Thumb指令
.text @ 定义一个代码段
.data @定义一个数据段
二、C和汇编的混合编程
为什么要用C和汇编混合编程:
汇编语言分为通用指令和专用指令。
通用指令是指数据处理指令、跳转指令、内存读写指令,这些指令可以在任意处理器上运行,而C语言也是通用语言,因此可以用C语言写这些通用指令。
专用指令是指某个处理器独有的指令,如ARM,有修改CPSR状态指令、软中断指令和协处理器指令,这些专用指令不能用C语言编写,因此只能用汇编来写。
所以需要C语言和汇编混合编程。
C和汇编的混合编程:
C和汇编的混合编程原则:在哪种语言环境下符合哪种语言的语法规则
1. 在汇编中将C中的函数当做标号处理
2. 在C中将汇编中的标号当做函数处理
3. 在C中内联的汇编当做C的语句来处理
1.方式一:汇编语言调用(跳转)C语言
1. 方式一:汇编语言调用(跳转)C语言
MOV R1, #1
MOV R2, #2
BL func_c 执行完func_c会自动跳回来
fun_c最后一句是R14 ,即 LR,跳转到LR
2.方式二:C语言调用(跳转)汇编语言
2. 方式二:C语言调用(跳转)汇编语言
.global FUNC_ASM
FUNC_ASM:
MOV R4, #4
MOV R5, #5
3.方式三:c内联汇编
三、ATPCS协议
ATPCS
: AT (ARM THUMB) P程序 C调用 S标准。
用来规定不同编译器编译的标准。防止出现类似采用不同压栈储存方式(一个采用增栈,一个采用减栈)而产生的错误。
ATPCS协议主要内容
1.栈的种类
1.1 使用满减栈
2.寄存器的使用
2.1 R15用作程序计数器,不能作其他用途 (PC)
2.2 R14用作链接寄存器,不能作其他用途(LP)
2.3 R13用作栈指针,不能作其他用途(SP)
2.4 当函数的参数不多于4个时使用R0-R3传递,当函数的参数多于4个时,多出的部分用栈传递(传参的本质;调用函数准备参数,给被调用函数使用)
2.5 函数的返回值使用R0传递
2.6 其它寄存器主要用于存储局部变量
调用之前:
调用fun_c: