日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

hello world漫游

發(fā)布時(shí)間:2023/12/8 编程问答 26 豆豆
生活随笔 收集整理的這篇文章主要介紹了 hello world漫游 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

Hello world漫游

在進(jìn)入我們今天的主題之前,我想回顧一下馮諾依曼體系結(jié)構(gòu)以及存儲(chǔ)程序思想。太經(jīng)典了!
1計(jì)算機(jī)是由運(yùn)算器,控制器,存儲(chǔ)器,輸入輸出設(shè)備五部分組成
2采用存儲(chǔ)程序的方式,要執(zhí)行的程序和數(shù)據(jù)先放到存儲(chǔ)器中
3采用二進(jìn)制編碼數(shù)據(jù)
4程序是指令的集合,指令在存儲(chǔ)器中按執(zhí)行順序存放

回到我們今天的hello world漫游,下面是我們要重點(diǎn)討論的部分,如果你確實(shí)看不下去,那么你也可以跳躍式閱讀。
1操作系統(tǒng)的啟動(dòng)
2信息的表示
3程序的編寫(xiě)
4 I/O設(shè)備的控制
5程序性能優(yōu)化
6程序的編譯與鏈接
7存儲(chǔ)器層次結(jié)構(gòu)以及虛擬存儲(chǔ)技術(shù)
8進(jìn)程與異常控制流
9指令系統(tǒng)
10指令在硬件上執(zhí)行
1:操作系統(tǒng)的啟動(dòng)
首先在我們漫游之前,讓我們開(kāi)啟我們的計(jì)算機(jī),啟動(dòng)操作系統(tǒng),為hello world提供生存環(huán)境。操作系統(tǒng)的啟動(dòng)過(guò)程主要是下面幾步,至于為什么我要介紹操作系統(tǒng)的啟動(dòng),接著往下看就明白了。

網(wǎng)上有很多詳細(xì)的介紹,具體可以參考下面鏈接,我不再詳述。
http://blog.chinaunix.net/uid-23069658-id-3142047.html

2信息的表示
Hello world 的生命周期可以說(shuō)是從源程序的產(chǎn)生開(kāi)始,說(shuō)到源程序我們必須先對(duì)源程序有一個(gè)基本概念—信息。信息就是位+上下文(深入理解計(jì)算機(jī)系統(tǒng)),在計(jì)算機(jī)系統(tǒng)中信息是用位和上下文來(lái)表示的。以文件形式存在于磁盤(pán)上,包括.txt .cpp .asm .obj…。其中文件主要包括文本文件和二進(jìn)制文件,可以這么理解,和計(jì)算機(jī)打交道的是二進(jìn)制文件,和我們打交道的是文本文件。二進(jìn)制文件就是由一串二進(jìn)制位0和1來(lái)表示的。對(duì)于這樣的0和1我們是不怎么喜歡看的了。為了讓我們更簡(jiǎn)單明了的看到計(jì)算機(jī)中的信息,計(jì)算機(jī)大牛們就想出了一個(gè)很巧妙的辦法來(lái)實(shí)現(xiàn)人機(jī)交互的問(wèn)題。那就是編碼,對(duì)一串二進(jìn)制位0和1進(jìn)行編碼,常見(jiàn)的有ascii,unicode,gb2312…。也就是通過(guò)一串0和1來(lái)表示成我們能看的懂的信息。例如ascii中,用二進(jìn)制的65D 0010 0001B表示大寫(xiě)字母A,unicode中用\u6b22\u8fce表示中文 ”歡迎”。

編碼是很神奇的一步,也是實(shí)現(xiàn)人機(jī)交互很重要的一步,下面有興趣的同學(xué)可以繼續(xù)深入了解其他信息的表示方式和處理,如整數(shù),浮點(diǎn)數(shù),運(yùn)算。說(shuō)到數(shù)的表示,在計(jì)算機(jī)中同樣也可以理解為是一個(gè)編碼的過(guò)程。就如我們常說(shuō)的,原碼,反碼,補(bǔ)碼一樣。想想我們平時(shí)使用的十進(jìn)制原來(lái)也是一個(gè)編碼的過(guò)程啊,只是我們沒(méi)有過(guò)多想過(guò)這個(gè)問(wèn)題,只是欣然的接收了而已,哈哈!

下面就簡(jiǎn)單介紹下計(jì)算機(jī)中整數(shù),浮點(diǎn)數(shù),以及他們的運(yùn)算問(wèn)題。常見(jiàn)的數(shù)進(jìn)制有二進(jìn)制,八進(jìn)制,十進(jìn)制,十六進(jìn)制,當(dāng)然他們之間的轉(zhuǎn)換我就不作介紹了。我們生活中通常使用十進(jìn)制,而計(jì)算機(jī)中使用二進(jìn)制,但是考慮到十進(jìn)制和二進(jìn)制之間轉(zhuǎn)換的不易性。我們程序員在計(jì)算機(jī)表示中常用十六進(jìn)制,如地址的表示我們不會(huì)用一長(zhǎng)串0和1來(lái)表示,也不會(huì)用十進(jìn)制表示,我們通常會(huì)用0XFFFF來(lái)表示。下面是C語(yǔ)言中常見(jiàn)的數(shù)據(jù)類(lèi)型以及他的表示范圍。當(dāng)然,不同計(jì)算機(jī)系統(tǒng),對(duì)數(shù)據(jù)類(lèi)型所占的字節(jié)數(shù)有所不同,但總是二進(jìn)制表示的形式。

說(shuō)到這里,對(duì)于一個(gè)稱(chēng)職的程序員,我想有必要了解的就是,數(shù)據(jù)類(lèi)型之間的轉(zhuǎn)換問(wèn)題,
關(guān)于這個(gè)問(wèn)題,我想最根本的解釋就是回到他們的二進(jìn)制表示形式以及定義上來(lái)理解。下面就介紹強(qiáng)制類(lèi)型轉(zhuǎn)化和截?cái)鄶?shù)字的準(zhǔn)則。
1對(duì)于位不同的類(lèi)型之間的轉(zhuǎn)換,就是對(duì)數(shù)據(jù)的位進(jìn)行擴(kuò)充或者截?cái)?#xff0c;當(dāng)然擴(kuò)充的方式需要根據(jù)數(shù)據(jù)的定義,有的是前補(bǔ)0,有的是前補(bǔ)符號(hào)位,截?cái)嗑褪潜A魯?shù)據(jù)的低有效位。

