一、从汇编到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灯,就不贴图上来了。