系统学习ARM之五 --C语言和汇编混合编写
扫描二维码
随时随地手机看文章
代码行中的注释符号: ‘@’ 整行注释符号: ‘#’语句分离符号: ‘;’直接操作数前缀: ‘#’ 或 ‘$’
全局标号:标号只能由a~z,A~Z,0~9,“.”,_等(由点、字母、数字、下划线等组成,除局部标号外,不能以数字开头)字符组成,标号的后面加“:”。
段内标号的地址值在汇编时确定;
段外标号的地址值在连接时确定。
局部标号:局部标号 主要在局部范围内使用而且局部标号可以重复出现。它由两部组成开头是一个0-99直接的数字局部标号 后面加“:”???
F:指示编译器只向前搜索,代码行数增加的方向/ 代码的下一句
B:指示编译器只向后搜索,代码行数减小的方向
注意局部标号的跳转,就近原则
例子:
1:a
2:b
1:c
b 1b 跳转到 c 所处的位置
==================================================================
二、混合编程和内联汇编:【1】1.c 和2.c 编译成一个elf文件gcc -c 1.c -o 1.o
gcc -c 2.c -o 2.o
ld -Ttext 40008000 1.o 2.o -o a.elf
【2】1.s 和2.c 编译成一个elf文件gcc -c 1.s -o 1.o
gcc -c 2.c -o 2.o
ld -Ttext 40008000 1.o 2.o -o a.elf
【3】c语言中调用汇编中的函数在汇编中.global/.globl (在定义的文件中)
在 c 中extern (在调用的文件中)
================内联汇编============
【4】内联汇编:在c语言代码中嵌入汇编指令(1)Gcc 通过关键字“asm”来声明内联汇编
(2)格式: asm或__asm__开头,小括号+分号,括号内容写汇编指令。
指令+nt用双引号引上
asm(code : output operand list : input operand list : clobber list);
(3)例一:无参数,无返回值
asm
(
//汇编指令
"mrs r0,cpsr nt"
"bic r0,r0,#0x80 nt"
"msr cpsr,r0 nt"
);
(4)
例二:有参数 1,有返回值
让内联汇编做加法运算,求a+b,结果存在c中
int a =100;
int b =200;
int c =0;
asm
(
"add%0,%1,%2nt"
: "=r"(c) //输出列表 %0 --c
: "r"(a),"r"(b) //输入列表 %1 --a %2--b
: "memory" //通知列表
);
例三:有参数 2 ,有返回值
让内联汇编做加法运算,求a+b,结果存在c中,把a-b的存在d中
int a=100;
int b=200;
int c=0;
int d=0;
asm volatile
(
"add %[op1],%[op2],%[op3]nt"
:[op1]"=r”(sum)
:[op2]"r"(a),[op3]”r”(b)
:"memory"
" sub%[op4],%[op2],%[op3]nt "
:[%op4]"=r"(d)
:
:"memory"
);
【5】 gcc的代码优化级别,在 makefile 文件中的编译命令4级 O0 -- O3 数字越大,优化程度越高。O3最大优化
【6】volatile作用volatile修饰的变量,编译器不再进行优化,每次都真正访问内存地址空间。
三、ATPCS规则:(ARM、thumber程序调用规范)(1)使用r0-r3,依次接受参数void func(a,b,c,d,e)
a -- r0
b -- r1
c -- r2
d -- r3
e -- 栈
(2)使用r0 接收返回值int func1(int m, int n)
m -- r0
n -- r1
返回值给 r0
(3)局部变量,保存到r4--r11,当局部变量多余8个,用栈(4)r12 -- ip(保存sp)r13 -- sp
r14 -- lr
r15 -- pc