一. 设置栈

  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. 【JSOI2014】歌剧表演

    题目 分析 我们抽象的认为一些不能互相辨认的人,被分到了一个集合,每当又有一场演出,就将每个出演的演员扔出集合,再将上次在相同集合的分在同一集合. 然后修改被分的集合和被新创建的时间,当集合只有一个数 ...

  2. layui中从子窗口传递数据到父窗口,第三个子弹层的值传给第二个弹层

    最近做一个项目的需要多个弹层,每个弹层中还需要数据传递, 经过测试,以下方法三个弹层才有效,如果只是有两个弹层,请用其它方法 大概如图,看图自己应该明白 如何在在b页面选择好的值传给a页面的问题,这个 ...

  3. 通过页面名字调用页面并添加到tab控件中

    /// <summary> /// 动态 显示 tab /// </summary> /// <param name="sFromName">类 ...

  4. SqlServer 随机生成中文姓名(转)

    ,) )) -- 姓氏 ,) )) -- 名字 INSERT @fName VALUES ('赵'),('钱'),('孙'),('李'),('周'),('吴'),('郑'),('王'),('冯'),( ...

  5. Django之nginx+wsgi后台部署(最新版)

    0-部署准备 1.要使用安全组打开腾讯云的80端口 腾讯云的80端口不能访问​www.jianshu.com 以实际项目部署为例 项目名称api_learn: Python版本:python 3.6. ...

  6. Windows和Linux下搭建J2sdk的环境

    J2SDK 作为jsp系统配置中必不可少的组件,越来越多的得到应用.下来是我整理的以往工作时搜集的资料.使用时方便查询,希望对广大的工程师有帮助. windows服务器环境下 j2sdk 的安装和环境 ...

  7. THU-CCF WC2019两开花记

    今年年初,清华大学举办的THUWC2019即将正式开启,我将继续扮演蒟蒻OIER,努力创造一个菜鸡的形象,THU-CCF WC两爆炸,笑掉各位大牙,大家多多关注. Day0 广州好热啊╰(‵□′)╯! ...

  8. Hbase meta 表异常修复

    Hbase meta表异常修复 标签(空格分隔): Hbase 一,Hbase meta元数据表 1.1 背景 线上Hbase 因为在hbase shell中清空 truncate 'table'一张 ...

  9. OOM和SOF代码

    OutOfMemoryError大数组,例如图片加载. public class MockOutOfMemoryError { public static void main(String[] arg ...

  10. 关于option标签的selected属性

    当item的dict_id和custSource一样,那么当前的item的name就被选中并显示在页面 如果直接写selected="selected",就等于直接回显这个集合中最 ...