从汇编到C
一. 设置栈
1.1. C语言运行时需要和栈的意义
1.1.1. “C语言运行时(runtime)”需要一定的条件,这些条件由汇编来提供。C语言运行时主要是需要栈
1.1.2. C语言与栈的关系
a. C语言中的局部变量都是用栈来实现的。如果我们汇编部分没有给C部分预先设置合理合法的栈地址,那么C代码中定义的局部变量就会落空,整个程序就死掉了。
b. 我们平时在编写单片机程序(譬如51单片机)或者编写应用程序时并没有去设置栈,但是C程序还是可以运行的。原因是:在单片机中由硬件初始化时提供了一个默认可用的栈,在应用程序中我们编写的C程序其实并不是全部,编译器(gcc)在链接的时候会帮我们自动添加一个头,这个头就是一段引导我们的C程序能够执行的一段汇编实现的代码,这个代码中就帮我们的C程序设置了栈及其他的运行时需要。
1.1.3. CPU模式和各种模式下的栈
1.1.3. 在ARM中37个寄存器中,每种模式下都有自己的独立的SP寄存器(r13),为什么这么设计?
a. 如果各种模式都使用同一个SP,那么就意味着整个程序(操作系统内核程序、用户自己编写的应用程序)都是用一个栈的。你的应用程序如果一旦出错(譬如栈溢出),就会连累操作系统的栈也损坏,整个操作系统的程序就会崩溃。这样的操作系统设计是非常脆弱的,不合理的。
b. 解决方案就是各种模式下用不同的栈。我的操作系统内核使用自己的栈,每个应用程序也使用自己独立的栈,这样各是各的,一个损坏不会连累其他人。
PS: S5PV210系统在复位后默认是进入SVC模式的,裸机程序运行在此模式
1.2. 汇编程序设置栈
a. 栈必须是当前一段可用的内存(可用的意思是这个地方必须有被初始化过可以访问的内存,而且这个内存只会被我们用作栈,不会被其他程序征用)
b. 当前CPU刚复位(刚启动),外部的DRRAM尚未初始化,目前可用的内存只有内部的SRAM(因为它不需初始化即可使用)。因此我们只能在SRAM中找一段内存来作为SVC的栈。
c. 栈有四种:满减栈 满增栈 空减栈 空增栈,详情查看《ARM汇编3》
d. 查阅《iROM_application_note》中的memory map,可知SVC栈应该设置为0xd0037D80
#define SVC_STACK 0xd0037d80
ldr sp, = SVC_STACK @set stack
二. 使用c编程
2.1. 汇编启动代码
a. 设置栈地址
b. 调用C函数led_blink
/*
* file name :set_stack.S
* author: MUSK
* description:set stack,
*/
#define WATCHCON 0xE2700000
#define SVC_STACK 0xd0037d80
.global _start
_start:
ldr r1, =WATCHCON @Watchdog Timer Control Register address
ldr r0, [r1] @config corresponding register
and r0, r0,#(~(0x01<<)) @config corresponding register
str r0, [r1] ldr sp, = SVC_STACK @set stack bl led_blink b . @while()
2.2. 编写C文件
a. 该文件主要实现LED的闪烁
#define GPJ0CON ((volatile unsigned int *)0xE0200240)
#define GPJ0DAT ((volatile unsigned int *)0xE0200244)
void delay(void);
void led_blink(void)
{
//led初始化, *GPJ0CON &=0xff000fff;
*GPJ0CON |=0x00111000;
while()
{
*GPJ0DAT &=~((0x01<<)|(0x01<<)|(0x01<<));
delay();
*GPJ0DAT |=((0x01<<)|(0x01<<)|(0x01<<));
delay();
}
} void delay(void)
{
volatile unsigned int times =;
while(times--); }
三. 编译测试
3.1. 编译前Makefile文件
set_stack.bin: set_stack.o led.o
arm-linux-ld -Ttext 0x0 -o set_stack.elf $^
arm-linux-objcopy -O binary set_stack.elf set_stack.bin
arm-linux-objdump -D set_stack.elf > set_stack_elf.dis
gcc mkv210_image.c -o mkx210
./mkx210 set_stack.bin .bin %.o : %.S
arm-linux-gcc -o $@ $< -c %.o : %.c
arm-linux-gcc -o $@ $< -c clean:
rm *.o *.elf *.bin *.dis mkx210 -f
3.2. 编译结果
a. 编译报错:led.o:(.ARM.exidx+0x0): undefined reference to `__aeabi_unwind_cpp_pr1'
b. google问题后解决方法是编译命令后加上-nostdlib
root@ubuntu:/mnt/hgfs/windows_share/baseC/lesson1.5.3-set-stack2# ls
led.c Makefile mkv210_image.c set_stack.S write2sd 说明.txt
root@ubuntu:/mnt/hgfs/windows_share/baseC/lesson1.5.3-set-stack2#
root@ubuntu:/mnt/hgfs/windows_share/baseC/lesson1.5.3-set-stack2#
root@ubuntu:/mnt/hgfs/windows_share/baseC/lesson1.5.3-set-stack2# make
arm-linux-gcc -o set_stack.o set_stack.S -c #-nostdlib
arm-linux-gcc -o led.o led.c -c #-nostdlib
arm-linux-ld -Ttext 0x0 -o set_stack.elf set_stack.o led.o
led.o:(.ARM.exidx+0x0): undefined reference to `__aeabi_unwind_cpp_pr1'
led.o:(.ARM.exidx+0x8): undefined reference to `__aeabi_unwind_cpp_pr0'
make: *** [set_stack.bin] Error
root@ubuntu:/mnt/hgfs/windows_share/baseC/lesson1.5.3-set-stack2#
3.3. 修改后的Makefile文件
a. 增加-nostdlib
set_stack.bin: set_stack.o led.o
arm-linux-ld -Ttext 0x0 -o set_stack.elf $^
arm-linux-objcopy -O binary set_stack.elf set_stack.bin
arm-linux-objdump -D set_stack.elf > set_stack_elf.dis
gcc mkv210_image.c -o mkx210
./mkx210 set_stack.bin .bin %.o : %.S
arm-linux-gcc -o $@ $< -c -nostdlib %.o : %.c
arm-linux-gcc -o $@ $< -c -nostdlib clean:
rm *.o *.elf *.bin *.dis mkx210 -f
b. 重新make
root@ubuntu:/mnt/hgfs/windows_share/baseC/lesson1.5.3-set-stack2# make clean
rm *.o *.elf *.bin *.dis mkx210 -f
root@ubuntu:/mnt/hgfs/windows_share/baseC/lesson1.5.3-set-stack2# make
arm-linux-gcc -o set_stack.o set_stack.S -c -nostdlib
arm-linux-gcc -o led.o led.c -c -nostdlib
arm-linux-ld -Ttext 0x0 -o set_stack.elf set_stack.o led.o
arm-linux-objcopy -O binary set_stack.elf set_stack.bin
arm-linux-objdump -D set_stack.elf > set_stack_elf.dis
gcc mkv210_image.c -o mkx210
./mkx210 set_stack.bin .bin
root@ubuntu:/mnt/hgfs/windows_share/baseC/lesson1.5.3-set-stack2#
参考《朱老师.1.2ARM裸机课件》
从汇编到C的更多相关文章
- u-boot源码汇编段简要分析
Hi,大家好!我是CrazyCatJack,你们可以叫我CCJ或者疯猫.今天我给大家带来的是u-boot的源代码汇编段分析,以后还会给大家讲解后续的C代码,请持续关注哦^_^ 先简单说一下u-boot ...
- GCC 预处理、编译、汇编、链接..
1简介 GCC 的意思也只是 GNU C Compiler 而已.经过了这么多年的发展,GCC 已经不仅仅能支持 C 语言:它现在还支持 Ada 语言.C++ 语言.Java 语言.Objective ...
- GDB调试汇编堆栈过程分析
GDB调试汇编堆栈过程分析 分析过程 这是我的C源文件:click here 使用gcc - g example.c -o example -m32指令在64位的机器上产生32位汇编,然后使用gdb ...
- Beennan的内嵌汇编指导(译)Brennan's Guide to Inline Assembly
注:写在前面,这是一篇翻译文章,本人的英文水平很有限,但内嵌汇编是学习操作系统不可少的知识,本人也常去查看这方面的内容,本文是在做mit的jos实验中的一篇关于内嵌汇编的介绍.关于常用的内嵌汇编(AT ...
- 从linux0.11中起动部分代码看汇编调用c语言函数
上一篇分析了c语言的函数调用栈情况,知道了c语言的函数调用机制后,我们来看一下,linux0.11中起动部分的代码是如何从汇编跳入c语言函数的.在LINUX 0.11中的head.s文件中会看到如下一 ...
- C内嵌汇编-格式
C内嵌汇编-格式: __asm__(汇编语句部分:输出部分:输入部分破坏描述部分);C内嵌汇编以关键字"__asm__"或"asm"开始, 下辖四个部分, 各部 ...
- 20145212——GDB调试汇编堆栈过程分析
GDB调试汇编堆栈过程分析 测试代码 #include <stdio.h> short val = 1; int vv = 2; int g(int xxx) { return xxx + ...
- C程序汇编运行模式简析
SJTUBEAR 原创作品转载请注明出处 /<Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-1000029000 1. 汇编 ...
- 生成ARM汇编
使用ndk即可生成arm汇编 1.首先写好hello.c 2.编写makefile #ndk根目录 NDK_ROOT=E:\Android\android-ndk-r10b #编译器根目录 TOOLC ...
- gdb调试汇编堆栈过程的学习
gdb调试汇编堆栈过程的学习 以下为C源文件 使用gcc - g code.c -o code -m32指令在64位的机器上产生32位汇编,然后使用gdb example指令进入gdb调试器: 进入之 ...
随机推荐
- 【NOIP2016提高组day1】换教室
题目 对于刚上大学的牛牛来说,他面临的第一个问题是如何根据实际情况申请合适的 课程. 在可以选择的课程中,有 2n 节课程安排在 n 个时间段上. 在第 i ( 1 ≤ i ≤ n )个 时间段上,两 ...
- DevOps之持续集成Jenkins+Gitlab
一.什么是DevOps DevOps(英文Development(开发)和Operations(技术运营)的组合)是一组过程.方法与系统的统称,DevOps是一组最佳实践强调(开发.运维.测试)在应用 ...
- 关于tomcat的server.xml里host节点配置的一些说明
其实对这个一直搞不清楚,后来公司的网站遭遇与IIS进行整合,然后上面有几个应用需要进行配置,所以对tomcat的server.xml进行了一些深入的了解 Host的节点主要是起一个对域名解析到那个虚拟 ...
- HDU 2243 ( Trie图 矩阵构造幂和 )
题意 : 长度不超过L,只由小写字母组成的,至少包含一个词根的单词,一共可能有多少个呢?这里就不考虑单词是否有实际意义. 比如一共有2个词根 aa 和 ab ,则可能存在104个长度不超过3的单词, ...
- Yahoo 军规(部分)
1.尽量减少HTTP的请求次数 网站中的图片,文字,样式表等内容都是从服务器端请求过来的.如果项目中有多个脚本,多个样式表需要加载,尽量将他们合并在一个CSS.JS文件中. 2.将CSS放在页面最上 ...
- install_github无法安装 Rwebdriver包的解决方法
1.通过install_githtb安装Rwebdriver包的错误如下: 提示不能打开URL,但是将URL地址输入浏览器地址栏,则可以下载包到本地 2.在网上搜索,发现可以通过本地文件来安装(ins ...
- ide破解
https://blog.csdn.net/yangying496875002/article/details/73603303
- C++引用与传参
# include <iostream> using namespace std; void Swap(int *pa, int *pb) { int t = *pa; *pa = *pb ...
- Nginx常见配置说明
#定义Nginx运行的用户和用户组 user www www; #nginx进程数,建议设置为等于CPU总核心数. worker_processes 8; #全局错误日志定义类型,[ debug | ...
- preventDefault 和 stopPropagation
概述 以前开发项目的时候,总是分不清楚 preventDefault 和 stopPropagation,每次都是用 @click.stop试一下,不能就用@click.prevent试一下.今天来好 ...