我想了解裸機C應用程序如何正確工作。我寫了自己的啓動彙編代碼,調用__libc_init_array
,我看到它迭代了preinit_array
部分並調用了其中的所有函數。據我所知GCC增加了需要之前主要運行一些自己的初始化程序段,但隨後進來的.init
部分_init()
功能。裸機C應用程序究竟如何啓動?
是否GCC生成功能?它來自libc嗎?或者我必須自己提供一個嗎?有什麼好的資源來學習這些東西?
我想了解裸機C應用程序如何正確工作。我寫了自己的啓動彙編代碼,調用__libc_init_array
,我看到它迭代了preinit_array
部分並調用了其中的所有函數。據我所知GCC增加了需要之前主要運行一些自己的初始化程序段,但隨後進來的.init
部分_init()
功能。裸機C應用程序究竟如何啓動?
是否GCC生成功能?它來自libc嗎?或者我必須自己提供一個嗎?有什麼好的資源來學習這些東西?
是什麼符號有平臺做?是由一個平臺上的 gcc生成的init_()而不是另一個平臺上的?
是的啓動和epiloque例程留給執行,實際上gcc
不會產生它。
libc中提供這些sysmbols - https://github.com/bminor/newlib/blob/e0f24404b3fcfa2c332ae14c3934546c91be3f42/newlib/libc/misc/init.c
根據您的目標硬件的初始化可以這樣做完全不同的方式。
例STM32Fxxx啓動。
.section .text.Reset_Handler
.weak Reset_Handler
.type Reset_Handler, %function
Reset_Handler:
ldr sp, =_estack /* Atollic update: set stack pointer */
/* Copy the data segment initializers from flash to SRAM */
movs r1, #0
b LoopCopyDataInit
CopyDataInit:
ldr r3, =_sidata
ldr r3, [r3, r1]
str r3, [r0, r1]
adds r1, r1, #4
LoopCopyDataInit:
ldr r0, =_sdata
ldr r3, =_edata
adds r2, r0, r1
cmp r2, r3
bcc CopyDataInit
ldr r2, =_sbss
b LoopFillZerobss
/* Zero fill the bss segment. */
FillZerobss:
movs r3, #0
str r3, [r2], #4
LoopFillZerobss:
ldr r3, = _ebss
cmp r2, r3
bcc FillZerobss
/* Call the clock system intitialization function.*/
bl SystemInit
/* Call static constructors */
bl __libc_init_array
/* Call the application's entry point.*/
bl main
正如你在這個實現兩個功能被稱爲看 - 一個SystemInit
非常低槓桿的硬件初始化和__libc_init_array
它是newlib庫的內部初始化(時下最常見的在裸機使用項目)
的問題是,如果你決定不使用標準庫,你不希望鏈接任何標準庫。一些takechains只提供了返回語句的弱函數,有些則沒有。如果你得到了鏈接問題,只是評論此呼叫在啓動文件或者提供一個空函數自己
良好的資源包括您的平臺文檔和'objdump'。 – spectras
符號與平臺有什麼關係?是在一個平臺上由gcc生成的init_(),而不是在另一個平臺上生成的::) –
所有進程都是特定於平臺的。例如,在AVR上,init代碼必須包含一些填充以跳過中斷向量表。然後內容本身在這裏爲C程序設置運行環境:初始化固定寄存器,設置堆棧指針,可能安裝一些陷阱處理程序...再次,所有這些都是平臺特定的。 – spectras