本文使用的开发板是九鼎创展的X210 iNand版本。
一、预备知识
1、C语言运行时和栈
(1)C语言运行时需要
C语言运行时(runtime)需要一定的条件,这些条件由汇编来提供。C语言运行时主要是需要栈。
(2)C语言与栈的关系
C语言中的局部变量都是用栈来实现的,如果汇编部分没有给C语言预先设置合理合法的栈地址,那么C代码中定义的局部变量就会落空,整个C程序就不能运行。
2、CPU模式和各种模式下的栈
(1)在ARM的37个寄存器中,每种模式下都有自己的独立的SP寄存器(r13)。
(2)我们要设置栈,不可能而且也没有必要去设置所有的栈。我们先要找到当前的模式,然后设置该模式下的栈到合理合法的位置即可。
(3)系统在复位后默认是进入SVC模式。
(4)我们先把模式设置为SVC,再直接操作SP,即可访问SVC模式下的SP。因为复位后就已经是SVC模式了,所以直接设置SP即可。
3、设置栈指针
(1)栈必须是当前一段可用的内存,这个内存必须是被初始化过可以访问的内存,而且这个内存只会被用作栈,不会被其他程序占用。
(2)当前CPU刚复位,外部的DRAM尚未初始化,目前可用的内存只有内部的SRAM(不需初始化即可使用),因此只能在SRAM中找一段内存来作为SVC的栈。
(3)在ARM中,ATPCS要求使用满减栈
二、查阅iROM Application Note文档
由上图可知SVC栈应该设置为0xD0037D80。
三、代码实现
#define SVC_STACK 0xD0037D80 .global _start _start: ldr sp, =SVC_STACK b .
四、汇编调用C函数,实现LED闪烁效果
(1)led.c
#define GPJ0CON 0xE0200240 #define GPJ0DAT 0xE0200244 #define rGPJ0CON *((volatile unsigned int *)GPJ0CON) #define rGPJ0DAT *((volatile unsigned int *)GPJ0DAT) void delay(void); void led_blink(void) { rGPJ0CON = 0x11111111; while(1) { // led亮 rGPJ0DAT = ((0<<3) | (0<<4) | (0<<5)); // 延时 delay(); // led灭 rGPJ0DAT = ((1<<3) | (1<<4) | (1<<5)); // 延时 delay(); } } void delay(void) { volatile unsigned int i = 900000; while (i--); }
(2)Makefile
led.bin: start.o led.o arm-linux-ld -Ttext 0x0 -o led.elf $^ arm-linux-objcopy -O binary led.elf led.bin arm-linux-objdump -D led.elf > led_elf.dis gcc mkv210_image.c -o mkx210 ./mkx210 led.bin 210.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
(3)start.S
#define SVC_STACK 0xD0037D80 .global _start _start: ldr sp, =SVC_STACK bl led_blink b .
相关推荐
实验报告主要涉及了在ARM架构下,如何使用汇编语言编写程序并调用C语言函数进行运算,以及在Embest IDE Pro 2004集成开发环境中进行程序的编译、调试和下载。实验的目标是理解处理器启动过程,学会使用Embest IDE...
当需要在低级操作(如中断处理或硬件交互)和高级抽象之间建立桥梁时,就需要用到汇编调用C语言的技巧。本教程将深入探讨如何在汇编程序中调用C语言函数,以实现"20!"这个特定示例。 首先,我们需要理解汇编语言...
- `start.S`是许多嵌入式系统启动时执行的第一个汇编程序,负责初始化硬件环境,设置堆栈,调用C语言的主函数。 - 它涉及CPU状态切换(从.thumb模式到.arm模式)、栈指针设置、异常向量表配置等重要操作。 - 学习...
通过分析这些文件,我们可以看到一个完整的嵌入式系统开发流程:从汇编启动代码的编写,到C语言应用的实现,再到硬件驱动的编写和系统配置。这对于学习和实践ARM嵌入式系统,尤其是LPC2106微控制器的使用,具有很高...
此外,启动代码中通常还会包含对系统栈的初始化,设置堆栈指针等操作。系统堆栈用于函数调用和局部变量的存储,是处理器运行环境的一个重要组成部分。在C语言中,使用关键字和类型定义(如union)可以方便地操作硬件...
本主题主要探讨的是如何使用裸机汇编启动代码来初始化S3C2440,并通过C语言实现LED灯的控制和按键检测。 一、S3C2440处理器概述 S3C2440是Samsung公司推出的一款32位RISC微处理器,基于ARM920T内核,工作频率可达...
内嵌汇编语言主要应用在两种场合:一种是直接使用汇编源程序,特别是Linux启动代码中;另一种是通过gcc的内嵌汇编语法asm,将汇编代码嵌入到C语言程序中。后者是本文介绍的重点。 内嵌汇编的语法格式基于Intel的...
5. **初始化程序**:系统启动时,需要进行一些低级的硬件初始化工作,如堆栈设置、内存配置等,汇编语言是首选。 6. **异常处理**:在处理硬件故障或系统异常时,使用汇编可以更好地控制恢复流程。 学习单片机的...
总的来说,C语言实现的加壳源码为初学者提供了一个学习代码保护和底层编程的平台,通过实践和调试这些代码,可以更好地掌握C语言和计算机系统的工作原理。同时,这也是一个提升编程能力、了解程序执行流程和PE文件...
通过这个实验,学习者可以了解如何在C语言程序中调用汇编语言编写的子程序,以及如何在CCS环境中进行编译、链接和调试。此外,还能学习到如何分析和优化代码,理解底层硬件工作原理,从而提升程序的执行效率。这样的...
在Linux操作系统在ARM平台上运行时,一个关键步骤就是启动代码的执行,这部分代码通常用汇编语言编写,以确保在系统初始化阶段对硬件进行必要的设置和控制。本文将深入剖析ARM Linux启动代码的汇编语言部分,帮助...
因此,当C代码调用汇编函数或者汇编代码调用C函数时,必须确保参数的传递方式符合对方的要求。 例如,C函数调用汇编函数时,C编译器会将函数参数压入栈中。汇编函数在被调用时,需要正确地从栈中读取参数。反之,...
在计算机硬件领域,CMOS(Complementary ...在"projects_CMOS"这个压缩包文件中,很可能包含了实现这些功能的源代码,通过分析和学习这些代码,可以深入理解汇编语言如何与硬件进行交互,以及如何实现CMOS的读写操作。
5. **高级语言入口调用**:初始化完成后,启动代码会调用C语言的主入口点`__main()`,这通常是C编译器生成的链接脚本中定义的全局符号。这个函数是C程序的起点,负责进一步的系统初始化和程序执行。 6. **映射功能*...
ARM7的启动代码是嵌入式系统开发中的关键部分,它负责初始化硬件、设置堆栈、配置中断向量表,并最终跳转到C语言的主函数。以下是对启动代码的详细分析: 首先,代码中定义了一些常量,如SVC_STACK_LENGTH、FIQ_...
- **启动代码:** `_start`标签定义了启动点,通过跳转指令`jmp begin`实现。 - **系统初始化:** `cmain`函数负责初始化操作系统的各个组件,例如调用`InitShell()`函数初始化命令行界面。 - **系统退出:** 通过...
4. 高级语言入口函数调用:完成硬件初始化后,启动代码将调用main函数,这通常是C语言编写的程序入口点。在此之前,可能需要进行一系列的硬件相关设置,如配置系统时钟、初始化外设等。 5. 配置系统时钟频率:在...
总结来说,C语言在DOS环境下实现关机代码小程序是一项涉及底层硬件控制和系统调用的挑战性任务。这需要对C语言、DOS系统、BIOS中断和硬件控制有深入的理解。通过学习这样的代码,开发者不仅可以提升自己的编程技能,...
启动代码是系统启动时首先执行的部分,负责初始化硬件,设置栈指针,以及将控制权交给C语言代码。它一般用汇编语言编写,因为汇编语言对硬件操作更直接,效率更高。 启动代码的功能包括但不限于: 1. **硬件初始化...
【start.S】是U-BOOT启动时执行的第一个汇编代码文件,它在系统启动过程中扮演着至关重要的角色。本文将详细解析start.S的功能和在U-BOOT启动流程中的作用。 U-BOOT是一款开源的引导加载程序,用于初始化硬件并加载...