S5PV210开发板用汇编设置栈和调用C语言
使用C語言前為什么要先用匯編設置棧?
C語言程序運行時需要棧,因為C語言中的局部變量都是用棧來實現的,如果沒有設置棧就使用C語言,局部變量就會落空,程序就會死掉,所以在使用C語言前,我們需要先在匯編編寫的啟動代碼中設置棧。
為什么使用51單片機和Ubuntu編寫應用程序時我們沒有設置棧依然能使用C語言?
原因是在單片機中已經由硬件設置提供了一個默認可用的棧,而在應用程序中我們編寫的C程序其實并不是全部,編譯器(gcc)在鏈接時會幫我們自動添加一個頭,這個頭就是一段引導C程序能夠執行的匯編代碼,在這個代碼中就幫我們的C程序設置了棧及其他的運行時需要。
為什么不同CPU模式下都有各自獨立的sp寄存器?
如果各個模式都使用同一個sp,意味著整個程序(操作系統內核程序,用戶應用程序)都使用同一個棧,這樣做,一旦用戶程序編寫出錯(棧溢出),將會影響操作系統的正常運行,操作系統會崩潰,同時運行在操作系統上的其他應用程序也會崩潰。所以各個模式下要使用不同的sp,使用不同的棧,操作系統有自己的棧,每個應用程序也有自己的棧,互不干擾。
怎么設置棧?
我們要設置棧,并不是設置所有CPU模式下的棧,而是設置當前CPU模式下的棧,因為這個程序可能只用到一種CPU模式。S5PV210復位后默認是進入SVN模式下的,我們設置當前模式下的棧,只需直接操作sp即可。
需要注意的是,棧必須是當前一段可用的內存(可用的意思是這個地方是有被初始化過的可以訪問的內存,而且這個內存只會被我們用作棧,不會被其他程序征用)
當前CPU剛復位(剛啟動),外部的DDR尚未初始化,需要我們后續對其初始化,所以目前可用的內存只有內部的SRAM(因為它不需初始化即可使用)。因此我們只能在SRAM中找一段內存來作為SVC的棧。
在ARM中,ATPCS(ARM關于程序應該怎么實現的一個規范)要求使用滿減棧,結合iROM_application_note中的memory map,可知SVC棧應該設置為0xD0037D80。
示例代碼:
start.S
led.c
#define GPJ0CON 0xE0200240 #define GPJ0DAT 0xE0200244 #define rGPJ0CON *((volatile unsigned int*)GPJ0CON) #define rGPJ0DAT *((volatile unsigned int*)GPJ0DAT) void delay(void); void led_blink(void) {rGPJ0CON = 0x11111111; while(1){rGPJ0DAT = ~(1<<3);delay();rGPJ0DAT = ~(1<<4);delay();rGPJ0DAT = ~(1<<5);delay();} }void delay(void) {volatile unsigned int i = 3000000;while(i--); } /* volatile的作用是防止編譯器優化我們的變量,有時候編譯器會認為我們對這個變量的操作是無意義的,例如對一個數+1然后-1,有些編譯器會直接保持原值不變 ,這樣做的結果可能導致我們的程序不對,所以為了不受編譯器的這個影響,加上 volatile會使程序更加穩定,一般對易變的變量都加上volatile,至于加不加volatile結果會不會有什么不同,取決于編譯器,一些編譯器不會對此優化,一些則會。 */Makefile
led.bin: start.o led.oarm-linux-ld -Ttext 0x0 -o led.elf $^arm-linux-objcopy -O binary led.elf led.binarm-linux-objdump -D led.elf > led_elf.disgcc mkv210_image.c -o mkx210./mkx210 led.bin 210.bin%.o : %.Sarm-linux-gcc -o $@ $< -c -nostdlib%.o : %.carm-linux-gcc -o $@ $< -c -nostdlib#這里要加-nostdlib,作用是不使用編譯器自帶的標準函數庫文件#因為led.c文件中的delay函數與編譯器自帶的標準函數庫中的delay重名#默認會去使用編譯器自帶的,我們要使用自己定義的話就會報錯#相當于你一個C程序定義了兩個同名函數 clean:rm *.o *.elf *.bin *.dis mkx210 -f總結
以上是生活随笔為你收集整理的S5PV210开发板用汇编设置栈和调用C语言的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: navicat如何粘贴多行数据
- 下一篇: Python 实现劳拉游戏(四连环、重力