使用c語言替代彙編的原理也是往寄存器位址寫數值,通路寄存器位址和通路記憶體是一樣的。給出C語言程式:
int main()
{
unsigned int *pGPFDAT = (unsigned int*)0x56000050;
unsigned int *pGPFCON = (unsigned int*)0x56000054;
*pGPFDAT = 0x400;
*pGPFCON = 0;
return 0;
}
對于main函數的調用:
.text
.global _start
_start:
ldr sp,=4096
//ldr sp,=0x40000000+4096
bl main
halt:
b halt
其中bl表示在棧中調用main函數,傳回值給到halt中。ldr是兩種啟動的程式複制到的最開始的位址。
燒寫oflash xxx.bin
0 1 0 0 0
測試。
原理分析:
start.S 可以用來設定棧,因為c函數要使用,儲存局部變量和lr等寄存器。同時調用者還可以向被調用者傳參數和接受傳回值。
為了使C語言和彙程式設計式之間能夠互相調用,必須為子程式間的調用指定規則,在ARM處理器中這個規則被稱為ATPCS:ARM程式和Thumb程式中子程式調用規則。基本的ATPCS規則包括寄存器使用規則、資料棧使用規則、參數傳遞規則。ARM處理器中有r0-15共16個寄存器,r0到r3用來參數傳遞,r4到r11可能在函數中被使用,是以在函數入口儲存,在函數的出口恢複。
對Nand啟動來說,硬體上會把nand flash前4k的内容完全拷貝的片内的4k記憶體,如何區分是哪種啟動?
// 設定記憶體:sp棧
ldr sp,=4096
ldr sp,=0x40000000+4096
是以分辨的方方法就是寫0到0位址再讀出來,如果得到0表示nand flash啟動:
mov r1,#0 //給r1指派為0
ldr r0,[r1] //把原來0位址的值取出來備份給r0
str r1,[r1] //給0位址寫入0
ldr r2,[r1] //把0位址再讀出來
cmp r1,r2 //比較讀出來的數值r2是不是0
ldr sp,=0x40000000+4096 //預設當成nor啟動調到sp
moveq sp,#4096 //如果r1等于r2的話,說明是nand flash啟動
streq r0,[r1] //再把備份的r0數值放回到0位址中