一、从汇编到C函数
1、设置栈
为什么从汇编调用C函数需要设置栈?
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)
三、程序
下面还是以点亮LED为例程,通过调用C函数来点亮一盏LED灯,在S3C2440启动流程已经给出了硬件原理图,这里就不贴出来了
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 << 8);
/* 设置为output */
GPFCON |= (0x01<<8);
/* 将 GPF4 输出低电平 */
GPFDAT &= ~(1<<4);
while(1);
return 0;
}
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 00000008 8: eafffffe b 8 0000000c c: e1a0c00d mov ip, sp /* 将sp的值保存起来,这里的ip寄存器其实是R12 */ 10: e92dd800 stmdb sp!, {fp, ip, lr, pc} /* 先将pc,lr,ip, fp 寄存器的值压入栈 */ 14: e24cb004 sub fp, ip, #4 ; 0x4 18: e3a02456 mov r2, #1442840576 ; 0x56000000 /* 下面的汇编语言就是操作GPF的寄存器的操作了 */ 1c: e2822050 add r2, r2, #80 ; 0x50 20: e3a03456 mov r3, #1442840576 ; 0x56000000 24: e2833050 add r3, r3, #80 ; 0x50 28: e5933000 ldr r3, [r3] 2c: e3c33c03 bic r3, r3, #768 ; 0x300 30: e5823000 str r3, [r2] 34: e3a02456 mov r2, #1442840576 ; 0x56000000 38: e2822050 add r2, r2, #80 ; 0x50 3c: e3a03456 mov r3, #1442840576 ; 0x56000000 40: e2833050 add r3, r3, #80 ; 0x50 44: e5933000 ldr r3, [r3] 48: e3833c01 orr r3, r3, #256 ; 0x100 4c: e5823000 str r3, [r2] 50: e3a02456 mov r2, #1442840576 ; 0x56000000 54: e2822054 add r2, r2, #84 ; 0x54 58: e3a03456 mov r3, #1442840576 ; 0x56000000 5c: e2833054 add r3, r3, #84 ; 0x54 60: e5933000 ldr r3, [r3] 64: e3c33010 bic r3, r3, #16 ; 0x10 68: e5823000 str r3, [r2] 6c: eafffffe b 6c Disassembly of section .comment: 00000000 <.comment>: 0: 43434700 cmpmi r3, #0 ; 0x0 4: 4728203a undefined 8: 2029554e eorcs r5, r9, lr, asr #10 c: 2e342e33 mrccs 14, 1, r2, cr4, cr3, {1} 10: Address 0x10 is out of bounds. 四、实验现象 实验现象也是点亮一盏LED灯,就不贴图上来了。
上一篇:S3C2440 启动和点亮第一盏LED
下一篇:S3C2440 初始化时钟
推荐阅读最新更新时间:2024-11-09 08:49