智能小车34:汇编与C语言一起玩

长时间写java程序,但从来没去研究main函数是如何执行的,今天学习嵌入式终于知道了原理。


之前看过一本30天做一个操作系统这本书,可以通过写个2进制文件来启动系统。然后进化到汇编语言,通过工具把汇编转为二进制一样可以启动系统(虚拟机)。这个系统的执行过程与我们的main函数有什么联系么。做java的同学知道,只要执行java命令自然会执行main函数。做c语言的同学,知道在编译后执行可执行文件(sh a.out)自然也会执行main函数。但为什么呢?看下面这段汇编代码:

.text

.global _start

_start:

      ldr   r0, =0x53000000   @ WATCHDOG寄存器地址

      mov   r1, #0x0          

      str   r1, [r0]      @ 写入0,禁止WATCHDOG,否则CPU会不断重启

      

      ldr   sp, =1024*4     @ 设置堆栈,注意:不能大于4k, 因为现在可用的内存只有4K

                    @ nand flash中的代码在复位后会移到内部ram中,此ram只有4K

      bl   main        @ 调用C程序中的main函数

halt_loop:

      b   halt_loop


start段开始后的前3行是关门看门狗程序,防止重启。ldr是设置一个4k的内存,也就是程序的存放地址。bl就是调用main函数了,后面是死循环不用管。

下面我们再写段C语言:
#define GPFCON   (*(volatile unsigned long *)0x56000050)

#define GPFDAT   (*(volatile unsigned long *)0x56000054)



int main()

{

  GPFCON = 0x00000100;  // 设置GPF4为输出口, 位[8:7]=0b01

  GPFDAT = 0x00000000;  // GPF4输出0,LED1点亮



  return 0;

}


上面两个宏是定义控制寄存器的地址,为什么是0x56000050,这是从2440板子的数据手册中找到的。如下图:



最后这个c语言程序与汇编程序如何连起来呢?看makefile文件:
arm-linux-gcc -g -c -o crt0.o crt0.S
arm-linux-gcc -g -c -o led_on_c.o led_on_c.c
arm-linux-ld -Ttext 0x0000000 -g crt0.o led_on_c.o -o led_on_c_elf
arm-linux-objcopy -O binary -S led_on_c_elf led_on_c.bin
arm-linux-objdump -D -m arm led_on_c_elf > led_on_c.dis

先编译汇编程序(crto.S),再编译c语言(led_on_c.c),再把这两生成的目标文件链接为led_on_c_elf文件,再把这个转为二进制文件。这个就可以烧进板子执行了。 其实30天制作操作系统也可以通过这个方法也制作,不过工具不是arm-linux_gcc,我们这也相当于在开始制作一个系统了。

文/程忠 浏览次数:0次   2017-10-03 13:28:40

相关阅读


评论: