【OS学习笔记】一 处理器、内存和指令
學習交流加
- 個人qq:
1126137994 - 個人微信:
liu1126137994 - 學習交流資源分享qq群:
962535112
我們已經知道,處理器是一臺電子計算機的核心,它會在振蕩器脈沖的激勵下,從內存中獲取指令,并發起一系列由該指令所定義的操作。當這些操作結束之后,它接著再取下一條指令。通常情況下,這個過程是連續不斷、循環往復的。
文章目錄
- 1、寄存器和算數邏輯部件
- 2、內存儲器
- 3、指令和指令集
- 4、Intel 8086處理器
- 4.1、 8086的通用寄存器
- 4.2、 程序的重定位問題
- 4.3、 內存分段機制
- 4.4 、8086的內存分段機制
- 4.5 、8086 處理器內部組成框圖
- 5、 總結
1、寄存器和算數邏輯部件
電子計算機能能做很多事情。計算天氣預報,看電影,聽音樂,上網等,實際上都是以數學計算為基礎。它之所以能夠計算,是因為它特殊的設計。想要了解計算機為什么能夠自動計算,請去閱讀書籍《穿越計算機的迷霧》。本片文章主要講解處理器的簡單功能。
如圖是一個處理器:
在處理器的周圍,有大量的引腳,這些引腳可以接受從外面來的電信號或者向外發送電信號(與外設進行信號的交互)。有很多引腳是復用的,假如現在我們要進行加法運算,我們就需要重復使用某一些引腳來依次將加數與被加數送入。一旦被加數被送入處理器,代表這個二進制數字的一組電信號就會出現在與該引腳相連的內部線路上(我們稱這個內部線路為內部總線)。這是一組高低電平的組合,代表著二進制數中的每一位。當被加數被送進來了,接下來就要將加數送進來,但是此時內部總線上有被加數,所以處理器內部需要有一個電路來將被加數“鎖存”。這個將被加數鎖存的電路就是寄存器。它是一個存儲器件。
同樣,加數也要鎖存進另一個寄存器。如圖中RA與RB分別鎖存的是被加數與加數。此后,被加數與加數將不再受處理器的內部總線的影響。寄存器是雙向器件,它會將它鎖存的數,在另一端產生一模一樣的電信號(注意此時寄存器中依然鎖存著之前的電信號,它只是在另一端產生一個一模一樣的電信號),傳送給相應的算數邏輯部件(ALU)進行計算。算數邏輯部件(ALU)計算出結果后,將結果送出,給另一個寄存器RC鎖存,稍后再將RC中的內容通過內部總線送到處理器外部,或者再次送回RA RB寄存器進行其他計算。
那么,處理器是如何知道什么時候該干什么,各個部件在各個時間點該干什么,以及哪些部件在哪些時候使用內部總線以避免總線沖突呢?這些實際上都是由處理器內部的一個控制器控制的(圖中沒有畫出)。
處理器總是繁忙的,所有數據都只能在寄存器中寄存一會,就必須被送往別處。早期的寄存器只能存儲4比特、8比特或者16比特,分別叫做4位寄存器,8位寄存器和16位寄存器。現在的處理器大多是32位和64位的。
2、內存儲器
上一節我們知道,處理器的計算過程實際上是借助于寄存器和算數邏輯部件進行的。那么計算的數據是從哪里來的呢?它是從一個可以保存很多數字的電路,叫做存儲器。存儲器的種類很多,我們常見的U盤,硬盤,磁盤,內存條,甚至寄存器等都是存儲器。
我們這里主要說內存條。由于它通常是和處理器直接相連的,所以叫內存儲器或者主存儲器。又或者內存或者主存。和寄存器不同,內存用于保存更多的比特。對應用的最多的個人計算機來說,內存是按字節來組織的,單次訪問的最小單位是1字節,這是最基本的存儲單元。如下圖所示是一個內存和內存訪問示意圖:
內存中的每一個字節都對應著一個地址。從0地址開始,由于上面的內存是65536字節,所以該內存的最后一個字節是FFFF(都是用的十六進制表示的)。為了訪問一個內存,處理器需要給出一個地址。同時訪問內存是什么方式?讀方式或者寫方式,所以處理器需要有一個讀寫控制。如果是寫數據,處理器還需要有一個數據傳輸的控制。最后,處理器單次訪問內存時,是以字節為單位訪問還是以字為單位訪問等,需要有一個字長控制來告知。
3、指令和指令集
從一開始設計處理器,就是想讓它自動工作,另外,還需要提供一種機制,來允許程序員決定進行何種工作。處理器的設計者用某些數來表示該處理器該做什么,這些數,我們稱為指令或者叫機器指令。
下面給個實際例子來分析指令在內存中的布局:
假設現在我們的處理器是從內存的0000地址開始取指令(實際上肯定不是從0地址開始,這里只是假設)。第一條指令B8 5D 00,該指令的意思是將立即數005D傳送到RA寄存器,它具有一個字節的操作碼B8。由此我們可以看出簡單的一個B8 5D 00指令,是一個傳送指令,且該指令將兩個字節(005D)傳送到RA寄存器,并且由于下一條指令的地址是在0003字節處,所以該指令肯定還知道它自己是一條3字節指令,以便下一次處理器可以直接去到0003字節處去取指令。
對于一些復雜的指令,一個字節的操作碼肯定不夠用,所以第二條指令8B 1E 3F 00的指令操作碼是兩字節8B 1E。
同時我們注意到上述前兩條指令中,第一條指令是將一個數005D直接傳送到寄存器,第二條指令,是需要從另外一個地址(003F)先取出數據,然后再將數據傳送到寄存器。第一種的操作數005D我們稱為立即數(表示可以立即將數傳送而不需要再去另外一個地址取數據)。
由以上分析,我們很容易知道,上述的幾條指令,首先將兩個數放到寄存器中去運算,然后運算結果放到其中一個寄存器中,最終還需要將運算結果再傳回到內存中以便該結果作為其他用處時處理器好可以從內存中得到計算結果。最后F4指令停機。
指令和非指令的二進制數據是一模一樣的,在組成內存的電路中,都是一些高低電平的組合。因為處理器是按順序取指令,并加以執行的,這樣的話,如果指令和數據存放在一起,處理器很容易將數據的二進制當成指令,從而導致錯誤。所以我們需要將指令與數據分開存放。分別存放在不同的區域。存放指令的區域叫做代碼區,存放數據的區域叫做數據區(這就是為什么進程的虛擬地址空間中代碼和數據區分開的原因)。
一個處理器能夠識別的指令的集合,稱為指令集。
4、Intel 8086處理器
要想學好編程,就必須要懂底層原理。但是想要徹底學好底層,就要把匯編學好。想要學好匯編,不得不先學好針對8086的匯編技術。
4.1、 8086的通用寄存器
8086處理器內部有8個16位寄存器。分別被命名為:AX,BX,CX,DX,SI,DI,BP,SP。通用的意思是他們中大部分可以根據需要用于多種目的。他們的用處,將在后面的文章逐漸給出。
下圖是幾個寄存器:
可以看到,有介個寄存器,AX,BX,CX,DX,又可以分為兩個8位的寄存器來使用。在后面文章中,我們會看到具體的應用。
4.2、 程序的重定位問題
我們知道,處理器是自動取指令和執行指令的,只要每條指令都正確無誤,它就能準確的知道下一條指令的地址。所以,指令必須集中在一起,形成一個段,叫做代碼段。
為了做某件事而編寫的指令,形成我們所知道的程序。程序中肯定需要操作大量的數據,這大量的數據也應該集中在一起,位于內存中的某個地方,叫做數據段。
段在內存中的位置并不重要,因為處理器是可控的,我們可以讓處理器在內存中的任何一個位置開始取指令并加以執行。
下面看一個圖示:
假設上面是一個程序片段在內存中的位置,相關指令的用處已經在圖中表明。這里不再贅述。但是現在有一個問題,就是我們寫的程序(不管是C語言還是C++語言或者Java語言),最終要運行在內存中的位置,是無法確定的。因為你想一想,本身你的電腦中有各種程序在跑了,有qq程序在跑,微信程序在跑,或者還有微博等在跑,他們可能把你的內存都占完了,當你想運行你寫的程序的時候,你的程序本想從0100H處開始存放代碼段,但是可能這個時候0100H處有其他程序的代碼或者指令在運行,此時你的程序只能去另一個位置存放你的代碼和數據,假設你的代碼下一次運行的時候代碼段和數據段在如下位置:
此時你的程序的代數據段在內存的位置為1000H處,但是你會發現,你的代碼段的第一條指令,還是將地址單元0100H處的內容傳送到AX寄存器中。但是!!!此時0100H處的內容,并不是我們想要的內容。
產生這種情況的原因就是我們在程序中使用的是絕對內存地址。這樣的程序是無法重新定位的。所以我們需要使用另一種方式訪問內存:相對地址或者叫做邏輯地址。在任何時候,程序的重定位都是非常棘手的事情。在8086處理器中,這個問題得到解決。它使用了分段機制。
4.3、 內存分段機制
在內存分段中,段,是很多個連續的字節組成的。如圖:
上圖有一個7個字節的段。段的起始地址為A532。那么段中的地址從第一個字節開始,他們的地址此時就是段內的偏移地址(0000,0001,0002…)。而他們的實際的物理地址,又恰好等于段地址加上段內的偏移地址。可以用“段地址:偏移地址”,來表示段中的每一個字節的地址。
為了在硬件一級提供對“段地址:偏移地址”的支持。處理器至少要提供兩個段寄存器,分別是代碼段寄存器CS,數據段寄存器DS。
對代碼段CS內容的改變,將導致處理器從新的代碼段開始執行。當然,在訪問數據之前,也是必須要提前設置好數據段寄存器DS的,使DS之指向數據段。
很重要的一點是,當處理器取指令執行指令的時候,它是把指令中指定的內存地址看成是段內偏移地址的。而不是內存的物理地址。那么當處理器遇到一條訪問內存的指令時,它就會將DS中的數據段起始地址加上指令中提供的段內偏移地址得到訪問內存所需要的物理地址的。
如下圖所示:
代碼段地址為1020H,數據段地址為1000H,在代碼段中有一條指令:A1 02 00,它的功能是將地址0002H處的的一個字傳送到寄存器AX。在這里處理器將0002H看成是段內偏移地址,段地址在DS中,應該在執行這條指令之前就已經用別的地址將數據段地址傳送到DS寄存器中了。當處理器執行到指令A1 02 00時,處理器會將DS中的內容和指令中指定的便宜地址相加,得到內存中的一個物理地址,這個物理地址就是處理器要去訪問的內存地址,就可以從該地址獲取一個字:00A0H。
如果下一次執行該程序,代碼段和數據段發生變化,只需要將程序的代碼段地址和數據段地址分別傳送到CS和DS就可以正常的執行程序了。
4.4 、8086的內存分段機制
前面講了如何從邏輯地址轉換到物理地址,以使得程序的運行和它在內存中的位置是無關的。上述策略在很多處理器上應用得到了支持。但是在8086處理器上,由于8086處理器是16位處理器,如果按照正常計算,給它提供16根地址線的話,那么8086處理器就只能用于尋址最多64KB的內存空間(65536字節=2的15次方+1)。在當時的年代64KB的內存還是不夠的。所以8086處理器就將16根地址線擴展到20根地址線。從而使得可尋址的空間變為1M(16*64KB)。
但是有一個問題就是16位的段地址加上16位的段內偏移地址,還是16位的,并不是20位的。所以有一個解決辦法就是在計算內存的物理地址時,先將段地址先左移4位,然后加上段內偏移地址,這樣就可以得到20位的物理地址,就可以將整個1M的地址空間表示完全。
8086在進行分段時,并不是每一個地址都可以作為段地址,地址必須是16的倍數,才能作為段地址。
如下圖,是其中的一種情況,我們從0地址開始分段,每段16字節(從任何地址只要這個地址是16的倍數,都可以作為段地址,每一個段內最低有16字節(可以分為65536個段)的內存,最高有65536(可以分為16個段)個字節的內存)
4.5 、8086 處理器內部組成框圖
最后我們再來看一下8086處理器內部組成框圖:
上圖中,我們知道8086內部有8個16位通用寄存器,分別為AX,BX,CX,DX,SI,DI,BP,SP。ALU是算數邏輯部件,用于算數邏輯運算或者數據傳送。標志寄存器是用于控制各種依賴于標志位的標志來進行相應的指令執行的,這個可以等到以后的文章中進行詳細的說明,目前不需要理解。處理器可以自動執行,依賴于控制器的控制。
指令隊列緩沖器,又名:指令預取隊列。什么意思呢?就是當你的CPU在忙于做其他事情(一般是指執行那些不需要去內存中取的指令)而并沒有去內存中取指令執行時,此時指令隊列緩沖器(指令預取隊列)就會去內存中取出6個字節的指令放到指令隊列緩沖器,那么當CPU該執行內存中的指令時,它就會就近向指令隊列緩沖器中去取指令,這樣的話就會比去內存中取指令要快很多,畢竟內存還是通過外部總線與內存條相連接的。
CS是代碼段寄存器。DS是數據段寄存器。SS是棧段寄存器(很重要,以后會講)。ES是額外的段寄存器,它的用處相當于補充段寄存器,當你的DS在使用時,但是你還要訪問另一個數據段,那么此時就可以使用ES寄存器(后面的文章中我們就用ES寄存器指向顯卡的內存區域,用來尋址顯存,從而控制顯卡)。IP寄存器,是存代碼段的段內偏移地址的。那么指令的地址此時就可以用“CS:IP”來表示。
上面的與總線控制邏輯相連的16位總線,實際上是16位的數據總線與20位的地址總線的低16位復用的。20位代表的是20位的地址總線是(當然,低16位是與數據總線復用的)。
5、 總結
想要寫出優秀的應用程序,就必須對系統編程有深入的理解。想要對系統編程有一定的理解,就必須理解操作系統原理。我選擇從X86匯編開始學習,逐步深入理解操作系統與計算機系統之間的關系。
本片文章可以讓我們學會
- 寄存器與算數邏輯部件的簡單關系
- 內存儲器
- 指令和指令集
- 程序的重定位問題
- 處理器與內存之間的關系
- 內存分段機制
學習探討加
qq:1126137994
微信:liu1126137994
總結
以上是生活随笔為你收集整理的【OS学习笔记】一 处理器、内存和指令的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 假如生活欺骗了你
- 下一篇: 全套思源黑体合集(含ttf/ttc版/行