2對(duì)于位相同的類(lèi)型之間的轉(zhuǎn)換,就是根據(jù)數(shù)據(jù)類(lèi)型的定義來(lái)重新解釋該數(shù)據(jù)(無(wú)符號(hào)數(shù))。

數(shù)據(jù)的機(jī)器級(jí)表示中有大端對(duì)其和小端對(duì)其,這里需要注意的就是,小端法(高有效位放在地地址)大端法(高有效位放在地址),下面是1234H在不同機(jī)器下的表示。

s為符號(hào)位,表示正負(fù)
f為尾數(shù),f是二進(jìn)制小數(shù),表示為0.的形式
e為階碼,e采用無(wú)符號(hào)數(shù)表示
IEEE浮點(diǎn)數(shù)表示有幾種情況:規(guī)格化,非規(guī)格化,特殊值
1規(guī)格化:e不全為0,也不全為1
S=s,M=1+f,E=e-Bias(單精度Bias為127,雙精度為1023)
那么 就等于
2非規(guī)格化:e全為0
S=s,M=f,E=1-Bias,換種理解,M=1+f,E=e-Bias也是一樣,問(wèn)題的關(guān)鍵是保證數(shù)的連續(xù)性
那么 就等于
3特殊值:e全為1,表示值為無(wú)窮大,NAN

關(guān)于數(shù)的運(yùn)算(算術(shù)運(yùn)算,邏輯運(yùn)算,關(guān)系運(yùn)算,位運(yùn)算),當(dāng)然和我們生活中數(shù)的運(yùn)算一樣,只是在計(jì)算機(jī)中同樣是采用二進(jìn)制數(shù)運(yùn)算,作為程序員,我們更關(guān)心的是如何安全,高效的進(jìn)行運(yùn)算。
1:有符號(hào)數(shù)和無(wú)符號(hào)數(shù)進(jìn)行運(yùn)算時(shí),隱式轉(zhuǎn)換為無(wú)符號(hào)數(shù)對(duì)待
浮點(diǎn)數(shù)與整數(shù)進(jìn)行運(yùn)算時(shí),隱式轉(zhuǎn)換為浮點(diǎn)數(shù)對(duì)待
2:乘法和除法運(yùn)算,為了簡(jiǎn)化運(yùn)算時(shí)間,常轉(zhuǎn)換為位運(yùn)算來(lái)代替
3:有符號(hào)數(shù)采用的是算術(shù)右移和無(wú)符號(hào)數(shù)采用的是邏輯右移

1有符號(hào)數(shù)和無(wú)符號(hào)數(shù)比較求值

2整數(shù)乘除轉(zhuǎn)位運(yùn)算
如x*14表示為(x<<3)+(x<<2)+(x<<1)
3帶符號(hào)數(shù)的算術(shù)右移操作

(x<0? (x+(1<<k)-1):x)>>k

好了,有了上面的編碼基礎(chǔ),我們可以開(kāi)始進(jìn)行hello world源文件的編輯了。

3:hello world編輯
說(shuō)到編寫(xiě)源程序,我想大家一定會(huì)第一時(shí)間打開(kāi)一個(gè)熟悉的編輯器,然后用不到幾十秒的時(shí)間寫(xiě)出hello world代碼,接著編譯運(yùn)行。然而很可惜的就是現(xiàn)在確實(shí)有那么些“程序員”只是在做這一部分工作,真是名副其實(shí)的“碼農(nóng)”。今天,我想簡(jiǎn)單從硬件角度介紹編輯源文件的問(wèn)題,這也就是我為什么已開(kāi)啟要介紹操作系統(tǒng)啟動(dòng)的原因,因?yàn)橹挥胁僮飨到y(tǒng)啟動(dòng)后,我們才能更好的通過(guò)操作系統(tǒng)來(lái)管理我們的硬件資源以及我們的應(yīng)用程序。當(dāng)我們打開(kāi)一個(gè)編輯器時(shí),實(shí)際上是在執(zhí)行一個(gè)應(yīng)用程序,操作系統(tǒng)會(huì)為這個(gè)程序創(chuàng)建進(jìn)程,通過(guò)進(jìn)程來(lái)管理我們的編輯文本文件時(shí)執(zhí)行的操作。也就是說(shuō)進(jìn)程在等待I/O設(shè)備。當(dāng)我敲擊鍵盤(pán)時(shí)很快會(huì)在編輯器行顯示如下源文件。但是硬件上,我們是怎么實(shí)現(xiàn)源文件的編輯的呢,接著往下看。

4:I/O控制方式
為了理解進(jìn)程與I/O設(shè)備的數(shù)據(jù)交流,我們有必要先了解 I/O接口(適配器)。對(duì)于I/O接口,我們可以采用內(nèi)存一樣的對(duì)其進(jìn)行編址,編址方式可以采用I/O獨(dú)立編址,也可以與主存一起進(jìn)行統(tǒng)一編址。編址之后,我們就通過(guò)I/O接口來(lái)訪問(wèn)控制I/O設(shè)備。我們就能像訪問(wèn)地址一樣的來(lái)訪問(wèn)I/O設(shè)備,講到后面的文件系統(tǒng)之后,我們也可以把I/O設(shè)備看作設(shè)備文件。對(duì)I/O設(shè)備的操作就好像是對(duì)文件操作一樣。

1 程序查詢式
通過(guò)程序指令不斷的去查詢?cè)O(shè)備是否準(zhǔn)備輸入/輸出數(shù)據(jù),這對(duì)cpu來(lái)說(shuō)是極大的浪費(fèi)時(shí)間。多說(shuō)無(wú)用!

2中斷

中斷是控制I/O設(shè)備的一個(gè)很重要的方式,同樣是一個(gè)非常值得借鑒的控制機(jī)制。講到中斷,我們先來(lái)了解下8088的中斷系統(tǒng)

其中,中斷的實(shí)現(xiàn)是通過(guò)8259A芯片硬件上來(lái)實(shí)現(xiàn)的,但中斷的管理也需要操作系統(tǒng)來(lái)實(shí)現(xiàn)。至于中斷嵌套可以自行看微機(jī)原理書(shū)。中斷包括硬件中斷和軟中斷,可屏蔽中斷和不可屏蔽中斷。需要注意的是中斷是一種機(jī)制,而異常,更非錯(cuò)誤。當(dāng)外設(shè)向cpu發(fā)出請(qǐng)求時(shí),會(huì)在8259A芯片上產(chǎn)生一個(gè)中斷信號(hào)。cpu通過(guò)中斷邏輯得到中斷向量號(hào),然后去訪問(wèn)中斷向量表得到中斷處理程序的入口地址,在系統(tǒng)啟動(dòng)后,中斷向量表存放在主存的從0000H—03FEH地址(8088),共255個(gè)中斷。由于中斷向量地址占4個(gè)字節(jié),而中斷向量號(hào)是按序存放的,所以中斷向量地址也等于4*中斷向量號(hào)。

