1. 程式人生 > >智能小車34:匯編與C語言一起玩

智能小車34:匯編與C語言一起玩

vol -s c語言: 否則 rto 輸出 代碼 過程 看門狗

長時間寫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語言一起玩