1.协处理器指令
协处理器:
一种协助中央处理器完成其无法执行或执行效率、效果低下的处理工作而开发和应用的处理器。这种中央处理器无法执行的工作有很多,比如设备间的信号传输、接入设备的管理等;而执行效率、效果低下的有图形处理、声频处理等。为了进行这些处理,各种辅助处理器就诞生了。
协处理器指令:操控协处理器的指令
1.协处理器数据运算指令
CDP
2.协处理器存储器访问指令
STC 将协处理器中的数据写入到存储器
LDC 将存储器中的数据读取到协处理器
3.协处理器寄存器传送指令
MRC 将协处理器中寄存器中的数据传送到ARM处理器中的寄存器
MCR 将ARM处理器中寄存器中的数据传送到协处理器中的寄存器
2.伪指令
定义:本身不是指令,编译器可以将其替换成若干条等效指令
NOP:Nop是空操作指令,用于控制时间周期。Nop是no operation 的缩写。Nop无操作数,所以称为空操作。执行Nop指令只使程序计数器PC加1,所以占用一个机器周期
LDR:较为特殊,他可以是指令也可以是伪指令,具体使用如下:
@ 做指令时:
@ LDR R1, [R2]
@ 表示将R2指向的内存空间中的数据读取到R1寄存器
@ 做伪指令时:
@ LDR R1, =0x12345678
@ 将立即数0x12345678赋给R1,使用MOV指令是无法将一个超过范围的立即数直接赋值给寄存器的
@ 而LDR伪指令可以将任意一个32位的数据放到一个寄存器,使用时注意语法
@伪指令两种格式表示两种不同的意思:
@ LDR R1, =STOP
@ 将STOP表示的地址写入R1寄存器
@ LDR R1, STOP
@ 将STOP地址中的内容写入R1寄存器
3.伪操作
定义:不会生成代码,只是在编译之前告诉编译器怎么编译,一般以 ‘.’ 开头,常用的伪操作有:
- .global
- .local
- .equ
- .macro与.endm
- .if 与.endif
- .rept 与 .endr
- .weak
- .word 与 .byte
- .align
- .arm与.thumb
- .text
- .data
- .space
具体使用如下:
@ .global symbol
@ 将symbol声明成全局符号
@ .local symbol
@ 将symbol声明成局部符号
@ .equ DATA, 0xFF
@ 使用DATA来代表0xFF,可以理解成define
@ MOV R1, #DATA
@ .macro 与 .endm:
@汇编宏,.macro和.endm区间内的指令就可以使用一句FUNC来代替,
@可以理解成定义了一个函数叫FUNC,然后以后就可以使用FUNC来表示其内容
@ .macro FUNC
@ MOV R1, #1
@ MOV R2, #2
@ .endm
@ FUNC
与C语言中的意思相同
@ .if 0
@ MOV R1, #1
@ MOV R2, #2
@ .endif
@.rept 3 重复执行3遍rept中的语句
@ 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
@ .byte 0xFF
@ .align N
@ 告诉编译器后续的代码2的N次方对其
@ .align 4
@ MOV R2, #2
@ .arm
@ 告诉编译器后续的代码是ARM指令
@ .thumb
@ 告诉编译器后续的代码是Thumb指令
@ .text
@ 定义一个代码段
@ .data
@ 定义一个数据段
@ .space N, VALUE
@ 在当前地址申请N个字节的空间并将其初始化为VALUE
@ MOV R1, #1
@ .space 12, 0x12
@ MOV R2, #2
注意: 不同的编译器伪操作的语法不同
4.C和汇编的混合编程
C和汇编的混合编程原则:在哪种语言环境下符合哪种语言的语法规则
1. 在汇编中将C中的函数当做标号处理
2. 在C中将汇编中的标号当做函数处理
3. 在C中内联的汇编当做C的语句来处理
其一共有三种方式:
- 汇编调用C语言
- C语言调用汇编
- C语言内联(内嵌)汇编
聚集使用如下:
@ 1. 方式一:汇编语言调用(跳转)C语言,直接使用BL指令即可:
@ MOV R1, #1
@ MOV R2, #2
@ BL func_c
@ MOV R3, #3
@ 2. 方式二:C语言调用(跳转)汇编语言,因为C语言与汇编不在同一个程序,
@所以在汇编中需要使用伪操作.global将其定义成全局以便C语言的调用,定义如下:
@ .global FUNC_ASM
@ FUNC_ASM:
@ MOV R4, #4
@ MOV R5, #5
@ 3. C内联(内嵌)汇编,与方式二的使用一同放在下面的C程序中
void func_c(void)
{
int a;
a ++;
//方式3,C内联(内嵌)汇编
asm//告诉程序下方代码为汇编
(
"MOV R6, #6\n"//汇编的指令要用双引号引起来,并且需要以\n结尾
"MOV R7, #7\n"
);
//方式2,C语言调用(跳转)汇编语言
FUNC_ASM();//像调用函数一样直接使用即可
a --;
}
int main()
{
func_c();
return 0;
}
4.ATPCS协议
ATPCS即ARM-THUMB procedure call standard(ARM-Thumb过程调用标准)的简称
ATPCS协议主要内容:
1.规定了栈的种类,使用满减栈FD
2.规定了寄存器的使用
- R15用作程序计数器,不能作其他用途
- R14用作链接寄存器,不能作其他用途
- R13用作栈指针,不能作其他用途
- 当函数的参数不多于4个时使用R0-R3传递,当函数的参数多于4个时,多出的部分用栈传递,函数的返回值使用R0传递
- 其它寄存器主要用于存储局部变量
3.规定了参数传递规则
根据参数个数是否固定,可以将子程序分为参数个数固定的子程序和参数个数可变的子程序.这两种子程序的参数传递规则是不同的.
(1)参数个数可变的子程序参数传递规则
对于参数个数可变的子程序,当参数不超过4个时,可以使用寄存器R0~R3来进行参数传递,当参数超过4个时,还可以使用数据栈来传递参数. 在参数传递时,将所有参数看做是存放在连续的内存单元中的字数据。然后,依次将各名字数据传送到寄存器R0,R1,R2,R3; 如果参数多于4个,将剩余的字数据传送到数据栈中,入栈的顺序与参数顺序相反,即最后一个字数据先入栈. 按照上面的规则,一个浮点数参数可以通过寄存器传递,也可以通过数据栈传递,也可能一半通过寄存器传递,另一半通过数据栈传递.
(2)参数个数固定的子程序参数传递规则
对于参数个数固定的子程序,参数传递与参数个数可变的子程序参数传递规则不同,如果系统包含浮点运算的硬件部件,浮点参数将按照下面的规则传递: 各个浮点参数按顺序处理;为每个浮点参数分配FP寄存器;分配的方法是,满足该浮点参数需要的且编号最小的一组连续的FP寄存器.第一个整数参数通过寄存器R0~R3来传递,其他参数通过数据栈传递.
4.子程序结果返回规则
1.结果为一个32位的整数时,可以通过寄存器R0返回.
2.结果为一个64位整数时,可以通过R0和R1返回,依此类推.
3.结果为一个浮点数时,可以通过浮点运算部件的寄存器f0,d0或者s0来返回. 4.结果为一个复合的浮点数时,可以通过寄存器f0-fN或者d0~dN来返回. 5.对于位数更多的结果,需要通过调用内存来传递.