c语言环境初始化&c语言和汇编混合编程
bootloader通常会分为两个阶段:第一阶段采用汇编语言来编写,主要是一些核心的初始化工作(内存,时钟的初始化),第二阶段使用C语言来编写,主要是它会完成一些板载硬件的初始化(串口,网口)然后其启动我们的操作系统。所以我们需要先搭建好C语言环境。
-----------------------------------------------------
栈的初始化(只有一行,但信息量巨大,而且非常重要,对以后嵌入式的学习起了至关重要的作用):
栈:一种后进先出性质的数据组织方式。
满栈:当堆栈指针sp总是指向最后压入堆栈的数据
空栈:当堆栈指针sp总是指向下一个将要放入数据的空位置。
ARM采用满栈。
--------------------------------------------------
升栈和降栈:
升栈:sp指针从地地址到高地址
降栈:sp指针从高地址到地地址
ARM采用降栈。
-------------------------------------------
栈帧:就是一个函数所使用的那部分栈,所以函数的栈帧串起来就组成了一个完整的栈,栈帧的两个边界分别由fp(r11)和sp(r13)来限定。main与main函数中所有调用的函数,共同形成一个栈,main也是一个栈帧。
栈帧与栈帧之间的界定:上边界为fp指针,下边界为sp指针。
而main函数的边界保存在所调用的函数中,通过指针映射,将整个main函数包含进来。
---------------------------------------------------------
三个实例阐述栈的作用:
1.保存局部变量(局部变量保存在栈中):
#include<stdio.h>
int main()
{
int a;
a++;
return a;
}
arm-linux-gcc -g -o stack1 stack1.c
arm-linux-objdump -D -S stack1 >dump
vim dump
:/main
(str fp,[sp,#-4]!),将fp放到sp减去4个字节的位置,"!"表示sp减去4个字节后的值还要赋值给sp.
2.传递参数(当参数个数大于4是,使用栈来传递参数):
#include<stdio.h>
void func1(int a,int b,int c,int d,int e,int f)
{
int k;
k=e+f;
}
int main()
{
func1(1,2,3,4,5,6);
return 0;
}
arm-linux-gcc -g -o stack1 stack2.c
arm-linux-objdump -D -S stack2 >dump2
vim dump2
:/main
push {1,2}先压入的是2。
3.保存寄存器的值:
#include<stdio.h>
void func2(int a,int b)
{
int k;
k=a+b;
}
void func1(int a,int b){
int c;
func2(3,4);
c=a+b;
}
int main()
{
func1(1,2);
return 0;
}
arm-linux-gcc -g -o stack1 stack2.c
arm-linux-objdump -D -S stack2 >dump3
vim dump3
:/main
-------------------------------------------------------
栈初始化编程:
bl init_stack
bl light_led
init_stack:
ldr sp,=0x54000000 //210:0x24000000 //2440:0x34000000
mov cp,lr
-------------------------------------------------------
初始化bss段(就是对bss段进行整体性清零,防止为初始化的全局变量产生错误):
bss段的作用:
初始化的全局变量存放在数据段,局部变量存放在栈段,未初始化的全局变量存放在bss段,malloc内存分配在堆中。面试易考。
如:#include<stdio.h>
int year;
int main()
{
year=2014;
return year;
}
arm-linux-gcc bss.c -o bss
arm-linux-readelf -a bss >dump
vim dump
查看year是否存放在bss段的起止位置之间。
-------------------------------------------------
首先我们要找到bss段的起始位置,然后在bss段中全部填0.
起始位置可以在链接器脚本中找到。
bl clean_bss
clean_bss:
ldr r0,=bss_start
ldr r1,=bss_end
cmp r0,r1 //比较bss段的起始位置是否相等
moveq pc,lr //相等则返回pc
clean_loop:
mov r2,#0 //每次清零4个字节
str r2,[r0],#4 //将r2的值放到r0中
cmp r0,r1
bne clean_loop
mov pc,lr
--------------------------------------------------
一跃进入c大门:采用什么方式跃,检验是否跃成功。
相对跳转:b,bl:跳转到内存当中的main
绝对跳转:pc=....:跳转到SRAM中的main
vi main.c
int gboot_main()
{
return 0;
}
reset:
ldr pc,=gboot_main
vim makefile
加上++main.o
-------------------------------------------
接下来是验证C程序已经被执行到了。这次我们使用c语言来点亮led.打开之前编写的start.S文件,然后将里面用汇编语言写的bl light_led的代码都注释掉,将它的实现部分放到main.c中。
实际代码:
#define GPKCON (volatile unsigned long*) 0x7f008800
#define GPKDAT (volatile unsigned long*) 0x7f008800
int gboot_main()
{
*(GPKCON) = 0x11110000
*(GPKDAT) = 0xa0
return 0;
}
210的开发板需要起点处向后移16字节的头。
-----------------------------------------------
c与汇编混合编程:
C语言:可读性强,移植性好,调试方便
汇编语言:执行效率高,编写繁琐,能直接控制处理器(关键)。
1.汇编调用c函数:
ldr pc,gboot_main:调用C函数。
2.C语言中调用汇编函数:
直接将汇编函数名放到c语言的main中:light_led;还有一点,就是要将其申明为全局:
.global light_led
light_led:
3.c内嵌汇编:
格式:
__asm__(
汇编语句部分
:输出部分
:输入部分
:破坏描述部分
);
void write_p15_c1(unsigned long value){
__asm__(
"mcr p15,0,,%0,c1,c0,0\n"//从%0中读取参数放到c1中
:
:"r"(value)将value赋值给r,然后将r中的值放到c1中。
);
}
-----------------------------------------------------
实例2:
unsigned long read_p15_c1(void){
unsigned long value;
__asm__(
"mrc p15,0,%0,c1,c0,0\n" //从c1中读出值写到%0中。
:"=r"(value)@"="表示只写操作数,用于输出部分
:
:"memory");//表示内存的值被修改了,value存在于内存。
return value;
}
------------------------------------------------
优化:
unsigned long old;
unsigned long temp;
__asm__volatile(
"mrs %0,cpsr \n"
"orr %1,%0,#128 \n"
"msr cpsr_c,%1\n"
:"=r"(0ld),"=r"(temp)
:
:"memory");
使用volatile来告诉编译器,不要对接下来的这部分代码进行优化。
-----------------------------------------------------
使用内嵌汇编点亮led:
start.S
main.c
#define GPKCON 0x7f008800
#define GPKDAT 0x7f008808
int gboot_main(){
__asm__(
"ldr r1,=0x11110000\n"
"str r1,[%0]\n"
"ldr r1,=0xa0\n"
"str r1,[%1]\n"
:
:"r"(GPKCON),"r"(GPKDAT)
:"r1"
);
return 0;
}
c语言环境初始化&c语言和汇编混合编程的更多相关文章
- 【转】VxWorks中高精度实时时钟的实现及C语言汇编混合编程
最近一个项目中需要在VxWorks下使用一个高精度实时时钟,要求精度为1ms,溢 出时间大于5小时.VxWorks提供系统时钟,该时钟在操作系统启动后开始计数,精度为1个tick,可以通过tickGe ...
- ARM中C和汇编混合编程及示例(转)
在嵌入式系统开发中,目前使用的主要编程语言是C和汇编,C++已经有相应的编译器,但是现在使用还是比较少的.在稍大规模的嵌入式软件中,例如含有OS,大部分的代码都是用C编写的,主要是因为C语言的结构比较 ...
- C51与汇编混合编程详解
C51和汇编混合编程(1)-C语言中嵌入汇编 1.在 C文件中要嵌入汇编代码片以如下方式加入汇编代码: #pragma ASM ;Assembler Code Here #pragma ENDASM ...
- Part10-C语言环境初始化-C与汇编混合编程lesson4
1.为什么要混合编程 汇编语言:执行效率高:编写繁琐: 执行效率高:能够更直接地控制处理器. c语言:可读性强,移植性好,调试方便. 1.汇编调用c函数 2.c调用汇编函数 汇编语言定义的函数(标号) ...
- [Swift通天遁地]五、高级扩展-(13)图片资源本地化设置:根据不同的语言环境显示不同语言版本图片
★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★➤微信公众号:山青咏芝(shanqingyongzhi)➤博客园地址:山青咏芝(https://www.cnblogs. ...
- Part10-C语言环境初始化-一跃进入C大门lesson3
1.跳转到c代码 因为内存中的代码来自于垫脚石SRAM,他们是相同的. 采用绝对跳转方式来完成. 因为我们是从汇编代码跳转到c语言的程序,所以我们要提前准备一个main.c文件. 修改makefile ...
- Part10-C语言环境初始化-栈初始化lesson1
1.概念解析 ARM系统使用的是满栈! ARM采用降栈!!! 栈帧 每一个进程会有一个栈,该进程中的每一个函数会分割栈的一部分,那么每一个函数使用的那部分栈就叫做栈帧.那么所有栈帧组成了整个栈. 子函 ...
- Part10-C语言环境初始化-Bss段初始化lesson2
1.BSS段的作用 初始化的全局变量存放在数据段: 局部变量存放在栈中: malloc的存放在堆: 未初始化的全局变量存放在BSS段: 找到bss段的起始与结束地址,往里面添加0,便初始化好了. 打开 ...
- arm:c语言和汇编混合编程
仅作演示. 1.C和汇编可相互调用,汇编子函数格式参考 汇编:普通的函数调用的汇编代码解析 http://www.cnblogs.com/mylinux/p/4139972.html 本文演示了 : ...
随机推荐
- linux 下CentOS 下 npm命令安装gitbook失败的问题
运行环境 linux 服务器:CentOS 7.0 系统:安装了nodejs :使用 npm 安装 gitbook 出现错误提示: npm install -g gitbook-cli symbol ...
- Flume介绍
Flume介绍 http://flume.apache.org/FlumeUserGuide.html 一.Flume架构图 含义 Source 规定收集数据的来源 Channel 相当于一个管道,连 ...
- Python3 的列表
1:列表: Python的列表比C语言的数组强大的多,数组只能存放相同类型的数据,而列表则像一个大集装箱可以存放整形.浮点型.字符串.对象等 2:创建列表的方法 #创建一个普通列表 list1=[1, ...
- asp.net -mvc框架复习(10)-基于三层架构与MVC搭建项目框架
一.三种模式比较 1.MVC框架(适合大型项目) (1).V视图 (网页部分) (2).M模型 (业务逻辑+数据访问+实体类) (3).C控制器 (介于M和V之间,起到引导作用) 2.三层架构 (1) ...
- ios开发-第二天
1.#import可保证无论头文件出现多少次,只包含一次,而#include相反. 2.如果用户不提供文件路径的话,那么argc的值为1,可以用来做是否错误的判断. 3.面向对象和面向过程的区别 面向 ...
- 微信小程序+和风天气完成天气预报
<冷暖自知>天气小程序 学无止境,以玩儿玩儿的心态去学习! 花半天时间完成简单的小程序应用.适合小程序初学者. 申请小程序帐号: https://mp.weixin.qq.com/wxop ...
- tone() 和 IRremote 冲突的解决办法
tone()函数冲突 http://www.geek-workshop.com/thread-4037-1-1.html 可以自制函数newtone() void newtone(byte toneP ...
- HX711初步处理记录
参考文档为极客工坊大神记录 http://www.geek-workshop.com/forum.php?mod=viewthread&tid=2315&highlight=hx711 ...
- greedy算法(python版)
greedy算法的核心思想是首先计算覆盖面大的部分,然后依次寻找其他覆盖面最大的部分.该算法的使用场景就像他的名字一样,当符合贪婪属性的时候就可以考虑. states_needed = set(['北 ...
- Web Magic 简介
WebMagic in Action Little book of WebMagic. WebMagic是我业余开发的一款简单灵活的爬虫框架.基于它你可以很容易的编写一个爬虫. 这本小书以WebMag ...