中斷響應(yīng)過(guò)程(同jmp指令執(zhí)行過(guò)程比較類(lèi)似,至于保護(hù)現(xiàn)場(chǎng)和恢復(fù)現(xiàn)場(chǎng)只是一種簡(jiǎn)單的描述,不過(guò)就是些寄存器狀態(tài)的保存,當(dāng)然還是挺麻煩的),中斷處理過(guò)程的示意圖如下:

有了中斷控制方式,cpu就不用不斷的去查詢等待外設(shè)是否處于準(zhǔn)備狀態(tài),而是外設(shè)通過(guò)中斷來(lái)請(qǐng)求cpu了,但是考慮到外設(shè)每一次請(qǐng)求cpu就中斷一次的話,cpu需要的代價(jià)很大,不僅要停下來(lái)而且要保存現(xiàn)場(chǎng),然后去執(zhí)行中斷,最后恢復(fù)現(xiàn)場(chǎng),才能繼續(xù)工作。所以又有了下面的DMA控制方式。

3 DMA控制方式
DMA全稱(chēng)direct memory access也就是是直接在內(nèi)存與I/O直接建立聯(lián)系,每次DMA先緩存一定量的數(shù)據(jù)塊,然后當(dāng)數(shù)據(jù)塊滿了之后,向cpu申請(qǐng)占用總線,這時(shí)DMA直接讀寫(xiě)內(nèi)存,控制I/O與內(nèi)存的操作,這樣就大大減少中斷的次數(shù),提高了cpu的利用率。

4通道控制方式
通道控制方式同樣是采用硬件來(lái)實(shí)現(xiàn)的,采用I/O通道控制器,相對(duì)于DMA來(lái)說(shuō),通道控制器是一個(gè)簡(jiǎn)易的處理器,能執(zhí)行有限的指令集,能控制數(shù)據(jù)傳送的方式,如字節(jié)多路通道,選擇通道,數(shù)組多路通道。

5 思考
關(guān)于I/O設(shè)備基本概念就介紹這些,相信大家都有一定的理解。下面回想我們hello world的編輯,如果從根本出發(fā),只要我們認(rèn)為我們敲進(jìn)去的不是鍵盤(pán)上的26個(gè)英文字母,而是敲進(jìn)去一個(gè)中斷信號(hào),然后程序調(diào)用中斷程序執(zhí)行相應(yīng)的中斷程序,我們的一切行為都是在為程序服務(wù),是程序?yàn)槲覀冊(cè)诖疟P(pán)上創(chuàng)建文件,編輯文件,保存文件就ok了,同樣需要注意的我們的源文件是以ascii碼的形式保存的。好了,編輯完hello world源文件之后,我們就可以開(kāi)始編譯運(yùn)行了,相信很多C教材都是這么說(shuō)的,但是作為程序員很有必要了解這個(gè)過(guò)程,因?yàn)樵谝院蟮墓ぷ髦?#xff0c;我們經(jīng)常會(huì)遇到類(lèi)似的問(wèn)題,我們常常會(huì)認(rèn)為程序沒(méi)有問(wèn)題,但是卻編譯不成功,或者是編譯不報(bào)錯(cuò),但運(yùn)行不起來(lái),類(lèi)似的問(wèn)題會(huì)讓我們頭痛不以,下面我們就慢慢的理解編譯鏈接的整個(gè)過(guò)程。

5:hello world的編譯與鏈接

1 預(yù)處理,把C語(yǔ)言中的一些預(yù)處理語(yǔ)句解釋出來(lái),如#include,#define ifdef,也就是宏定義,文件包含,條件編譯。執(zhí)行cpp命令,會(huì)在當(dāng)前目錄下產(chǎn)生test.i文件,查看文件可以看出預(yù)處理所做的工作。我們會(huì)發(fā)現(xiàn)test.i文件里面引入了很多我們沒(méi)有編輯過(guò)的代碼。

2 編譯
說(shuō)到編譯,就是把C語(yǔ)言程序編譯成匯編代碼。那么我們還是要有一定的匯編語(yǔ)言基礎(chǔ),至少能看懂匯編代碼。當(dāng)然,我們所學(xué)的匯編是inter匯編,與編譯器匯編出來(lái)的匯編指令語(yǔ)法不同,但是還是可以相通的,如果你還是很遺憾的說(shuō),匯編我都幾年沒(méi)用了,差不多都忘了,那也沒(méi)關(guān)系,下面一張常用匯編程序格式能給你簡(jiǎn)單的回憶(這里我省去了宏,條件編譯等)。

data segment commom;不同模塊下同名段連接,即在同一模塊下dataname dw 20 dup(1,?)array dw 1,2,$+2,4,$+8 ;$表示當(dāng)前地址計(jì)數(shù)器sp的值org 0020h ;使下一偏移地址從0020h開(kāi)始even ;下一地址從偶地址開(kāi)始 data ends;------------------------------------------------------- code segment main proc farassume cs:code,ds:data start:push dssub ax,axpush axmov ax,data;把data的數(shù)據(jù)段地址給axmov dx,axmov ax,dataname ;把dataname數(shù)據(jù)給axmov ax,offset dataname;把data的地址給axmov ax,es:[di] ;默認(rèn)es和di連用mov ax,ds:table[si][bx] ;ds默認(rèn)和si連用,相對(duì)基址變址尋址call suncall far prt extern_sunjmp startmov dl,1hmov ah,displayint 21hretmain endp;--------------------------------------------------------sun proc near..retsun endp code endsend start

看完上面的匯編程序的一般格式后,默認(rèn)大家對(duì)匯編有一定的理解,至少能看明白。畢竟我們確實(shí)很少會(huì)再去寫(xiě)匯編代碼了。然而不得不說(shuō)的是匯編語(yǔ)言確實(shí)很強(qiáng)大,而且很危險(xiǎn),然后我只想對(duì)早期的程序員說(shuō),你們真的辛苦了,匯編代碼真難調(diào)試!!!

