要想清楚的了解程序的執(zhí)行過程就要先知道計(jì)算機(jī)的基本結(jié)構(gòu)
2. 圖靈和圖靈機(jī)
阿蘭·圖靈于1912年出生于英國,擅長數(shù)理邏輯學(xué)和計(jì)算理論。
阿蘭.圖靈
圖靈機(jī)是阿蘭·圖靈在24歲時(shí)提出的,發(fā)表在論文《論可計(jì)算數(shù)及其在判定問題中的應(yīng)用》。圖靈的基本思想是用機(jī)器來模擬人們用紙筆進(jìn)行數(shù)學(xué)運(yùn)算的過程,而且還定義了計(jì)算機(jī)由哪些部分組成,程序又是如何執(zhí)行的。
圖靈機(jī)長什么樣子呢?示意圖如下:
基本組成部分:
- 「紙帶」:紙帶由一個(gè)個(gè)連續(xù)的格子組成,每個(gè)格子可以寫入字符,紙帶就好比內(nèi)存,而紙帶上的格子的字符就好比內(nèi)存中的數(shù)據(jù)或程序;
- 「讀寫頭」:讀寫頭可以順序讀取紙帶上格子的字符,也可以把字符寫入到紙帶的格子;
- 讀寫頭部件:如存儲(chǔ)單元、控制單元以及運(yùn)算單元:1、存儲(chǔ)單元用于存放數(shù)據(jù);2、控制單元用于識(shí)別字符是數(shù)據(jù)還是指令,以及控制程序的流程等;3、運(yùn)算單元用于執(zhí)行運(yùn)算指令;
圖靈機(jī)只是一個(gè)抽象的模型,這個(gè)理想的模型是好,但是理想終歸是理想,想要成為現(xiàn)實(shí),我們得想其它辦法。于是在此基礎(chǔ)上,馮洛伊曼提出了電子計(jì)算機(jī)使用二進(jìn)制數(shù)制系統(tǒng)和儲(chǔ)存程序,并按照程序順序執(zhí)行,即馮諾依曼體系結(jié)構(gòu)。
3. 馮諾依曼模型
在 1945 年馮諾依曼和其他計(jì)算機(jī)科學(xué)家們提出了計(jì)算機(jī)具體實(shí)現(xiàn)的報(bào)告,其遵循了圖靈機(jī)的設(shè)計(jì),而且還提出用電子元件構(gòu)造計(jì)算機(jī),并約定了用二進(jìn)制進(jìn)行計(jì)算和存儲(chǔ)。
根據(jù)馮諾依曼體系結(jié)構(gòu)構(gòu)成的計(jì)算機(jī),必須具有如下功能:
· 把程序和數(shù)據(jù)裝入到計(jì)算機(jī)中;
· 必須具有長期記住程序、數(shù)據(jù)的中間結(jié)果及最終運(yùn)算結(jié)果;
· 完成各種算術(shù)、邏輯運(yùn)算和數(shù)據(jù)傳送等數(shù)據(jù)加工處理;
· 根據(jù)需要控制程序走向,并能根據(jù)指令控制機(jī)器的各部件協(xié)調(diào)操作;
· 能夠按照要求將處理的數(shù)據(jù)結(jié)果顯示給用戶。
為了完成上述的功能,計(jì)算機(jī)必須具備五大基本組成部件:
· 裝載數(shù)據(jù)和程序的輸入設(shè)備;
· 記住程序和數(shù)據(jù)的存儲(chǔ)器;
· 完成數(shù)據(jù)加工處理的運(yùn)算器;
· 控制程序執(zhí)行的控制器;
· 顯示處理結(jié)果的輸出設(shè)備。
因此,定義計(jì)算機(jī)基本結(jié)構(gòu)就需要 5 個(gè)部分:運(yùn)算器、控制器、存儲(chǔ)器、輸入設(shè)備、輸出設(shè)備,這 5 個(gè)部分也被稱為馮諾依曼模型。
馮諾依曼體系結(jié)構(gòu)是現(xiàn)代計(jì)算機(jī)的基礎(chǔ)。在該體系結(jié)構(gòu)下,程序和數(shù)據(jù)統(tǒng)一存儲(chǔ),指令和數(shù)據(jù)需要從同一存儲(chǔ)空間存取,經(jīng)由同一總線傳輸,無法重疊執(zhí)行。根據(jù)馮諾依曼體系,CPU的工作分為以下 5 個(gè)階段:取指令階段、指令譯碼階段、執(zhí)行指令階段、訪存取數(shù)和結(jié)果寫回。
· 取指令(IF,instruction fetch),即將一條指令從主存儲(chǔ)器中取到指令寄存器的過程。程序計(jì)數(shù)器中的數(shù)值,用來指示當(dāng)前指令在主存中的位置。當(dāng) 一條指令被取出后,程序計(jì)數(shù)器(PC)中的數(shù)值將根據(jù)指令字長度自動(dòng)遞增。
· 指令譯碼階段(ID,instruction decode),取出指令后,指令譯碼器按照預(yù)定的指令格式,對(duì)取回的指令進(jìn)行拆分和解釋,識(shí)別區(qū)分出不同的指令類 別以及各種獲取操作數(shù)的方法。現(xiàn)代CISC處理器會(huì)將拆分已提高并行率和效率。
· 執(zhí)行指令階段(EX,execute),具體實(shí)現(xiàn)指令的功能。CPU的不同部分被連接起來,以執(zhí)行所需的操作。
· 訪存取數(shù)階段(MEM,memory),根據(jù)指令需要訪問主存、讀取操作數(shù),CPU得到操作數(shù)在主存中的地址,并從主存中讀取該操作數(shù)用于運(yùn)算。部分指令不需要訪問主存,則可以跳過該階段。
· 結(jié)果寫回階段(WB,write back),作為最后一個(gè)階段,結(jié)果寫回階段把執(zhí)行指令階段的運(yùn)行結(jié)果數(shù)據(jù)“寫回”到某種存儲(chǔ)形式。結(jié)果數(shù)據(jù)一般會(huì)被寫到CPU的內(nèi)部寄存器中,以便被后續(xù)的指令快速地存??;許多指令還會(huì)改變程序狀態(tài)字寄存器中標(biāo)志位的狀態(tài),這些標(biāo)志位標(biāo)識(shí)著不同的操作結(jié)果,可被用來影響程序的動(dòng)作。
在指令執(zhí)行完畢、結(jié)果數(shù)據(jù)寫回之后,若無意外事件(如結(jié)果溢出等)發(fā)生,計(jì)算機(jī)就從程序計(jì)數(shù)器中取得下一條指令地址,開始新一輪的循環(huán),下一個(gè)指令周期將順序取出下一條指令。 許多復(fù)雜的CPU可以一次提取多個(gè)指令、解碼,并且同時(shí)執(zhí)行。
運(yùn)算器、控制器是在中央處理器里的,存儲(chǔ)器就我們常見的內(nèi)存,輸入輸出設(shè)備則是計(jì)算機(jī)外接的設(shè)備,比如鍵盤就是輸入設(shè)備,顯示器就是輸出設(shè)備。
存儲(chǔ)單元和輸入輸出設(shè)備要與中央處理器打交道的話,離不開總線。所以,它們之間的關(guān)系如下圖:
接下來,分別介紹內(nèi)存、中央處理器、總線、輸入輸出設(shè)備。
3.1. 內(nèi)存
簡稱(RAM)專業(yè)的說內(nèi)存是計(jì)算機(jī)中重要的部件之一,它是與CPU進(jìn)行溝通的橋梁。計(jì)算機(jī)所有的程序都是在內(nèi)存中運(yùn)行的,如果沒有內(nèi)存你的電腦將開不了機(jī)。
在計(jì)算機(jī)數(shù)據(jù)存儲(chǔ)中,存儲(chǔ)數(shù)據(jù)的基本單位是字節(jié)(byte),1 字節(jié)等于 8 位(8 bit)。每一個(gè)字節(jié)都對(duì)應(yīng)一個(gè)內(nèi)存地址。
內(nèi)存的地址是從 0 開始編號(hào)的,然后自增排列,最后一個(gè)地址為內(nèi)存總字節(jié)數(shù) - 1,這種結(jié)構(gòu)好似我們程序里的數(shù)組,所以內(nèi)存的讀寫任何一個(gè)數(shù)據(jù)的速度都是一樣的。
RAM的優(yōu)點(diǎn):是存取速度快、讀寫方便。缺點(diǎn):是數(shù)據(jù)不能長久保持,斷電后自行消失,因此主要用于計(jì)算機(jī)主存儲(chǔ)器等要求快速存儲(chǔ)的系統(tǒng)。按工作方式不同,可分為靜態(tài)和動(dòng)態(tài)兩類。
靜態(tài)隨機(jī)存儲(chǔ)器(SRAM)的單元電路是觸發(fā)器,存入的信息在規(guī)定的電源電壓下便不會(huì)改變。SRAM速度快,使用方便。
動(dòng)態(tài)隨機(jī)存儲(chǔ)器(DRAM)的單元由一個(gè)金屬-氧化物-半導(dǎo)體(MOS)電容和一個(gè)MOS晶體管構(gòu)成,數(shù)據(jù)以電荷形式存放在電容之中,需每隔2~4毫秒對(duì)單元電路存儲(chǔ)信息重寫一次(刷新)。DRAM存儲(chǔ)單元器件數(shù)量少,集成度高,應(yīng)用廣泛。
3.2. 中央處理器
CPU:中央處理器,由運(yùn)算器和控制器組成。計(jì)算機(jī)解決某個(gè)問題時(shí)要為它編寫程序,它告訴計(jì)算機(jī)要執(zhí)行什么操作,在什么地方來找到用來操作的數(shù)據(jù)一旦把程序加載到內(nèi)存儲(chǔ)器,CPU的基本工作是執(zhí)行存儲(chǔ)的指令序列,即程序。程序的執(zhí)行過程實(shí)際上是不斷地取出指令、分析指令、執(zhí)行指令的過程。
CPU從存放程序的主存儲(chǔ)器里取出一條指令,譯碼并執(zhí)行這條指令,保存執(zhí)行結(jié)果,緊接著又去取指令,譯碼,執(zhí)行指令……,如此周而復(fù)始,反復(fù)循環(huán),使得計(jì)算機(jī)能夠自動(dòng)地工作。除非遇到停機(jī)指令,否則這個(gè)循環(huán)將一直進(jìn)行下去。其過程如圖所示
CPU 中的寄存器主要作用是存儲(chǔ)計(jì)算時(shí)的數(shù)據(jù),你可能好奇為什么有了內(nèi)存還需要寄存器?原因很簡單,因?yàn)閮?nèi)存離 CPU 太遠(yuǎn)了,而寄存器就在 CPU 里,還緊挨著控制單元和邏輯運(yùn)算單元,自然計(jì)算時(shí)速度會(huì)很快。
常見的寄存器種類:
- 通用寄存器,用來存放需要進(jìn)行運(yùn)算的數(shù)據(jù),比如需要進(jìn)行加和運(yùn)算的兩個(gè)數(shù)據(jù)。
- 程序計(jì)數(shù)器,用來存儲(chǔ) CPU 要執(zhí)行下一條指令「所在的內(nèi)存地址」,注意不是存儲(chǔ)了下一條要執(zhí)行的指令,此時(shí)指令還在內(nèi)存中,程序計(jì)數(shù)器只是存儲(chǔ)了下一條指令「的地址」。
- 指令寄存器,用來存放當(dāng)前正在執(zhí)行的指令,也就是指令本身,指令被執(zhí)行完成之前,指令都存儲(chǔ)在這里。
總線(Bus),是指計(jì)算機(jī)設(shè)備和設(shè)備之間傳輸信息的公共數(shù)據(jù)通道。在城市中,車輛通行需要道路,需要交通。在計(jì)算機(jī)中,同樣需要在各部件之間傳輸信息的通路,信息通過電線束從一個(gè)計(jì)算機(jī)部件到另一個(gè)部件,就稱作總線,它是一種信號(hào)傳遞的布線方式??偩€是用于 CPU 和內(nèi)存以及其他設(shè)備之間的通信,總線按照不同的分類標(biāo)準(zhǔn)可以有不同的分類。按照傳遞的數(shù)據(jù)分可分為 3 種:
- 地址總線,用于指定 CPU 將要操作的內(nèi)存地址;
- 數(shù)據(jù)總線,用于讀寫內(nèi)存的數(shù)據(jù);
- 控制總線,用于發(fā)送和接收信號(hào),比如中斷、設(shè)備復(fù)位等信號(hào),CPU 收到信號(hào)后自然進(jìn)行響應(yīng),這時(shí)也需要控制總線;
當(dāng) CPU 要讀寫內(nèi)存數(shù)據(jù)的時(shí)候,一般需要通過下面這三個(gè)總線:
- 首先要通過「地址總線」來指定內(nèi)存的地址;
- 然后通過「控制總線」控制是讀或?qū)懨睿?/li>
- 最后通過「數(shù)據(jù)總線」來傳輸數(shù)據(jù);
按照在計(jì)算機(jī)所在區(qū)域分:內(nèi)部總線,系統(tǒng)總線,外部總線。按實(shí)現(xiàn)方式分:并行總線,串行總線。
3.4. 輸入、輸出設(shè)備
輸入輸出設(shè)備(IO設(shè)備),是數(shù)據(jù)處理系統(tǒng)的關(guān)鍵外部設(shè)備之一,可以和計(jì)算機(jī)本體進(jìn)行交互使用。輸入設(shè)備向計(jì)算機(jī)輸入數(shù)據(jù),計(jì)算機(jī)經(jīng)過計(jì)算后,把數(shù)據(jù)輸出給輸出設(shè)備。期間,如果輸入設(shè)備是鍵盤,按下按鍵時(shí)是需要和 CPU 進(jìn)行交互的,這時(shí)就需要用到控制總線了。
4. 線路位寬與 CPU 位寬
我們經(jīng)常聽到32位或64位計(jì)算機(jī),32 位和 64 位 CPU 最主要區(qū)別在于一次能計(jì)算多少字節(jié)數(shù)據(jù):
- 32 位 CPU 一次可以計(jì)算 4 個(gè)字節(jié);
- 64 位 CPU 一次可以計(jì)算 8 個(gè)字節(jié);
這里的 32 位和 64 位,通常稱為 CPU 的位寬。
線路位寬:數(shù)據(jù)是如何通過線路傳輸?shù)哪??其?shí)是通過操作電壓,低電壓表示 0,高壓電壓則表示 1。為了避免低效率的串行傳輸?shù)姆绞剑?strong>線路的位寬最好一次就能訪問到所有的內(nèi)存地址。
CPU 要操作的內(nèi)存地址空間就需要相應(yīng)的地址總線:
- 如果地址總線只有 1 條,那每次只能表示 「0 或 1」這兩種地址,所以 CPU 能操作的內(nèi)存地址最大數(shù)量為 2(2^1)個(gè)(注意,不要理解成同時(shí)能操作 2 個(gè)內(nèi)存地址);
- 如果地址總線有 2 條,那么能表示 00、01、10、11 這四種地址,所以 CPU 能操作的內(nèi)存地址最大數(shù)量為 4(2^2)個(gè)。
那么,想要 CPU 操作 4G 大的內(nèi)存,那么就需要 32 條地址總線,因?yàn)?2 ^ 32 = 4G。
CPU 位寬:CPU 的位寬最好等于線路位寬,比如 32 位 CPU 控制 40 位寬的地址總線和數(shù)據(jù)總線的話,處理比較麻煩。所以 32 位的 CPU 最好和 32 位寬的線路搭配,64 位的 CPU 最好和 64 位寬的線路搭配。但是并不代表 64 位 CPU 性能比 32 位 CPU 高很多,很少應(yīng)用需要算超過 32 位的數(shù)字,所以如果計(jì)算的數(shù)額不超過 32 位數(shù)字的情況下,32 位和 64 位 CPU 之間沒什么區(qū)別的,只有當(dāng)計(jì)算超過 32 位數(shù)字的情況下,64 位的優(yōu)勢才能體現(xiàn)出來。另外,32 位 CPU 最大只能操作 4GB 內(nèi)存,就算你裝了 8 GB 內(nèi)存條,也沒用實(shí)質(zhì)的作用。而 64 位 CPU 尋址范圍則很大,理論最大的尋址空間為 2^64。
5. 一個(gè)程序的生與死
程序?qū)嶋H上就是把我們現(xiàn)實(shí)中的一個(gè)生活場景,通過計(jì)算機(jī)的編程語言搬到電腦中的一種實(shí)現(xiàn)方式罷了。
程序?qū)嶋H上是一條一條指令,負(fù)責(zé)執(zhí)行指令的就是 CPU 了。一個(gè)程序執(zhí)行的時(shí)候,CPU 會(huì)根據(jù)程序計(jì)數(shù)器里的內(nèi)存地址,從內(nèi)存里面把需要執(zhí)行的指令讀取到指令寄存器里面執(zhí)行,然后根據(jù)指令長度自增,開始順序讀取下一條指令。
現(xiàn)代大多數(shù) CPU 都使用來流水線的方式來執(zhí)行指令,所謂的流水線就是把一個(gè)任務(wù)拆分成多個(gè)小任務(wù),于是一條指令通常分為 4 個(gè)階段,稱為 4 級(jí)流水線,如下圖:
四個(gè)階段的具體含義:取得指令,指令譯碼,執(zhí)行指令,數(shù)據(jù)回寫。上面這 4 個(gè)階段,我們稱為指令周期(Instrution Cycle),CPU 的工作就是一個(gè)周期接著一個(gè)周期,周而復(fù)始。
每個(gè)CPU都有一套自己可以執(zhí)行的專門的指令集。接下來我們選用最簡單的 MIPS 指集,來看看機(jī)器碼是如何生成的。MIPS 的指令是一個(gè) 32 位的整數(shù),高 6 位代表著操作碼,表示指令類型,剩下的 26 位根據(jù)不同指令類型所表示的內(nèi)容也就不相同,總結(jié)下來主要有三種類型R、I 和 J。
具體含義:
- R 指令:用在算術(shù)和邏輯操作,里面有讀取和寫入數(shù)據(jù)的寄存器地址。如果是邏輯位移操作,后面還有位移操作的「位移量」,而最后的「功能碼」則是再前面的操作碼不夠的時(shí)候,擴(kuò)展操作碼來表示對(duì)應(yīng)的具體指令的;
- I 指令:用在數(shù)據(jù)傳輸、條件分支等。這個(gè)類型的指令,就沒有了位移量和功能碼,也沒有了第三個(gè)寄存器,而是把這三部分直接合并成了一個(gè)地址值或一個(gè)常數(shù);
- J 指令:用在跳轉(zhuǎn),高 6 位之外的 26 位都是一個(gè)跳轉(zhuǎn)后的地址;
編譯器在編譯程序的時(shí)候,會(huì)構(gòu)造指令,這個(gè)過程叫做指令的編碼。CPU 執(zhí)行程序的時(shí)候,就會(huì)解析指令,這個(gè)過程叫作指令的解碼。
CPU需要使用一個(gè)叫做存儲(chǔ)器(也就是各種寄存器)的東西保存輸入和輸出數(shù)據(jù)。以下是幾種常見的寄存器
· MAR: memory address register,保存將要被訪問數(shù)據(jù)在內(nèi)存中哪個(gè)地址處,保存的是地址值
· MDR: memory data register,保存從內(nèi)存讀取進(jìn)來的數(shù)據(jù)或?qū)⒁獙懭雰?nèi)存的數(shù)據(jù),保存的是數(shù)據(jù)值
· AC: Accumulator,保存算術(shù)運(yùn)算和邏輯運(yùn)算的中間結(jié)果,保存的是數(shù)據(jù)值
· PC: Program Counter,保存下一個(gè)將要被執(zhí)行指令的地址,保存的是地址值
· CIR: current instruction register,保存當(dāng)前正在執(zhí)行的指令
關(guān)于CPU上的高速緩存
- 最高速的緩存是CPU的寄存器,它們和CPU的材料相同,最靠近CPU或最接近CPU,訪問它們沒有時(shí)延(<1ns)。但容量很小,小于1kb。32bit:32*32比特=128字節(jié),64bit:64*64比特=512字節(jié)
- 寄存器之下,是CPU的高速緩存。分為L1緩存、L2緩存、L3緩存,每層速度按數(shù)量級(jí)遞減、容量也越來越大
指令的類型
指令從功能角度分為 5 大類:
- 數(shù)據(jù)傳輸:比如 store/load 是寄存器與內(nèi)存間數(shù)據(jù)傳輸?shù)闹噶?,mov 是將一個(gè)內(nèi)存地址的數(shù)據(jù)移動(dòng)到另一個(gè)內(nèi)存地址的指令;
- 運(yùn)算類型:比如加減乘除、位運(yùn)算、比較大小等等,它們是二元運(yùn)算;
- 跳轉(zhuǎn)類型:通過修改程序計(jì)數(shù)器的值來達(dá)到跳轉(zhuǎn)執(zhí)行指令的過程,比如編程中常見的 if-else、switch-case、goto函數(shù)調(diào)用等。
- 信號(hào)類型:比如發(fā)生中斷的指令 trap;
- 閑置類型:比如指令 nop,執(zhí)行后 CPU 會(huì)空轉(zhuǎn)一個(gè)周期;
指令的執(zhí)行速度
CPU 的硬件參數(shù)都會(huì)有 GHz 這個(gè)參數(shù),比 1 GHz 的 CPU指的是時(shí)鐘頻率是 1 G,代表著 1 秒會(huì)產(chǎn)生 1G 次數(shù)的脈沖信號(hào),每一次脈沖信號(hào)高低電平的轉(zhuǎn)換就是一個(gè)周期,稱為時(shí)鐘周期。
對(duì)于 CPU 來說,在一個(gè)時(shí)鐘周期內(nèi),CPU完成一個(gè)指令時(shí)鐘頻率越高,時(shí)鐘周期就越短,工作速度也就越快。
一個(gè)時(shí)鐘周期一定能執(zhí)行完一條指令嗎?答案是不一定的,大多數(shù)指令不能在一個(gè)時(shí)鐘周期完成,通常需要若干個(gè)時(shí)鐘周期。不同的指令需要的時(shí)鐘周期是不同的,加法和乘法都對(duì)應(yīng)著一條 CPU 指令,但是乘法需要的時(shí)鐘周期就要比加法多。
程序執(zhí)行耗費(fèi)的 CPU 時(shí)間少就說明程序執(zhí)行的快。對(duì)于程序的 CPU 執(zhí)行時(shí)間,我們可以拆解成 CPU 時(shí)鐘周期數(shù)(CPU Cycles)和時(shí)鐘周期時(shí)間(Clock Cycle Time)的乘積。
時(shí)鐘周期時(shí)間就是 CPU 主頻,主頻越高說明 CPU 的工作速度就越快,比如電腦的 CPU 是 2.4 GHz 四核 Intel Core i5,這里的 2.4 GHz 就是電腦的主頻,時(shí)鐘周期時(shí)間就是 1/2.4G。
要想 CPU 跑的更快,自然縮短時(shí)鐘周期時(shí)間,對(duì)于 CPU 時(shí)鐘周期數(shù)我們可以進(jìn)一步拆解成:「指令數(shù) x 每條指令的平均時(shí)鐘周期數(shù)(Cycles Per Instruction,簡稱 CPI)」,于是程序的 CPU 執(zhí)行時(shí)間的公式可變成如下:
因此,要想程序跑的更快,優(yōu)化這三者即可:
- 指令數(shù),表示執(zhí)行程序所需要多少條指令,以及哪些指令。這個(gè)依賴編譯器的優(yōu)化。
- 每條指令的平均時(shí)鐘周期數(shù) CPI,表示一條指令需要多少個(gè)時(shí)鐘周期數(shù),現(xiàn)代大多數(shù) CPU 通過流水線技術(shù)(Pipeline),讓一條指令需要的 CPU 時(shí)鐘周期數(shù)盡可能的少;
- 時(shí)鐘周期時(shí)間,表示計(jì)算機(jī)主頻,取決于計(jì)算機(jī)硬件。
當(dāng)我們輸入以下程序,編譯運(yùn)行,計(jì)算機(jī)從屏幕輸出Hello,World!整個(gè)過程計(jì)算機(jī)都怎么運(yùn)作的呢?
計(jì)算機(jī)內(nèi)部存儲(chǔ)的是0和1,計(jì)算機(jī)通過位信息以及上下文來解讀這些0、1信息的。Hellow,World是由0和1組成的序列,將這些程序代碼轉(zhuǎn)換成相應(yīng)的文本字符,每8位表示一個(gè)字節(jié),用來存儲(chǔ)一個(gè)字符。
Hello,World的ASCII碼表示
因?yàn)槲覀冚斎氲腍ello,World是人可以閱讀和編寫的,但是機(jī)器并不能直接識(shí)別,它需要把這些文字翻譯成機(jī)器可執(zhí)行的二進(jìn)制文件,這一部分的工作是由編譯系統(tǒng)完成的。編譯系統(tǒng)由預(yù)處理器、編譯器、匯編器、連接器四部分組成。以hello, world程序?yàn)槔?,各部分共同完成將源文件編譯成二進(jìn)制可執(zhí)行文件。各個(gè)部分完成的具體工作如下:
- 預(yù)處理器:根據(jù)以#開頭的命令,將包含的頭文件加載進(jìn)入源程序源程序。預(yù)處理器是一個(gè)文本處理程序,它在程序編譯的第一個(gè)階段處理源代碼的文本。當(dāng)然預(yù)處理器不只是編譯之前才被調(diào)用處理源代碼,它也可以被其他程序單獨(dú)的調(diào)用以實(shí)現(xiàn)文本的處理。
- 編譯器:將預(yù)處理后的.i文件轉(zhuǎn)換成匯編程序。編譯器將不同的高級(jí)語言(如c語言,C++語言)轉(zhuǎn)換成嚴(yán)格一致的匯編語言格式進(jìn)行輸出。匯編語言以標(biāo)準(zhǔn)的文本格式確切的描述每機(jī)器語言指令。編譯器得到的文件通常以.s為后綴保存。
- 匯編器:將匯編語言(.s文件)翻譯成機(jī)器語言指令,并將這些指令打包成一種可定位目標(biāo)程序格式。匯編后得到的文件即為二進(jìn)制文件,通常以.o為后綴。
- 鏈接器:Hello, World程序中調(diào)用過printf函數(shù),它是一個(gè)c標(biāo)準(zhǔn)庫里的函數(shù)。Printf函數(shù)存放在一個(gè)名為printf.o的單獨(dú)預(yù)編譯的文件中。而這個(gè)文件必須以適當(dāng)?shù)姆绞讲⑷氲轿覀兊某绦蛑?,這個(gè)工作由鏈接器完成。將外部的.o文件并入后,得到一個(gè)完整的hello, world可執(zhí)行文件。可執(zhí)行文件加載到存儲(chǔ)器后,由系統(tǒng)復(fù)制執(zhí)行。
程序加載進(jìn)入CPU的過程
Shell:命令行解釋器。當(dāng)用戶輸入一行命令后,shell先判斷它是不是一個(gè)shell內(nèi)置命令;如果不是,shell會(huì)假定為一個(gè)可執(zhí)行文件的名字,直接去加載并執(zhí)行該文件。因此,當(dāng)我們通過編譯系統(tǒng)將源文件編譯成可執(zhí)行二進(jìn)制文件后,在shell中輸入我們得到的可執(zhí)行二進(jìn)制文件名,shell將其從磁盤中加載到主存當(dāng)中,通過CPU進(jìn)行解釋運(yùn)行,最終通過終端設(shè)備(屏幕)將他顯示出來,程序運(yùn)行結(jié)束。
主內(nèi)存對(duì)指令的處理分為多級(jí)緩存,其中比較重要的就是各類寄存器。寄存器是中央處理器內(nèi)主要組成結(jié)構(gòu)成分,它是CPU當(dāng)中有限存貯容量的高速存貯部件,它在工作時(shí)能將計(jì)算機(jī)指令數(shù)據(jù)進(jìn)行暫時(shí)的存儲(chǔ)。
內(nèi)存地址=基質(zhì)+變址
CPU中的主要寄存器:
- 累加寄存器(AC) :主要進(jìn)行加法運(yùn)算。
- 標(biāo)志寄存器(PSW) :記錄狀態(tài),做邏輯運(yùn)算。
- 程序計(jì)數(shù)器(PC) :是用于存放下一條指令所在單元的地址的地方。
- 基質(zhì)寄存器(BX) :儲(chǔ)存當(dāng)前數(shù)據(jù)內(nèi)存開始的位置。
- 變址寄存器 :儲(chǔ)存基質(zhì)寄存器的相對(duì)位置。
- 通用寄存器(GPRs) :支持有所的用法。
- 指令寄存器(IR) :CPU專用,儲(chǔ)存指令。
- 堆棧寄存器(SP) :記錄堆棧的起始位置。
處理器讀取并解釋存儲(chǔ)在存儲(chǔ)器中的指令處理器的操作主要是圍繞程序計(jì)數(shù)器、算術(shù)/邏輯運(yùn)算單元、主存來進(jìn)行運(yùn)作的。處理器首先從PC所指向的主存存儲(chǔ)單元讀取指令,解釋指令中的位,執(zhí)行該指令指示的簡單操作,然后更新PC寄存器,使其指向下一條要執(zhí)行的指令。CPU會(huì)執(zhí)行的操作有:
加載:把一個(gè)字節(jié)或一個(gè)字從主存復(fù)制到寄存器,覆蓋掉寄存器中原來的值。
存儲(chǔ):把一個(gè)字節(jié)或一個(gè)從寄存器復(fù)制到主存,并覆蓋主存中原來的值。
操作:把兩個(gè)寄存器的內(nèi)容復(fù)制到ALU,ALU對(duì)兩個(gè)字做算術(shù)運(yùn)算后存回其中的一個(gè)寄存器,該寄存器中原來的值會(huì)被覆蓋。
跳轉(zhuǎn):從cpu執(zhí)行的指令抽取一個(gè)字的內(nèi)容存入PC,覆蓋掉原來的值,從而改變下一條要執(zhí)行的指令,達(dá)到跳轉(zhuǎn)的目的。
Hello,World程序首先被加載,從磁盤中復(fù)制到寄存器中,寄存器將Hello,World程序復(fù)制到主存中進(jìn)行存儲(chǔ)。程序運(yùn)行過程中,CPU執(zhí)行Hellow,World機(jī)器指令,指令的結(jié)果是將”Hellow,World”字符由內(nèi)存復(fù)制到寄存器,寄存器再將結(jié)果復(fù)制到顯示設(shè)備上顯示出來。
下面我們?cè)敿?xì)的給出一個(gè)代碼段在內(nèi)存中的存儲(chǔ)示意圖。
更多詳細(xì)信息,請(qǐng)您微信關(guān)注“計(jì)算網(wǎng)”公眾號(hào):