天天看點

c++對的調用沒有比對的函數_Linux系統啟動時為什麼沒有最先調用main函數?

c++對的調用沒有比對的函數_Linux系統啟動時為什麼沒有最先調用main函數?

學過C語言的人都知道,用C語言設計的程式都有一個main函數,而且是從main函數開始執行的。Linux0.11的代碼是用C語言編寫的。奇怪的是,為什麼在作業系統啟動時先執行的是三個由彙編語言寫成的程式,然後才開始執行main函數;為什麼不是像我們熟知的C語言程式那樣,從main函數開始執行呢?

通常,我們用C語言編寫的程式都是使用者應用程式。這類程式的執行有一個很重要的特征,就是必須在作業系統的平台上執行,也就是說,要由作業系統為應用程式建立程序,并把應用程式的可執行代碼從硬碟加載到記憶體。現在我們讨論的是作業系統,不是普通的應用程式,這樣就出現了一個問題:應用程式是由作業系統加載的,作業系統該由誰加載呢?

從前面的隻是中我們知道,加載作業系統的時候,計算機剛剛加電,隻有BIOS程式在運作,而且此時的計算機處在16位實模式狀态,通過BIOS程式自身的代碼形成的16位的中斷向量表及相關的16位的中斷服務程式,将作業系統在軟碟上的第一扇區(512位元組)的代碼加載到記憶體,BIOS能主動操作的内容也就到此為止了。準确的說,這是一個約定。對于第一扇區代碼的加載,不論是什麼作業系統都是一樣的;從第二扇區開始,就要由第一扇區中的代碼來完成後續的代碼加載工作。

當加載工作完成後,好像仍然沒有立即執行main函數,而是打開A20,打開pe、pg,建立IDT、GDT......然後才開始執行main函數,這是什麼道理?

原因是,Linux0.11是一個32位的實時多任務的現代作業系統,main函數肯定要執行的事32位的代碼。編譯作業系統代碼時,是由16位和32位不同的編譯選項的。如果選擇了16位,C語言編譯出來的代碼是16位模式的,結果可能是一個int型變量,隻有2位元組,而不是32位的4位元組......這不是Linux0.11想要的。Linux0.11要的是32位的編譯結果。隻有這樣才能成為32位的作業系統代碼。這樣的代碼才能用到32位總線(打開A20後的總線),才能用到保護模式和分頁,才能成為32位的實時多任務的現代作業系統。

開機時的16位實模式與main函數執行需要的32位保護模式之間有很大的差距,這個差距誰來填補?head.s做的就是這項工作。這期間,head程式打開A20,打開pe、pg。廢棄舊的、16位的中斷響應機制,建立新的32位的IDT......這些工作都做完了,計算機已經處在32位的保護模式狀态了,調用32位main函數的一切條件已經準備完畢,這時順理成章地調用main函數。後面的作業系統就可以用32位編譯的main函數完成。

繼續閱讀