一. 设置栈

  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的更多相关文章

  1. u-boot源码汇编段简要分析

    Hi,大家好!我是CrazyCatJack,你们可以叫我CCJ或者疯猫.今天我给大家带来的是u-boot的源代码汇编段分析,以后还会给大家讲解后续的C代码,请持续关注哦^_^ 先简单说一下u-boot ...

  2. GCC 预处理、编译、汇编、链接..

    1简介 GCC 的意思也只是 GNU C Compiler 而已.经过了这么多年的发展,GCC 已经不仅仅能支持 C 语言:它现在还支持 Ada 语言.C++ 语言.Java 语言.Objective ...

  3. GDB调试汇编堆栈过程分析

    GDB调试汇编堆栈过程分析 分析过程 这是我的C源文件:click here 使用gcc - g example.c -o example -m32指令在64位的机器上产生32位汇编,然后使用gdb ...

  4. Beennan的内嵌汇编指导(译)Brennan's Guide to Inline Assembly

    注:写在前面,这是一篇翻译文章,本人的英文水平很有限,但内嵌汇编是学习操作系统不可少的知识,本人也常去查看这方面的内容,本文是在做mit的jos实验中的一篇关于内嵌汇编的介绍.关于常用的内嵌汇编(AT ...

  5. 从linux0.11中起动部分代码看汇编调用c语言函数

    上一篇分析了c语言的函数调用栈情况,知道了c语言的函数调用机制后,我们来看一下,linux0.11中起动部分的代码是如何从汇编跳入c语言函数的.在LINUX 0.11中的head.s文件中会看到如下一 ...

  6. C内嵌汇编-格式

    C内嵌汇编-格式: __asm__(汇编语句部分:输出部分:输入部分破坏描述部分);C内嵌汇编以关键字"__asm__"或"asm"开始, 下辖四个部分, 各部 ...

  7. 20145212——GDB调试汇编堆栈过程分析

    GDB调试汇编堆栈过程分析 测试代码 #include <stdio.h> short val = 1; int vv = 2; int g(int xxx) { return xxx + ...

  8. C程序汇编运行模式简析

    SJTUBEAR 原创作品转载请注明出处 /<Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-1000029000 1. 汇编 ...

  9. 生成ARM汇编

    使用ndk即可生成arm汇编 1.首先写好hello.c 2.编写makefile #ndk根目录 NDK_ROOT=E:\Android\android-ndk-r10b #编译器根目录 TOOLC ...

  10. gdb调试汇编堆栈过程的学习

    gdb调试汇编堆栈过程的学习 以下为C源文件 使用gcc - g code.c -o code -m32指令在64位的机器上产生32位汇编,然后使用gdb example指令进入gdb调试器: 进入之 ...

随机推荐

  1. 【leetcode】Find K Pairs with Smallest Sums

    You are given two integer arrays nums1 and nums2 sorted in ascending order and an integer k. Define ...

  2. 对云信SDK的研究

    1.我首先看了网易的云的各个产品 2.进行了分析发现产品还是很多的 3.主要对web的SDK进行了查看 4.主要有即时通信和聊天室 5.在githup上有网易托管的代码,我用git拉下来,并进行了查看 ...

  3. package.json文件

    http://javascript.ruanyifeng.com/nodejs/packagejson.html#toc7(copy) 通常我们使用npm init命令来创建一个npm程序时,会自动生 ...

  4. SpringBoot项目中,表单的验证操作

    在创建Springboot项目中,我们使用了表单验证操作,这一操作将极大地简化我们编程的开发 1.接收数据,以及验证 @PostMapping("/save") public Mo ...

  5. asp.net 如何实现大文件断点上传功能?

    之前仿造uploadify写了一个HTML5版的文件上传插件,没看过的朋友可以点此先看一下~得到了不少朋友的好评,我自己也用在了项目中,不论是用户头像上传,还是各种媒体文件的上传,以及各种个性的业务需 ...

  6. 随机数:rand()

    首先我们要对rand&srand有个总体的看法:srand初始化随机种子,rand产生随机数,下面将详细说明.   rand(产生随机数)   表头文件: #include<stdlib ...

  7. Spring Boot教程(十二)整合elk(1)

    elk 简介 Elasticsearch是个开源分布式搜索引擎,它的特点有:分布式,零配置,自动发现,索引自动分片,索引副本机制,restful风格接口,多数据源,自动搜索负载等. Logstash是 ...

  8. HDU1847--Good Luck in CET-4 Everybody!(SG函数)

    Problem Description 大学英语四级考试就要来临了,你是不是在紧张的复习?也许紧张得连短学期的ACM都没工夫练习了,反正我知道的Kiki和Cici都是如此.当然,作为在考场浸润了十几载 ...

  9. 添加tomcat为启动服务/删除tomcat服务

    在很多生产把环境下,tomcat的启动要随着windows的启动一起启动,这个时候就需要将tomcat添加成服务.步骤如下: 1:环境配置 配置jdk环境变量: JAVA_HOME:jdk路径 配置p ...

  10. SpringBoot,用200行代码完成一个一二级分布式缓存

    缓存系统的用来代替直接访问数据库,用来提升系统性能,减小数据库复杂.早期缓存跟系统在一个虚拟机里,这样内存访问,速度最快. 后来应用系统水平扩展,缓存作为一个独立系统存在,如redis,但是每次从缓存 ...