汇编写启动代码之设置栈和调用C语言
2016-11-17 22:05
603 查看
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文档
![](https://oscdn.geek-share.com/Uploads/Images/Content/202009/22/f308a220ec504ceb3df61b95d786f96b.png)
由上图可知SVC栈应该设置为0xD0037D80。
三、代码实现
Assembly代码
![](https://oscdn.geek-share.com/Uploads/Images/Content/201612/10/36a486c4a1c0b79d367909066b6dd524.png)
#define SVC_STACK 0xD0037D80
.global _start
_start:
ldr sp, =SVC_STACK
b .
四、汇编调用C函数,实现LED闪烁效果
(1)led.c
C代码
![](https://oscdn.geek-share.com/Uploads/Images/Content/201612/10/36a486c4a1c0b79d367909066b6dd524.png)
#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
C代码
![](https://oscdn.geek-share.com/Uploads/Images/Content/201612/10/36a486c4a1c0b79d367909066b6dd524.png)
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
Assembly代码
![](https://oscdn.geek-share.com/Uploads/Images/Content/201612/10/36a486c4a1c0b79d367909066b6dd524.png)
#define SVC_STACK 0xD0037D80
.global _start
_start:
ldr sp, =SVC_STACK
bl led_blink
b .
(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文档
![](https://oscdn.geek-share.com/Uploads/Images/Content/202009/22/f308a220ec504ceb3df61b95d786f96b.png)
由上图可知SVC栈应该设置为0xD0037D80。
三、代码实现
Assembly代码
![](https://oscdn.geek-share.com/Uploads/Images/Content/201612/10/36a486c4a1c0b79d367909066b6dd524.png)
#define SVC_STACK 0xD0037D80
.global _start
_start:
ldr sp, =SVC_STACK
b .
四、汇编调用C函数,实现LED闪烁效果
(1)led.c
C代码
![](https://oscdn.geek-share.com/Uploads/Images/Content/201612/10/36a486c4a1c0b79d367909066b6dd524.png)
#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
C代码
![](https://oscdn.geek-share.com/Uploads/Images/Content/201612/10/36a486c4a1c0b79d367909066b6dd524.png)
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
Assembly代码
![](https://oscdn.geek-share.com/Uploads/Images/Content/201612/10/36a486c4a1c0b79d367909066b6dd524.png)
#define SVC_STACK 0xD0037D80
.global _start
_start:
ldr sp, =SVC_STACK
bl led_blink
b .
相关文章推荐
- 汇编写启动代码之关看门狗和设置栈和调用C语言和ICache
- 1.5.3.汇编写启动代码之设置栈和调用C语言2
- 汇编写启动代码之设置栈和调用C语言
- 汇编写启动代码之设置栈和调用C语言
- 汇编写启动代码之设置栈和调用C语言1
- 汇编写启动代码之设置栈和调用C语言2
- 朱老师ARM裸机学习笔记(七):汇编写启动代码之调用C语言
- 五.ARM裸机学习之汇编写启动代码之关看门狗,开iCache,汇编程序和C程序互相调用
- 汇编代码调用C语言及四种类型的栈
- 汇编代码创建从软盘启动的boot loader
- 深入汇编语言来理解C语言中的传值和传址调用
- s3c2410汇编启动代码与中断跳转分析
- C语言中if 语句的汇编代码
- 内网P2P点播设置详解 WEBPLAYER9播放器调用代码
- 从U-Boot源码看C语言对汇编代码中的符号引用
- 写注册表设置开机启动的代码
- ABAP--C语言调用SAP的RFC的代码样例
- C# 直接执行、调用本机代码、汇编代码 shell Native Code(转)
- 设置服务账号失败(WMI提供程序错误,对WMI提供程序的调用返回了错误代码:0x80074814)
- ABAP--C语言调用SAP的RFC的代码样例