程序是如何運(yùn)行的作為一個(gè)程序員,已不知編了多少行代碼。但若問我程序是如何在計(jì)算機(jī)中運(yùn)行的,我怕只有張口結(jié)舌。書中第一章就給了我們相關(guān)的答案。
首先,看如下最簡(jiǎn)單的C語(yǔ)言Helloword的代碼
1
#include <stdio.h>
2
3
int main()
4

{
5
printf("hello, world\n");
6
}
上面的代碼我們保存在helloworld.c文件中。其本質(zhì)實(shí)際上是由0、1的比特(位)序列構(gòu)成的。8位為一個(gè)字節(jié)。每個(gè)字節(jié)對(duì)應(yīng)某個(gè)文本字符。不少系統(tǒng)用ASCII來(lái)表示文本字符。實(shí)際是由一個(gè)唯一的同字節(jié)大小的整數(shù)值來(lái)表示每個(gè)字符。下面給出helloworld.c的ASCII表示。
# i n c l u d e <sp> < s t d i o .
35 105 110 99 108 117 100 101 32 60 115 116 100 105 111 46
h > \n \n i n t <sp> m a i n ( ) \n {
104 62 10 10 105 110 116 32 109 97 105 110 40 41 10 123
\n <sp> <sp> <sp> <sp> p r i n t f ( " h e l
10 32 32 32 32 112 114 105 110 116 102 40 34 104 101 108
l o , <sp> w o r l d \ n " ) ; \n }
108 111 44 32 119 111 114 108 100 92 110 34 41 59 10 125
以此類推,在計(jì)算機(jī)系統(tǒng)中,任何介質(zhì)中的數(shù)據(jù)都是比特序列。把他們區(qū)分成不同的數(shù)據(jù)對(duì)象,是通過數(shù)據(jù)對(duì)象的上下文來(lái)確定的。
程序編譯程序的編譯過程如下圖所示,分為預(yù)處理、編譯、匯編、鏈接等幾個(gè)階段。

預(yù)處理:預(yù)處理相當(dāng)于根據(jù)預(yù)處理命令組裝成新的C程序,不過常以i為擴(kuò)展名。
編譯: 將得到的i文件翻譯成匯編代碼。s文件。
匯編: 將匯編文件翻譯成機(jī)器指令,并打包成可重定位目標(biāo)程序的O文件。該文件是二進(jìn)制文件,字節(jié)編碼是機(jī)器指令。
鏈接: 將引用的其他O文件并入到我們程序所在的o文件中,處理得到最終的可執(zhí)行文件。
硬件組成:從下圖中看出一個(gè)典型的系統(tǒng)由總線、Cpu、I/O設(shè)備、主存等構(gòu)成。

CPU: Central Processing Unit, ALU: Arithmetic/Logic Unit, PC: Program counter, USB: Universal Serial Bus.
程序執(zhí)行
我們已經(jīng)討論了可執(zhí)行文件產(chǎn)生的過程。接下來(lái)討論哈可執(zhí)行文件執(zhí)行的過程。從上面途中的彩色線條可以清晰的看到這個(gè)過程,我們簡(jiǎn)單的把它分為6步。
1.shell程序執(zhí)行指令,等待用戶輸入,這里我們輸入“hello”。
2.shell程序?qū)⒆址鹨蛔x到寄存器中
3.再?gòu)募拇嫫魅〕龇诺街鞔嬷?br>4.當(dāng)我們敲入回車時(shí),shell程序得知輸入結(jié)束,將hello目標(biāo)文件的代碼和數(shù)據(jù)拷貝到主存,從而加載hello文件數(shù)據(jù)包括最終被輸出的字符串“hello,world\n”.利用了DMA訪問技術(shù),數(shù)據(jù)可不經(jīng)CPU直接到主存
5.執(zhí)行主程序中的機(jī)器語(yǔ)言指令,將“hello,world\n”串的字節(jié)從主存拷貝到寄存器堆。
6.從寄存器中把文件拷貝到顯示設(shè)備。