下面我們來(lái)對(duì)比一下,匯編語(yǔ)言寫(xiě)的hello world,和C語(yǔ)言經(jīng)過(guò)編譯后的hello world有什么不一樣

C語(yǔ)言版

匯編語(yǔ)言版

對(duì)比C語(yǔ)言匯編得到的匯編代碼和直接用匯編語(yǔ)言寫(xiě)的代碼,我們發(fā)現(xiàn)兩者之間非常相似,但又有不同。其中我們注意到的是,C語(yǔ)言匯編后的代碼有很多.file .def類(lèi)的標(biāo)識(shí),這些我們可以暫時(shí)理解為是匯編器產(chǎn)生的一種標(biāo)識(shí),方便后面進(jìn)行鏈接用的。還有一個(gè)就是_call _printf的調(diào)用,這個(gè)我們暫時(shí)理解為是對(duì)函數(shù)庫(kù)的一個(gè)調(diào)用,在鏈接過(guò)程中繼續(xù)討論。可以看得出他們之間很類(lèi)似,雖然目前看他們輸出字符串執(zhí)行的命令不同。


既然談到C語(yǔ)言和匯編,那就不可避免的得說(shuō)一下棧的問(wèn)題。因?yàn)镃語(yǔ)言中的控制,函數(shù)調(diào)用同匯編中的過(guò)程控制都需要運(yùn)用到棧。棧的一個(gè)基本思想就是先進(jìn)后出。為了更好的理解C語(yǔ)言中函數(shù)的遞歸調(diào)用,我們這里用匯編語(yǔ)言來(lái)描述它對(duì)棧操作過(guò)程。

C語(yǔ)言實(shí)現(xiàn)代碼:

#include <stdio.h> int fu(int x) {if(x<1)return 1;elsereturn fu(x-2)+fu(x-1); } int main() {int x;fu(x);return 0; }

機(jī)器反匯編代碼:(每一步的執(zhí)行都對(duì)應(yīng)一條匯編指令,真正用匯編語(yǔ)言實(shí)現(xiàn)不用如此麻煩,因?yàn)?#xff0c;匯編語(yǔ)言也支持選擇,循環(huán),調(diào)用)

00401020 push %ebp 00401021 mov %esp,%ebp 00401023 push %ebx 00401024 sub $0x34,%esp 00401027 movl $0x401150,(%esp) 0040102E call 0x4019b4 <SetUnhandledExceptionFilter@4> 00401033 sub $0x4,%esp 00401036 call 0x401360 <__cpu_features_init> 0040103B call 0x401770 <fpreset> 00401040 lea -0x10(%ebp),%eax 00401043 movl $0x0,-0x10(%ebp) 0040104A mov %eax,0x10(%esp) 0040104E mov 0x402000,%eax 00401053 movl $0x404004,0x4(%esp) 0040105B movl $0x404000,(%esp) 00401062 mov %eax,0xc(%esp) 00401066 lea -0xc(%ebp),%eax 00401069 mov %eax,0x8(%esp) 0040106D call 0x40195c <__getmainargs> 00401072 mov 0x404008,%eax 00401077 test %eax,%eax 00401079 jne 0x4010c5 <__mingw_CRTStartup+165> 0040107B call 0x401964 <__p__fmode> 00401080 mov 0x402004,%edx 00401086 mov %edx,(%eax) 00401088 call 0x401520 <_pei386_runtime_relocator> 0040108D and $0xfffffff0,%esp 00401090 call 0x401750 <__main> 00401095 call 0x40196c <__p__environ> 0040109A mov (%eax),%eax 0040109C mov %eax,0x8(%esp) 004010A0 mov 0x404004,%eax 004010A5 mov %eax,0x4(%esp) 004010A9 mov 0x404000,%eax 004010AE mov %eax,(%esp) 004010B1 call 0x40134d <main> 004010B6 mov %eax,%ebx 004010B8 call 0x401974 <_cexit> 004010BD mov %ebx,(%esp) 004010C0 call 0x4019bc <ExitProcess@4> 004010C5 mov 0x4050f4,%ebx 004010CB mov %eax,0x402004 004010D0 mov %eax,0x4(%esp) 004010D4 mov 0x10(%ebx),%eax 004010D7 mov %eax,(%esp) 004010DA call 0x40197c <_setmode> 004010DF mov 0x404008,%eax 004010E4 mov %eax,0x4(%esp) 004010E8 mov 0x30(%ebx),%eax 004010EB mov %eax,(%esp) 004010EE call 0x40197c <_setmode> 004010F3 mov 0x404008,%eax 004010F8 mov %eax,0x4(%esp) 004010FC mov 0x50(%ebx),%eax 004010FF mov %eax,(%esp) 00401102 call 0x40197c <_setmode> 00401107 jmp 0x40107b <__mingw_CRTStartup+91> 0040110C lea 0x0(%esi,%eiz,1),%esi

匯編語(yǔ)言實(shí)現(xiàn)代碼:

