S3C2440 用C语言点亮LED
2021-03-22 04:24
标签:int format bin png address oba binary block vol 为什么从汇编调用C函数需要设置栈? 设置栈,本质就是将 从下面的内存映射图可以看出;从 从下面的内存映射图可以看出;从 下面还是以点亮LED为例程,通过调用C函数来点亮一盏LED灯,在S3C2440启动流程已经给出了硬件原理图,这里就不贴出来了 在看反汇编的时候,可能会遇到 实验现象也是点亮一盏LED灯,就不贴图上来了。 S3C2440 用C语言点亮LED 标签:int format bin png address oba binary block vol 原文地址:https://www.cnblogs.com/gulan-zmc/p/13894441.html一、从汇编到C函数
1、设置栈
1、因为arm汇编调用C函数参数要遵循APCS规则。即参数小于等于4个可以用R0-R3来传参;多于4个的参数,前四个参数用R0-R3传参,第五个参数开始使用栈来传参
2、C函数内部使用到的局部变量,它所存储的空间就是栈空间
3、C函数里面调用C函数时,需要用栈来保存返回地址(LR寄存器的值)。二、怎么设置堆栈
1、设置SP寄存器
SP
(堆栈寄存器)指向一块内存。在S3C2440
处理器里,要指向那块内存呢?
由于S3C2440
在上电启动的时候,外部内存还没有初始化,我们只能将SP
指向它内部4Kb的SRAM
。
又因为S3C2440
支持nand flash
启动和nor flash
启动两种方式启动,而且两种方式的启动,内部SRAM
的映射地址不一样,所以里两种方式设置地址不一样2、nand flash启动
nand flash
启动的时候,内部SRAM
被映射到了0x0000 0000
地址;因为编译器编译的使用的是递减栈变编译的,所以通常我们将SP
指向内部SRAM
的最高地址处0x1000 (4096)
2、nor flash启动
nand flash
启动的时候,内部SRAM
被映射到了0x4000 0000
地址,所以通常我们将SP
指向内部SRAM
的最高地址处0x40001000 (0x40000000+0x1000)
三、程序
1、启动程序(汇编程序 Startup.S)
.text /*定义代码段*/
.global _start /*标号_start是GNU连接器用来指定第一个要执行所必须的(只能出现在一个模块),.global将_start声明为全局可见*/
_start:
/* 设置栈 */
/* nand flash 启动的设置方法 */
ldr sp, =0x1000 /* 将栈设置在4k处 */
/* nor flash 启动的设置方法 */
//ldr sp, =0x40000000+0x1000 /* 将栈设置在0x40000000 + 4k处 (本程序使用nand flash启动,所以这里注释掉)*/
/*调用C函数*/
b main
loop:
b loop
2、C函数(main.c)
/* 定义GPFCON 寄存器 */
#define GPFCON *((volatile unsigned long*)0x56000050)
/* 定义GPFDAT 寄存器 */
#define GPFDAT *((volatile unsigned long*)0x56000054)
int main(){
/* 清零 */
GPFCON &= ~(0x03
3、Makefile
all:
arm-linux-gcc -c Startup.S -o Startup.o
arm-linux-gcc -c main.c -o main.o
arm-linux-ld -Ttext 0 Startup.o main.o -o Led.elf
arm-linux-objcopy -O binary -S Led.elf Led.bin
arm-linux-objdump -D Led.elf > led.dis
clean:
rm *.o *.elf *.bin *.dis
4、反汇编程序
sl
,ip
,fp
,a1-a4
,v1-v6
这些寄存器,这些寄存器只是在APCS
规则下的别名。他们对应的关系: sl
->r10
, fp
->r11
, ip
->r12
, a1-a4
->r0-r3
, v1-v6
->r4-r9
。Led.elf: file format elf32-littlearm
Disassembly of section .text:
00000000 <_start>:
0: e3a0da01 mov sp, #4096 ; 0x1000 /* 设置sp */
4: ea000000 b c
四、实验现象