智能小車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,我們這也相當於在開始制作一個系統了。
智能小車34:匯編與C語言一起玩