arm汇编和c混合编程
来源:互联网 发布:left软件安卓版 编辑:程序博客网 时间:2024/05/02 04:29
一、ARM在复位启动的时候,执行的是汇编指令
ARM复位启动,首先执行汇编指令,完成一些硬件的基本初始化(stack、clock、DDR2 SDRAM、uart、cache、wdt、int、.....)。
然后在使用C来初始化:LCD、网卡、USB、加载操作系统并启动操作系统。
ARM代码的编写过程:
ARM汇编 ----> C语言
不能C和汇编反复调用
ARM汇编 --> C语言 -->ARM汇编
使用了R2 局部变量a-->R2 再使用R2,产生问题
注意入栈和出栈。
====================================================================================
二、汇编调用C
汇编程序:
.global _start
_start:
@将GPJ2_3 --->output
LDR R0, =0xe0200280 //R0=0xe0200280
LDR R1, [R0] //R1=0xe0200280地址下的内容
BIC R1,R1,#(0xf<<12) //R1 &= ~(0xf<<12)
ORR R1, R1, #(1<<12) //R1 |= (1<<12)
STR R1,[R0] //将R1 保存到 0xe0200280
loop:
@将GPJ2_3 output 0,LED4-->on
LDR R0, =0xe0200284 //R0=0xe0200284
LDR R1, [R0] //R1=0xe0200284地址下的内容
BIC R1,R1,#(1<<3) //R1 &= ~(1<<3)
STR R1,[R0] //将R1 保存到 0xe0200284
mov R0, #0x300000 //R0作为参数,传递给delay()
BL delay //BL -- 在跳转之前,保存了返回地址-->R14
@将GPJ2_3 output 1,LED4-->off
LDR R0, =0xe0200284 //R0=0xe0200284
LDR R1, [R0] //R1=0xe0200284地址下的内容
ORR R1, R1, #(1<<3) //R1 |= (1<<3)
STR R1,[R0] //将R1 保存到 0xe0200284
mov R0, #0x300000 //R0作为参数,传递给delay()
BL delay
b loop //while(1) b--branch
C程序:
void delay(int time) //time <---R0
{
int i;
for(i=0;i<time;i++);
}
===========================================================================================
三、编译器的优化级别
gcc有几个优化等级:
O0,O1,O2,O3
-O0表示没有优化,-O1为缺省值,-O3优化级别最高。
默认的优化级别-O1
gec@ubuntu:/mnt/hgfs/08arm/04ASM_C/demo1$ size led.elf
text data bss dec hex filename
148 0 0 148 94 led.elf
使用-O2优化级别
gec@ubuntu:/mnt/hgfs/08arm/04ASM_C/demo2-O2$ size led.elf
text data bss dec hex filename
84 0 0 84 54 led.elf
编译器将delay()优化成:
40000050 <delay>:
40000050: e12fff1e bx lr //mov PC,lr
如何避免delay被优化:
void delay(int time) //time <---R0
{
volatile int i; //int i;
for(i=0;i<time;i++);
}
另一个volatile例子:
int key_cnt=0; //虽然key_cnt赋值为0,但是key_cnt是存放在BSS段,BSS的内容是内存中默认值。
//所以key_cnt的值是未知的。
void key_irq(void) //按键的中断服务程序
{
key_cnt ++;
}
int a, b
int main(void)
{
key_cnt = 0;
.........
a = key_cnt;
sleep(10);
b = key_cnt;
if(a==b)
printf("no key is pressing in 10s\n");
else
printf("key is pressing in 10s\n");
}
这样的程序在编译过程中会被优化(-O2)。编译器会认为a和b是相等的。编译器没有考虑key_cnt是变化的。在这里面key_cnt应该是一个“易变的”
变量,这个变量时时刻刻都可能都会改变,所以每次使用这个变量的时候,都要重新从内存中读取该变量的值,不能优化这个变量。
所以:
volatile int key_cnt=0;
volatile用来修饰一个“易变的”变量,每次使用这个变量的时候都重新从内存中读取它的值,防止被编译器优化。
voltale的应用场合:
1)中断服务程序和应用程序之间共享的全局变量
2)两个线程之间共享的全局变量
3)定义硬件寄存器的内存
#define rGPJ2CON (*( volatile unsigned int *)0xe0200280)
#define rGPJ2DAT (*( volatile unsigned int *)0xe0200284)
===========================================================================================
五、C调用汇编
1、C语言程序
#define rGPJ2CON (*( volatile unsigned int *)0xe0200280)
#define rGPJ2DAT (*( volatile unsigned int *)0xe0200284)
//GPJ2_3 ----> LED4
extern void delay(int dat);
void _start(void) //相当于main()
{
//将GPJ2_3 --->output
rGPJ2CON &= ~(0xf<<12);
rGPJ2CON |= (1<<12);
while(1)
{
//将GPJ2_3 output 0,LED4-->on
rGPJ2DAT &= ~(1<<3);
delay(0x3000000); //
//将GPJ2_3 output 1,LED4-->off
rGPJ2DAT |= (1<<3); //1000b
delay(0x3000000);
}
}
2、汇编程序
.global delay
delay:
SUB R0,R0,#1 // R2=R2-1
TEQ R0, #0 //compare if(R2 == 0)
BNE delay //B--branch,NE -- Not Equal
bx lr // R15=R14, delay返回
@传递参数的规则--->ATPCS规则
===========================================================================================
六、C内嵌汇编
arm-linux-gcc支持C内嵌汇编。
ARM复位启动,首先执行汇编指令,完成一些硬件的基本初始化(stack、clock、DDR2 SDRAM、uart、cache、wdt、int、.....)。
然后在使用C来初始化:LCD、网卡、USB、加载操作系统并启动操作系统。
ARM代码的编写过程:
ARM汇编 ----> C语言
不能C和汇编反复调用
ARM汇编 --> C语言 -->ARM汇编
使用了R2 局部变量a-->R2 再使用R2,产生问题
注意入栈和出栈。
====================================================================================
二、汇编调用C
汇编程序:
.global _start
_start:
@将GPJ2_3 --->output
LDR R0, =0xe0200280 //R0=0xe0200280
LDR R1, [R0] //R1=0xe0200280地址下的内容
BIC R1,R1,#(0xf<<12) //R1 &= ~(0xf<<12)
ORR R1, R1, #(1<<12) //R1 |= (1<<12)
STR R1,[R0] //将R1 保存到 0xe0200280
loop:
@将GPJ2_3 output 0,LED4-->on
LDR R0, =0xe0200284 //R0=0xe0200284
LDR R1, [R0] //R1=0xe0200284地址下的内容
BIC R1,R1,#(1<<3) //R1 &= ~(1<<3)
STR R1,[R0] //将R1 保存到 0xe0200284
mov R0, #0x300000 //R0作为参数,传递给delay()
BL delay //BL -- 在跳转之前,保存了返回地址-->R14
@将GPJ2_3 output 1,LED4-->off
LDR R0, =0xe0200284 //R0=0xe0200284
LDR R1, [R0] //R1=0xe0200284地址下的内容
ORR R1, R1, #(1<<3) //R1 |= (1<<3)
STR R1,[R0] //将R1 保存到 0xe0200284
mov R0, #0x300000 //R0作为参数,传递给delay()
BL delay
b loop //while(1) b--branch
C程序:
void delay(int time) //time <---R0
{
int i;
for(i=0;i<time;i++);
}
===========================================================================================
三、编译器的优化级别
gcc有几个优化等级:
O0,O1,O2,O3
-O0表示没有优化,-O1为缺省值,-O3优化级别最高。
默认的优化级别-O1
gec@ubuntu:/mnt/hgfs/08arm/04ASM_C/demo1$ size led.elf
text data bss dec hex filename
148 0 0 148 94 led.elf
使用-O2优化级别
gec@ubuntu:/mnt/hgfs/08arm/04ASM_C/demo2-O2$ size led.elf
text data bss dec hex filename
84 0 0 84 54 led.elf
编译器将delay()优化成:
40000050 <delay>:
40000050: e12fff1e bx lr //mov PC,lr
如何避免delay被优化:
void delay(int time) //time <---R0
{
volatile int i; //int i;
for(i=0;i<time;i++);
}
另一个volatile例子:
int key_cnt=0; //虽然key_cnt赋值为0,但是key_cnt是存放在BSS段,BSS的内容是内存中默认值。
//所以key_cnt的值是未知的。
void key_irq(void) //按键的中断服务程序
{
key_cnt ++;
}
int a, b
int main(void)
{
key_cnt = 0;
.........
a = key_cnt;
sleep(10);
b = key_cnt;
if(a==b)
printf("no key is pressing in 10s\n");
else
printf("key is pressing in 10s\n");
}
这样的程序在编译过程中会被优化(-O2)。编译器会认为a和b是相等的。编译器没有考虑key_cnt是变化的。在这里面key_cnt应该是一个“易变的”
变量,这个变量时时刻刻都可能都会改变,所以每次使用这个变量的时候,都要重新从内存中读取该变量的值,不能优化这个变量。
所以:
volatile int key_cnt=0;
volatile用来修饰一个“易变的”变量,每次使用这个变量的时候都重新从内存中读取它的值,防止被编译器优化。
voltale的应用场合:
1)中断服务程序和应用程序之间共享的全局变量
2)两个线程之间共享的全局变量
3)定义硬件寄存器的内存
#define rGPJ2CON (*( volatile unsigned int *)0xe0200280)
#define rGPJ2DAT (*( volatile unsigned int *)0xe0200284)
===========================================================================================
五、C调用汇编
1、C语言程序
#define rGPJ2CON (*( volatile unsigned int *)0xe0200280)
#define rGPJ2DAT (*( volatile unsigned int *)0xe0200284)
//GPJ2_3 ----> LED4
extern void delay(int dat);
void _start(void) //相当于main()
{
//将GPJ2_3 --->output
rGPJ2CON &= ~(0xf<<12);
rGPJ2CON |= (1<<12);
while(1)
{
//将GPJ2_3 output 0,LED4-->on
rGPJ2DAT &= ~(1<<3);
delay(0x3000000); //
//将GPJ2_3 output 1,LED4-->off
rGPJ2DAT |= (1<<3); //1000b
delay(0x3000000);
}
}
2、汇编程序
.global delay
delay:
SUB R0,R0,#1 // R2=R2-1
TEQ R0, #0 //compare if(R2 == 0)
BNE delay //B--branch,NE -- Not Equal
bx lr // R15=R14, delay返回
@传递参数的规则--->ATPCS规则
===========================================================================================
六、C内嵌汇编
arm-linux-gcc支持C内嵌汇编。
0 0
- ARM中C和汇编混合编程
- C和ARM汇编混合编程
- arm汇编和c混合编程
- ARM汇编和C混合编程-笔记
- arm C、汇编混合编程
- ARM C、汇编混合编程
- ARM汇编, C语言和汇编混合编程
- ARM中C和汇编混合编程及示例
- ARM中C和汇编混合编程及示例(转)
- ARM中C和汇编混合编程及示例
- ARM中C和汇编混合编程及示例
- ARM中C和汇编混合编程及示例
- ARM中C和汇编混合编程及示例
- ARM中C和汇编混合编程及示例
- ARM中C和汇编混合编程及示例
- ARM中C和汇编混合编程中的参数传递
- ARM中C和汇编混合编程中的参数传递
- 【实验】Arm汇编和C语言混合编程实验
- 传递闭包-POJ 3660 Cow Contest
- 在latex中导入endnote中的参考文献——简明步骤
- Sublime Text3中编译运行JAVA控制台中文GBK编码无法输出的问题
- 菜鸟零基础搭建jdk环境到搭建服务器tomcat到搭建nexus私服教程
- 第十四周项目3---是否二叉排序树
- arm汇编和c混合编程
- UVa 1594 Ducci
- stl之queue(队列)的使用
- 关于移动页面开发的初级认识与布局
- 步进电机基本知识
- 使用redis缓存数据需要注意的问题以及个人的一些思考和理解
- CSS之元素定位
- Android中dialog的使用
- jffs2文件系统制作