GNU的伪操作一般都以.
开
.global symbol
@ 将symbol声明成全局符
.local symbol
@ 将symbol声明成局部符号,只能在当前.s文件使用
.equ DATA, 0xFF @类似于C语言的宏定义
MOV R1, #DATA
通过反编译可以看出
MOV
指令占用的是0地址,说明.equ
是不会生成指令的
将语句封装
@ 封装开始
.macro FUNC
MOV R1, #1
MOV R2, #2
.endm
@封装结束
FUNC
将程序复位后可以看到指针指向FUNC
.if 0 @1会编译机器码,0不编译
MOV R1, #1
MOV R2, #2
.endif
程序复位后指针直接指向了B
.rept 3 @重复编译的次数
MOV R1, #1
MOV R2, #2
.endr
可以看到编译了3次指令出来
弱化一个符号,即告诉编译器即便没有这个符号也不要报错
@ .weak symbol
@ 弱化一个符号,即告诉编译器即便没有这个符号也不要报错
.weak func
B func
在当前地址申请一个字的空间并将其初始化为VALUE
@ .word VALUE
@ 在当前地址申请一个字的空间并将其初始化为VALUE
MOV R1, #1
.word 0xFFFFFFFF
MOV R2, #2
可以看到04的地址被占用掉了,只是用来放的数据
在当前地址申请一个字节的空间并将其初始化为VALUE
@ .byte VALUE
@ 在当前地址申请一个字节的空间并将其初始化为VALUE
MOV R1, #1
.byte 0xFF
MOV R2, #2
- 因为指令都是4的整数倍,当使用
.byte
后会占用04的地址,第二条MOV指令会从05开始不满足条件无法编译成功将5-7的地址空出来,从08开始就能解决这个问题
- 如何空出地址需要用到另外一个伪操作
.align
告诉编译器后续的代码2的N次方对齐
@ .byte VALUE
@ 在当前地址申请一个字节的空间并将其初始化为VALUE
MOV R1, #1
.byte 0xFF
@ .align N
@ 告诉编译器后续的代码2的N次方对其
.align 4
MOV R2, #2
当N取4时就是16,可以看到第二条MOV指令存放在16(16进制就是10)的位置
告诉编译器后续的代码是ARM指令
@ .arm
@ 告诉编译器后续的代码是ARM指令
告诉编译器后续的代码是Thumb指令
@ .thumb
@ 告诉编译器后续的代码是Thumb指令
定义一个代码段
@ .text
@ 定义一个代码段
定义一个数据段
@ .data
@ 定义一个数据段
在当前地址申请N个字节的空间并将其初始化为VALUE
@ .space N, VALUE
@ 在当前地址申请N个字节的空间并将其初始化为VALUE
MOV R1, #1
.space 12, 0x12
MOV R2, #2
不同的编译器伪操作的语法不同
在哪种语言环境下符合哪种语言的语法规则:
在汇编中将C中的函数当做标号处理:汇编没有函数的概念,调用C语言就要去掉括号
在C中将汇编中的标号当做函数处理:C语言的函数后面是有括号的,调用汇编的话就需要补上
在C中内联的汇编当做C的语句来处理
.s文件
MOV R1, #1
MOV R2, #2
BL func_c
MOV R3, #3
.c文件
void func_c(void)
{
int a;
a ++;
a --;
}
- 通过调试我们可以发现当执行到BL后LR会保存下一条的地址
- 当执行完C语言后跳转BL的后一条指令
- 要想从C语言跳转回来的话就需要将LR值给PC,所以C语言最后一句话会自己写一条指令
.c文件
void func_c(void)
{
int a;
a ++;
FUNC_ASM();
a --;
}
.s文件
MOV R1, #1
MOV R2, #2
BL func_c
MOV R3, #3
.global FUNC_ASM @使用伪操作声明全局符
FUNC_ASM:
MOV R4, #4
MOV R5, #5
当C语言结束后跳转到相应的汇编代码位置
以上两种都是需要创建.s .c文件,通过两个文件之间的跳转来实现混合编程
C内联(内嵌)汇编
在C语言中插入汇编
void func_c(void)
{
int a;
a ++;
//C内联(内嵌)汇编
asm
(
"MOV R6, #6\n"
"MOV R7, #7\n"
);
//C语言调用(跳转)汇编语言
FUNC_ASM();
a --;
}
ATPCS协议:(ARM-THUMB Procedure Call Standard)
ATPCS协议主要内容
栈的种类
寄存器的使用
R15
用作程序计数器,只能用于储存程序的指针,不能作其他用途R14
用作链接寄存器,只能用于存储返回地址,不能作其他用途R13
用作栈指针,只能用于存储栈指针不能作其他用途R0-R3
传递,当函数的参数多于4个时,多出的部分用栈传递R0
传递int a=1,b=1,c=1,d=1,e=1,f=1,g;
int func(int a,int b,int c,int d,int e,int f)
{
return a+b+c+d+e+f;
}
int main(void)
{
g = func(a,b,c,d,e,f);
return 0;
}
1.简述ATPCS协议的主要内容是什么
1.栈的种类 1.1 使用满减栈 2.寄存器的使用 2.1 R15用作程序计数器,不能作其他用途 2.2 R14用作链接寄存器,不能作其他用途 2.3 R13用作栈指针,不能作其他用途 2.4 当函数的参数不多于4个时使用R0-R3传递,当函数的参数多于4个时,多出的部分用栈传递 2.5 函数的返回值使用R0传递 2.6 其它寄存器主要用于存储局部变量