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 本文演示了 : ...
随机推荐
- PHP安全之webshell和后门检测
基于PHP的应用面临着各种各样的攻击: XSS:对PHP的Web应用而言,跨站脚本是一个易受攻击的点.攻击者可以利用它盗取用户信息.你可以配置Apache,或是写更安全的PHP代码(验证所有用户输入) ...
- XML中文乱码问题
XML中文乱码问题
- C#面试常见题目
1.CTS.CLS.CLR分别作何解释 CTS:Common Type System 通用系统类型.Int32.Int16→int.String→string.Boolean→bool CLS:Com ...
- 整理关于web项目如何防止CSRF和XSS攻击的方法
1 了解CSRF的定义 CSRF(Cross-site request forgery)跨站请求伪造,也被称为"One Click Attack"或者Session Riding, ...
- java访问修饰符 public protect default private
适用范围<访问权限范围越小,安全性越高> 访问权限 类 包 子类 其他包 public ok ok ok ok (对所有可用的 ...
- 再叙Java反射
Java中的反射 本文为反射的基础知识部分. 能够分析类能力的程序被称为反射(reflective). 反射机制允许程序在运行时取得任何一个已知名称的class的内部信息,容许程序在运行时加载.探知. ...
- Java数据持久层框架 MyBatis之API学习六(Mapper XML 文件详解)
对于MyBatis的学习而言,最好去MyBatis的官方文档:http://www.mybatis.org/mybatis-3/zh/index.html 对于语言的学习而言,马上上手去编程,多多练习 ...
- 从arduino到32单片机的转型
#include "stm32f10x.h" #include "led.h" #include "delay.h" int main(vo ...
- pythhon_如何读写json数据
案例: 在web应用中常常用到json数据进行传输数据,本质上是字典类型数据转换成字符串,通过字符串进行网页传输,然后把接收到的字符串转换成字典类似数据 需求:实现字典转换成字符串,字符串转换成字典数 ...
- CSS深入理解学习笔记之float
1.float的历史 float设计的初衷仅仅是为了文字环绕效果. 示例代码: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transit ...