``` code segment;主程序main proc farassume cs:code start:mov ax,0 ;ax存儲(chǔ)函數(shù)值,清零mov bx,8 ;設(shè)置函數(shù)xpush bx ;參數(shù)壓棧call digui ;ip壓棧 retmain endp;遞歸子程序digui proc near push bp mov bp,sppush dx ;保存和的后一個(gè)加數(shù)push bxsub sp,2mov bx,(bp+4)cmp bx,2je out1cmp bx,1je out1sub bx,1mov (bp-6),bxcall diguimov dx,ax ;將和的第一個(gè)加數(shù)保存到dx,去計(jì)算后一個(gè)加數(shù)dec bx ;求f(n-2)push bxcall diguipop bx ;清空nadd ax,dx ;將第二個(gè)加數(shù)加到第一個(gè)加數(shù)上,即求和jmp out2 ;作為第二個(gè)加數(shù)的參數(shù)壓棧out1:mov ax,1 out2:add sp,2pop bxpop dxpop bpretdigui endp code endsend main


由此,我們可以看出函數(shù)的遞歸調(diào)用就是一個(gè)壓棧的過(guò)程,先把一些需要保存的寄存器壓棧,再把參數(shù)壓棧,壓棧順序?yàn)橹劣蚁蜃?#xff0c;最后是是返回地址壓棧,直到函數(shù)執(zhí)行return返回,返回即對(duì)應(yīng)一次出棧操作。同樣,我們可以看出匯編語(yǔ)言實(shí)現(xiàn)的麻煩,我們必須清楚的知道棧里面的情況,想想要是程序員一不下心搞錯(cuò)了怎么辦?哈哈,這就引出我們編程上的數(shù)組越界和緩沖區(qū)溢出問(wèn)題了。當(dāng)程序的返回地址CS:IP被惡意修改,那么程序就會(huì)轉(zhuǎn)而去執(zhí)行一段我們并不知道的程序,當(dāng)這段程序是攻擊性程序的話,那么我們就麻煩了。當(dāng)然現(xiàn)在的操作系統(tǒng)已經(jīng)對(duì)此類(lèi)問(wèn)題又了很強(qiáng)的保護(hù)。所以說(shuō)匯編語(yǔ)言是很強(qiáng)大,但也很危險(xiǎn)的!

3 匯編
匯編是一個(gè)將匯編語(yǔ)言文件匯編成二進(jìn)制文件的一個(gè)過(guò)程。這里我們?cè)賮?lái)看看匯編后的二進(jìn)制文件,由于二進(jìn)制文件不能直接打開(kāi),但是我們可以看到下面的東西:先匯編產(chǎn)生二進(jìn)制文件,然后反匯編得到一個(gè)類(lèi)似于.Lst的文件,其中左邊是對(duì)應(yīng)的二進(jìn)制機(jī)器碼,右邊為匯編代碼。

下面是匯編語(yǔ)言產(chǎn)生的.Lst文件,左邊為機(jī)器碼,右邊為匯編代碼

從上面二個(gè)文件中可以看出,C語(yǔ)言匯編后的二進(jìn)制代碼和匯編語(yǔ)言的代碼很相似,唯一不同還是C語(yǔ)言的匯編代碼時(shí)通過(guò)_printf輸出hello world,而匯編語(yǔ)言是通過(guò)dos中斷 int 21來(lái)實(shí)現(xiàn)輸出hello world。_printf調(diào)用來(lái)哦什么呢,下面就讓鏈接的解釋問(wèn)題吧。

4鏈接
想想,計(jì)算機(jī)能識(shí)別就是二進(jìn)制文件,既然有了二進(jìn)制文件,怎么還不能執(zhí)行呢。對(duì)的,我們還不能執(zhí)行,因?yàn)樵诖酥?#xff0c;我們還有很重要,很關(guān)鍵的事要做–鏈接。通常我們的程序都是分模塊的,就好像我們的.c中需要.h頭文件一樣。我們把各個(gè)功能模塊分開(kāi)來(lái),把一些大部分程序要用到的功能段都放到.h文件中,這樣,其他的c文件想用的時(shí)候都可以把他include進(jìn)來(lái)。然而對(duì)于可執(zhí)行文件也是一樣,我們也可以把一些大部分可執(zhí)行文件需要用到的功能放到一個(gè)靜態(tài)庫(kù),動(dòng)態(tài)庫(kù)中,就好像一個(gè)模塊一樣,即插即用。我們常用的有靜態(tài)鏈接庫(kù).a,和動(dòng)態(tài)鏈接庫(kù).dll。

例如,我們?cè)诰幊踢^(guò)程中常遇到需要使用庫(kù)函數(shù)的問(wèn)題,我們通常是采用include把需要的庫(kù)函數(shù)加載到我們的源文件中。那么編譯,鏈接后得到的可執(zhí)行文件中就包括了我們需要的庫(kù)函數(shù)。但是有個(gè)問(wèn)題我們得想清楚,include加載到源程序中不僅加載了我們需要的函數(shù),還包括很多其他功能實(shí)現(xiàn),盡管這樣不會(huì)增加我們.c文件的大小,但是它會(huì)大大增加編譯鏈接后得到的可執(zhí)行文件的大小,這樣不僅浪費(fèi)了磁盤(pán)存儲(chǔ),更可怕的是他加載到內(nèi)存中后,對(duì)內(nèi)存是一種極大的浪費(fèi)。考慮到上面的兩個(gè)問(wèn)題,鏈接部分完美的解決了這兩個(gè)問(wèn)題。
靜態(tài)鏈接.a,它是可重定位目標(biāo)文件,采用下面的命令,我們同樣可以得到我們想要的可執(zhí)行文件,而不需要把不需要的功能實(shí)現(xiàn)加載到可執(zhí)行文件中,這樣就解決了磁盤(pán)存儲(chǔ)的浪費(fèi)。

動(dòng)態(tài)鏈接.dll,他是共享目標(biāo)文件,他可以加載到任意的內(nèi)存地址,并和一個(gè)在內(nèi)存中運(yùn)行的程序鏈接起來(lái),也就是說(shuō)多個(gè)程序在運(yùn)行時(shí)可以共享這個(gè)功能實(shí)現(xiàn)。這樣它在內(nèi)存中就不需要拷貝多份而浪費(fèi)內(nèi)存了,如printf。

那么,就會(huì)有同學(xué)會(huì)說(shuō),那為什么我們還是要用include stdio.h,下面是我的一個(gè)嘗試,把它去掉后,程序會(huì)出現(xiàn)警告,但還是可以正常運(yùn)行,說(shuō)明在我的系統(tǒng)路徑下一定有一個(gè)包含printf的動(dòng)態(tài)鏈接.dll文件。

但是我們別喜過(guò)了,鏈接是給我們帶來(lái)了很大的方便,但要真的實(shí)現(xiàn)即插即用真的就這么簡(jiǎn)單嗎,多個(gè)目標(biāo)文件是怎么鏈接的,怎么插入的,并非是簡(jiǎn)單的插入進(jìn)去就行了。而是需要對(duì)文件的重整。下面我們介紹一下我們的目標(biāo)文件。

通常我們的目標(biāo)文件分為三類(lèi)

1 可重定位目標(biāo)文件
2可執(zhí)行目標(biāo)文件
3共享目標(biāo)文件

對(duì)于上面的目標(biāo)文件,都有一個(gè)典型的格式

我只簡(jiǎn)單介紹幾個(gè)節(jié)的含義

.text: 已編譯的機(jī)器代碼
.rodata:只讀數(shù)據(jù)
.data: 已初始化的全局變量
.bss:未初始化的全局變量
.symtab: 符號(hào)表
.rel.text:鏈接器把這個(gè)目標(biāo)文件和其他目標(biāo)文件結(jié)合時(shí),需要修改這些位置。
.rel.data:

有了上面的一些節(jié)之后,我們就能把多個(gè)目標(biāo)文件鏈接到一個(gè)可執(zhí)行文件中去。為什么我們要這么做呢,其中最重要的就是實(shí)現(xiàn)指令的執(zhí)行順序的安排。這里我們提下后面要講的一個(gè)概念,就是虛擬地址。簡(jiǎn)單的理解虛擬地址對(duì)應(yīng)的是我們的磁盤(pán)地址。有了這個(gè)虛擬地址之后,我們就能合理的,有序的安排指令執(zhí)行順序。為了看看鏈接后的虛擬地址,我們采用反匯編來(lái)看看鏈接之后得到的文件和前面的匯編文件有什么不一樣。

反匯編鏈接后的可執(zhí)行文件得到的

直接反匯編二進(jìn)制文件得到的

對(duì)比上面的,我們能夠看到的就是他們的指令和機(jī)器代碼完全一樣,但是最左邊的地址不一樣,這也就是鏈接過(guò)程所做的事了,當(dāng)然,鏈接的代碼我只截取了一部分。

好了,終于講完了程序是怎么變成可執(zhí)行文件的了,看到這里,相信你對(duì)源程序的編輯,編譯,鏈接已經(jīng)有了自己的理解,一定也很累了。但是我們的漫游還沒(méi)結(jié)束,我們還需要深入計(jì)算機(jī)硬件,了解程序是怎么運(yùn)行的。不過(guò)在此之前,我們先了解下程序運(yùn)行的性能問(wèn)題,相信對(duì)自己嚴(yán)格要求的程序員一定會(huì)買(mǎi)一本代碼規(guī)范化編程的書(shū)籍好好的研究程序優(yōu)化問(wèn)題,但這里我只是簡(jiǎn)單說(shuō)下,緩解一下疲勞!

6:程序性能優(yōu)化

下面來(lái)看一看一個(gè)簡(jiǎn)單的數(shù)組求和問(wèn)題(下面是偽代碼)

下面是一個(gè)對(duì)結(jié)構(gòu)體數(shù)據(jù)求和的過(guò)程

消除循環(huán)的低效率

減少過(guò)程調(diào)用

消除不必要的存儲(chǔ)器的引用如函數(shù)傳遞的參數(shù)是放在存儲(chǔ)器的棧中的,而局部變量可以放在寄存器中,訪問(wèn)寄存器的速度明顯優(yōu)于存儲(chǔ)器
循環(huán)展開(kāi)

提高并行性等…下面我們進(jìn)入計(jì)算機(jī)硬件,了解計(jì)算機(jī)體系結(jié)構(gòu)。我們先看一張圖,大致了解一下計(jì)算機(jī)有哪些硬件組成。

7:存儲(chǔ)器層器結(jié)構(gòu)以及虛擬存儲(chǔ)技術(shù)

同樣在我們運(yùn)行可執(zhí)行文件之前,我們必須要清楚一個(gè)概念,因?yàn)榍懊嫖覀冋f(shuō)到過(guò)指令的執(zhí)行順序是很關(guān)鍵的,而我們使用的是虛擬地址,而不是真正的物理地址,執(zhí)行前必須虛擬地址轉(zhuǎn)換為物理地址之,那么或許這時(shí)你會(huì)想為什么我們不直接使用物理地址呢?我們不妨來(lái)看下那就是虛擬存儲(chǔ)器。下面就來(lái)介紹一下我們的存儲(chǔ)器層次結(jié)構(gòu)以及其中最重要虛擬存儲(chǔ)器。

關(guān)于各種類(lèi)型的存儲(chǔ)詳細(xì)介紹,可以百度!
下面介紹兩種DRAM的擴(kuò)展方式,位擴(kuò)展和字?jǐn)U展。

有了上面的這些存儲(chǔ)器之后,下面繼續(xù)介紹我們的存儲(chǔ)器層次結(jié)構(gòu)

為什存儲(chǔ)器采用如此多的層次結(jié)構(gòu),為什么采用緩存和虛擬存儲(chǔ)技術(shù),最根本的問(wèn)題就是解決cpu與存儲(chǔ)器之間速度不匹配的問(wèn)題,當(dāng)然還有擴(kuò)展存儲(chǔ)器大小的用途。也就是說(shuō),每一次cpu根據(jù)地址去訪問(wèn)存儲(chǔ)器時(shí),都是先訪問(wèn)更快但又容量極小的存儲(chǔ)器。如果不存在,則繼續(xù)往下找。那么關(guān)鍵的問(wèn)題就是高速緩存中能否找到cpu想要的指令或者數(shù)據(jù),而我們的操作系統(tǒng)會(huì)盡最大努力的提高命中率。但是很可惜的是,我們不能未卜先知,預(yù)測(cè)cpu下一個(gè)需要訪問(wèn)的地址。我們能做的就是先把最大可能訪問(wèn)的東西放到高速緩存中,然后提高cpu隨機(jī)訪問(wèn)命中的概率。但是幸運(yùn)的是我們的程序具有時(shí)間和空間上的局部性,這就大大提高了我們cpu訪問(wèn)緩存命中的概率。為了提高命中率,合理利用高速緩存空間就顯的十分重要了。硬件我們采用了各種存儲(chǔ)器映射方式,軟件上采用了各種的頁(yè)面置換算法。

存儲(chǔ)器映射方式
1全相連映射(不贅述)

2直接映射

3組相連映射

頁(yè)面置換算法(這里不過(guò)多介紹)
1先進(jìn)先出
2最近最久未使用
3clock置換

如果說(shuō)緩存是緩存主存到高速緩存的話,那么虛擬存儲(chǔ)器就是緩存磁盤(pán)到主存,前者主要加快了訪存的速度,那么后者就增大了主存的容量(虛擬內(nèi)存)。這就是虛擬存儲(chǔ)技術(shù),也就是為什么我們能運(yùn)行比我們內(nèi)存大的程序的原因,也是我們使用虛擬地址(邏輯地址)的原因。而且程序在很長(zhǎng)一段時(shí)間使用的都是虛擬地址,只有真正執(zhí)行的時(shí)候才會(huì)將虛擬地址轉(zhuǎn)變?yōu)閷?shí)際的物理地址,簡(jiǎn)單說(shuō)吧,虛擬地址就是映射到磁盤(pán)的地址,物理地址是映射到內(nèi)存的地址。那么讓我們的可執(zhí)行文件運(yùn)行起來(lái),還有很重要的一步就是虛擬地址到物理地址的轉(zhuǎn)換。
下面就介紹虛擬存儲(chǔ)器,解決虛擬地址到物理地址的映射問(wèn)題,當(dāng)然高速緩存的地址轉(zhuǎn)換也是類(lèi)似。虛擬地址翻譯,在進(jìn)行虛擬地址翻譯過(guò)程中需要用到一個(gè)頁(yè)表,該頁(yè)表是存放在內(nèi)存中的(物理存儲(chǔ)器),為了圖示,我把他單獨(dú)列出物理內(nèi)存。

從上面可以看出,頁(yè)表就是一個(gè)定位指令或數(shù)據(jù)地址的作用,有效位表示是否在物理存儲(chǔ)器中,為0表示不在,為null表示該頁(yè)表項(xiàng)未被使用,為1表示能在物理存儲(chǔ)器上找到。

考慮到虛擬存儲(chǔ)器很大的時(shí)候,假如64位,那么如果我們采用上面的映射方式一個(gè)頁(yè)表項(xiàng)對(duì)應(yīng)磁盤(pán)上4K大小。那么我們的頁(yè)表就需 s
可見(jiàn)這是不可能的。所以引出了多級(jí)頁(yè)表的方法來(lái)解決我們不斷擴(kuò)大的虛擬存儲(chǔ)器問(wèn)題。

也就是說(shuō)一級(jí)頁(yè)表負(fù)責(zé)映射虛擬存儲(chǔ)器上的4M地址空間,二級(jí)頁(yè)表繼續(xù)劃分這4M空間,負(fù)責(zé)映射4K地址空間。這樣大大減少來(lái)哦頁(yè)表的地址空間,但是不得不說(shuō)的是,增加了地址映射的復(fù)雜性。但這對(duì)高速的cpu來(lái)說(shuō)不是問(wèn)題,問(wèn)題是需要多訪問(wèn)一次物理內(nèi)存。好了,講完地址映射之后,我們終于可以把我們的程序裝載到內(nèi)存上運(yùn)行了。

8:進(jìn)程與異常控制流

程序需要運(yùn)行起來(lái),沒(méi)有操作系統(tǒng)是不行,因?yàn)椴僮飨到y(tǒng)管理著我們的硬件資源。在計(jì)算機(jī)系統(tǒng)下,提高系統(tǒng)的吞吐量是操作系統(tǒng)的一大職責(zé),早期的操作系統(tǒng)沒(méi)有過(guò)多的要求,只需要管理計(jì)算機(jī)硬件資源,保證有效性(提高資源利用率和系統(tǒng)吞吐量)即可,當(dāng)然操作系統(tǒng)的目標(biāo)有:有效性,方便性,可擴(kuò)充性,開(kāi)放性。所以早期的操作系統(tǒng)有單道批處理系統(tǒng),多道批處理系統(tǒng),分時(shí)系統(tǒng),實(shí)時(shí)系統(tǒng)。無(wú)論如何,操作系統(tǒng)的目標(biāo)就是上面幾個(gè)。由于程序不具備并發(fā)性,不能有效的利用計(jì)算機(jī)硬件資源,所以操作系統(tǒng)提出了進(jìn)程和線程的概念。進(jìn)程是一個(gè)抽象的概念,進(jìn)程是程序運(yùn)行的一個(gè)實(shí)例,也就是說(shuō),操作系統(tǒng)為了提高資源利用率,通過(guò)進(jìn)程來(lái)抽象的執(zhí)行程序。也就是說(shuō),我們的程序需要以進(jìn)程的形式才能運(yùn)行起來(lái)!
這里簡(jiǎn)單介紹一下進(jìn)程,每一個(gè)進(jìn)程都有唯一一個(gè)進(jìn)程標(biāo)識(shí)號(hào)PID。操作系統(tǒng)在初始化的時(shí)候,有一個(gè)pid為0號(hào)的進(jìn)程,它是所有進(jìn)程的父進(jìn)程。
操作系統(tǒng)會(huì)在下面幾種情況下創(chuàng)建進(jìn)程。

1用戶登入:合法用戶登入后,操作系統(tǒng)為該用戶終端創(chuàng)建一個(gè)進(jìn)程。
2作業(yè)調(diào)度:系統(tǒng)用來(lái)完成進(jìn)程調(diào)度的一種機(jī)制
3提供服務(wù):系統(tǒng)提供的一套為用戶進(jìn)程的服務(wù)
4應(yīng)用請(qǐng)求:應(yīng)用進(jìn)程申請(qǐng)創(chuàng)建一個(gè)進(jìn)程
前面3個(gè)都是系統(tǒng)創(chuàng)建新的進(jìn)程(內(nèi)核態(tài)),第4個(gè)是用戶創(chuàng)建進(jìn)程(用戶態(tài))

下面我們開(kāi)始運(yùn)行我們的hello world程序。

windows下我們執(zhí)行可執(zhí)行文件test.exe,當(dāng)然linux下是./test,但這不是問(wèn)題的關(guān)鍵。問(wèn)題的關(guān)鍵是運(yùn)行hello world時(shí)操作系統(tǒng)做了些什么?這直接關(guān)系到我們繼續(xù)了解程序運(yùn)行的實(shí)質(zhì)。當(dāng)我們?cè)诿畲翱趫?zhí)行test時(shí),因?yàn)閠est不是內(nèi)置的外殼命令,所以他會(huì)認(rèn)為test是一個(gè)可執(zhí)行文件,當(dāng)外殼運(yùn)行一個(gè)程序時(shí),父外殼進(jìn)程會(huì)調(diào)用fork()函數(shù)生成一個(gè)子進(jìn)程,內(nèi)核為新的子進(jìn)程創(chuàng)建各種數(shù)據(jù)結(jié)構(gòu),并分配唯一的PID,為了給子進(jìn)程創(chuàng)建虛擬存儲(chǔ)器(就是虛擬地址到物理地址的映射表)它創(chuàng)建與當(dāng)前進(jìn)程一樣的mm_struct,區(qū)域結(jié)構(gòu), 頁(yè)表的原樣拷貝。它是父進(jìn)程的一個(gè)復(fù)制品。子進(jìn)程通過(guò)調(diào)用execve系統(tǒng)調(diào)用啟動(dòng)加載器。加載器會(huì)刪除子進(jìn)程現(xiàn)有的虛擬存儲(chǔ)器,并創(chuàng)建一組新的代碼,數(shù)據(jù),堆,和棧。通過(guò)虛擬地址空間中的頁(yè)映射到可執(zhí)行文件的頁(yè)大小的片,新的代碼和數(shù)據(jù)段被初始化為可執(zhí)行文件的內(nèi)容,最后加載器跳到_strat地址,最終調(diào)用main函數(shù)。在加載過(guò)程中不會(huì)把程序的數(shù)據(jù)拷貝到存儲(chǔ)器,直到cpu引用一個(gè)虛擬頁(yè)面才進(jìn)行拷貝,此時(shí)利用的就是操作系統(tǒng)的頁(yè)面調(diào)度機(jī)制。關(guān)于fork和execve函數(shù)就不做過(guò)多介紹,有興趣同學(xué)可以自己查閱資料,看看這兩個(gè)函數(shù)的實(shí)現(xiàn)和作用。當(dāng)然,進(jìn)程運(yùn)行的過(guò)程并非總是一帆風(fēng)順的,操作系統(tǒng)也不會(huì)讓一個(gè)進(jìn)程一直占用cpu直到進(jìn)程結(jié)束。進(jìn)程運(yùn)行過(guò)程總會(huì)發(fā)生一些異常,注意異常不是錯(cuò)誤,可以理解為是一種機(jī)制。

異常的類(lèi)別有下面幾種
1中斷
2陷阱和系統(tǒng)調(diào)用
3故障
4終止
異常的機(jī)制和中斷類(lèi)似,也就是進(jìn)程執(zhí)行過(guò)程中,有其他更重要的事要做,cpu轉(zhuǎn)而做其他事情,實(shí)現(xiàn)機(jī)制也類(lèi)似,中斷有中斷向量表和中斷處理程序,異常有異常表和異常處理程序,尋址方式和中斷也類(lèi)似。所以進(jìn)程的執(zhí)行過(guò)程也可以用下面示意圖表示。

操作系統(tǒng)終于組織好我們的程序了,并以進(jìn)程的方式開(kāi)始運(yùn)行了。離我們真正的在硬件上分析指令的運(yùn)行就差最后一步了。

9指令系統(tǒng)

別忘了,我們的計(jì)算機(jī)可不認(rèn)識(shí)什么程序,進(jìn)程之類(lèi),計(jì)算機(jī)硬件只能識(shí)別0和1,不過(guò)幸運(yùn)的是我們的前面通過(guò)lst文件也看到匯編后的二進(jìn)制文件,左邊為機(jī)器碼,右邊為機(jī)器指令。所以這又是一個(gè)編碼的過(guò)程,也就是用一串0和1來(lái)編碼機(jī)器指令,我們只要知道指令系統(tǒng)的編碼規(guī)則就好,至于指令功能上的實(shí)現(xiàn),那是硬件上的問(wèn)題了。為了讓大家能記起我們的匯編代碼和機(jī)器碼,我再把之前的lst文件貼上,也方便介紹后面的指令系統(tǒng)和硬件執(zhí)行指令的過(guò)程。

下面是深入理解計(jì)算機(jī)系統(tǒng)書(shū)中定義的一套Y86指令集,就是用一串0和1組成的二進(jìn)制數(shù)代表一條指令。其實(shí)如果我們是搞硬件的話,我們也可以自己設(shè)計(jì)電路,定義一套簡(jiǎn)單的指令系統(tǒng)集。

當(dāng)然指令系統(tǒng)集的定義也必須合理安排,否則對(duì)硬件是一種極大的浪費(fèi)和損害上面定的Y86指令集是由1-6個(gè)字節(jié)進(jìn)行編碼的,也就是說(shuō)不是固定長(zhǎng)度編碼。不定長(zhǎng)編碼將會(huì)導(dǎo)致執(zhí)行不同的指令使用的總線數(shù)量不一致。下面是我們熟知的CISC和RISC指令系統(tǒng)集

10指令在硬件上執(zhí)行

有了指令系統(tǒng)之后,我們就有了和硬件打交道的語(yǔ)言了。但是我們必須在硬件上實(shí)現(xiàn)指令系統(tǒng)的功能。要實(shí)現(xiàn)數(shù)字系統(tǒng)在硬件上需要有三個(gè)主要部分支持:1計(jì)算對(duì)位進(jìn)行操作的函數(shù)的組合邏輯,2存儲(chǔ)位的存儲(chǔ)器單元,3以及控制存儲(chǔ)器元素更新的時(shí)鐘信號(hào)。幸運(yùn)的是我們都有。
1邏輯門(mén)

下面是TTL電路實(shí)現(xiàn)上面邏輯門(mén)的硬件原理圖,具體怎么實(shí)現(xiàn),我也看不明白了!

2存儲(chǔ)器:如我們的虛擬存儲(chǔ)器系統(tǒng),寄存器(通用,專(zhuān)用,段)
3時(shí)鐘信號(hào):存儲(chǔ)單個(gè)位或字節(jié),時(shí)鐘控制寄存器加載輸入信號(hào)
如我們常用的運(yùn)算操作指令,傳送指令。

計(jì)算機(jī)硬件翻譯指令過(guò)程

看完上面的圖,我們?cè)倩剡^(guò)頭來(lái)看看馮諾依曼體系結(jié)構(gòu)以及存儲(chǔ)程序思想。
1計(jì)算機(jī)是由運(yùn)算器,控制器,存儲(chǔ)器,輸入輸出設(shè)備五部分組成
2采用存儲(chǔ)程序的方式,要執(zhí)行的程序和數(shù)據(jù)先放到存儲(chǔ)器中
3采用二進(jìn)制編碼數(shù)據(jù)
4程序是指令的集合,指令在存儲(chǔ)器中按執(zhí)行順序存放

好了,這一次hello world漫游就到這里,如果你能看到這里,并能理解我今天介紹的這些東西,那么相信你一定對(duì)計(jì)算機(jī)系統(tǒng)有一個(gè)系統(tǒng)的理解,一定會(huì)覺(jué)得閱讀的幾個(gè)小時(shí)有收獲!

參考資料
1深入理解計(jì)算機(jī)系統(tǒng)
2匯編語(yǔ)言程序設(shè)計(jì)
3C/C++程序設(shè)計(jì)語(yǔ)言
4計(jì)算機(jī)組織與結(jié)構(gòu)
5計(jì)算機(jī)操作系統(tǒng)
616/32位微機(jī)原理

注:文章中圖部分來(lái)源于百度

總結(jié)

以上是生活随笔為你收集整理的hello world漫游的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。