程式的執行步驟(程式在電腦裡如何運行)
首先,如果有一直在關注我發文的夥伴們,可能會發現我文章的內容十分凌亂,內容包括:C程式語言、演算法、資料結構、機器學習、有時居然還有t程式解題??這是因為筆者自己在學習的過程中,有很多東西都摸不清楚,或是很希望當初可以看到類似的文章,來幫助我釐清觀念。因此想把曾經苦思很久的觀念或想法都重新整理一遍,幫助到未來有需要的人。
還請各位原諒一下這些凌亂的文章~~
話不多說,直接開始今天的主題吧!
前情提要:想當初在學習程式語言的時候,隱隱約約有聽到老師說C語言是怎麼進行的,會從.c
檔,轉成.s
檔,最後又變成.a
檔等等。當聽到的當下,覺得非常新奇,很想要一探究竟,但起出找資料的功力不夠高明(關鍵字下得不好),實在還是無法理解網頁的內容。因此今天就要帶大家認識,
平常在使用的程式是怎麼被機器理解、執行
Outline:
1. C 語言是如何被編譯(Compiler)
2. 什麼是組譯器(Assembler)、連結器(Linker)、載入器(Loader)及其功用
3. 整個程式在電腦裡的執行過程
1. C 語言是如何被編譯(Compiler)
首先,請看下面這張圖,之後會對圖有更詳細的說明。
目標:
Input:C program
Output:可執行檔案
從這張圖來說,最難理解的莫過是Assembler → Object File → Linker的部分。讓我來解釋一下:
- 從C語言變成組合語言的過程,請參考下圖。有寫過組合語言的應該知道,組與有很多東西,需要事前先宣告,後面才能使用。
2. 有了組合語言程式後,我們發現他雖然比C語言複雜,但如果有對組合語言有基本的認知的話,我們人類還是看得懂,主要因為還是大部分由英文字母所組成。所以Assembler的任務,就是要將這些還是由英文字母所組成的語言,轉換成只有機器(電腦)才能理解的「機器語言(Machine Language)」,而電腦能理解的語言當然只有0和1。而經由Assembler所產生的檔案,我們稱為Object File。(可以回上面對照一下圖片有很多01產生的圖片)
相信一定還有人有疑問說,為什麼圖上有好幾個 Object File?
Ans:因為在原本的程式中,我們有呼叫到外部的函式(printf),而在 Linker的階段會把程式所需要的函式、檔案都彙整再一起。因此在前面的步驟要事先產生出多個 Object File,以便後面(Linker)做整合。
補充說明:在C語言中,我們可以看到最上方有
#include<stdio.h>
吧。因為我們在程式內有用到一個printf()
的函式,而在程式碼中,我們也沒有寫過關於怎麼把字串顯示到螢幕上的程式,所以可想而知printf()
這個程式一定存在於某個地方。在程式編譯的過程中,會把printf()
函式呼叫到程式後,再執行。所以在Assembler這個階段,他會去判斷程式中,使用到哪些外部的函式,或是呼叫到哪些額外的 function等。並把程式執行中,所有會用到的 function都列出來。方便之後連結器(Linker)把他們全部連接再一起。
3. 最後連結器(Linker)的工作,則是會把Assembler所產生的object file全部都「連結」再一起後,形成一個「可執行檔(execute)」。
2. 什麼是組譯器(Assembler)、連結器(Linker)、載入器(Loader)
前面大概都已經把各自的任務交代清楚,這邊要對他們做更詳細的說明。
組譯器(Assembler)
組譯器的任務在於「將組合語言轉換成機器語言(由0, 1所組成的語言)」。
Input:組合語言程式
Output:Object File
其中轉換的東西包括以下幾點:
- Header:描述程式的內容、大小、位址等資訊
- Text Segment:機器語言(machine language code)
- Static data segment:資料在程式中的生命週期。
- Relocation information:程式載入到記憶體,表示指定和資料之間的相對位址。
- Symbol table:儲存未定義的標籤,例如:external reference
- Debug information:簡明的闡述程式碼如何被compile,好讓debugger可以連結到原始的C source file。
這邊有些我是直接參考白算盤去翻譯,請大家參考參考即可。不了解的話也沒關係,這不會影響我們對他整個的了解~~
連結器(Linker)
Input:Object File
Output:Execute File(.exe)
主要有三個功能:
- Allocation:向OS要一個起始位址
- Loading:將object code中的Text records載入到Memory
- 決定內部與外部位址參考(Reference)
注意!!這邊為了方便大家理解,上面所呈現的畫面是「一般我們看得懂的程式碼」,但實際上這些程式是Object File(由很多的0, 1所組成的程式碼)
載入器(Loader)
載入器顧名思義,就是把程式變成「可執行檔(.exe)」後,放到電腦裡運行。載入器主要可以分為6個步驟:
- 讀取可執行檔(.exe)的header來決定程式碼(text)、資料區(data segments)
- 建立出一個足夠容納程式碼以及資料(data)的記憶體空間(memory space)
- 複製可執行黨的指令以及資料到memory
- 複製主程式的參數到stack中
- 初始化暫存器、並將堆疊指標(stack pointer)在第一個可用空間
- 跳到start-up routine並且複製參數到argument registers,而且呼叫將要被執行的主程式。主程式結束返回後,呼叫
exit
來結束程式的執行。
3. 整個程式的執行架構
最後只是1, 2兩個步驟的大彙整。
如果內容有任何錯誤,懇請各位夥伴不吝指教~~
希望這篇能幫助大家更加了解程式在電腦裡面的運作,今天就到這邊結束了,那我們就下次再見囉~~