匯編語言第二章
在CPU中,有四種主要的部件。運算器,控制器,寄存器,內部總線。這裏的內部總線用於CPU內部進行各種信息的傳遞,與第一章所講的控制總線,數據總線,地址總線不同,第一章所描述的總線屬於外部總線,作為CPU與外部期間進行信息傳遞的通路。運算器用於各種信息的處理,寄存器用於信息的處理,控制器用於控制信息的處理。對於利用匯編編程來說,寄存器是主要操作的部件,不同的CPU中寄存器的個數和種類是不同的,8086CPU寄存器個數為14個AX,BX,CX,DX,CS,SS,DS,ES,SI,DI,SP,BP,IP,PSW。
2.1 通用寄存器和字在寄存器中的存儲
8086CPU所有的寄存器均為16位,其中AX,BX,CX,DX這四個寄存器一般作為通用的寄存器使用,用於存儲一般的數據。16位寄存器能存儲的最大值為2^16=65536,在8086CPU寄存器之前有很多8位的寄存器的CPU,為了和以前在8位寄存器下寫的程序相兼容,8086CPU將16位寄存器可分為高八位和低八位的寄存器使用。
以AX寄存器為例,其邏輯結構如下圖所示,從做到右依次為高位到低位。
比如我們存儲一個數據2000H(後綴H,hex代表16進制),其二進制位10000000000000B(B,binary代表二進制),我們將該數據存入AX中為:
0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0
當我們將AX分為兩個8位寄存器的時候為:AH(AX High 8-BIT),AL(AX Low-BIT)。
類似的BX,CX,DX分成8位寄存器為:BH和BL,CH和CL,DH和DL
一個字節代表8位二進制位,一個字代表兩個字節即16位二進制位。當存儲一個字節的時候可以將其存儲在寄存器的高8位或者低8位,當存儲一個字的時候需要將該字的高字節存儲在寄存器的高8位,將該字的低字節存儲在寄存器的低8位。
2.2 一些匯編指令和物理地址
(1)mov ax,12h與MOV AX,12H是一樣的效果,匯編指令不區分大小寫
(2)若ax和bx當前存儲的值都是8226H,當執行add ax,bx的時候其結果應該為1044CH,但是存儲結果的寄存器ax為16位
而1044CH位20位,所以進位的1不能存儲(當可以影響進位標識寄存器),相加後的ax存儲的值為044CH
(3)指令add al,93h,執行器al中的數據為C5H,相加之後為158H。但是你會以為在al中存儲58H,同時將最高位的1存儲在ah中,那麽這樣理解你就錯了,因為當匯編指令使用8位寄存器的時候,是作為獨立的寄存器使用與其高位寄存器是無關的。所以ax中的值為0058h.
(4) 在進行運算和數據傳送的時候。寄存器的位數必須一致,不能出現mov ax,bl或者add bh,ax之類的指令。
(5) 在第一章已經介紹過,計算機內的所有存儲區都是通過進行統一進行編制的,其尋址是通過地址總線進行尋址,每個存儲區單元都有唯一的地址進行尋址,這個地址我們稱為物理地址。
2.3 16位機和8086進行尋址的方法
16位機代表CPU內部進行運算和寄存的位數為16位,即CPU內部的運算器一次性能進行16位數據的運算,CPU內部的寄存器最大能存儲16位數據單元。8086CPU有20條地址總線進行尋址,那麽問題來了,CPU在進行尋址的時候地址信息會先存儲在CPU內部,但是8086CPU內部最大可以存儲16位地址信息,那麽怎麽來對20位地址進行存儲呢。
其解決辦法是在內部通過一個加法器將兩個16位地址合成20位地址來進行存儲區尋址。其示意圖如下:
8086CPU內部的寄存器提供兩個16位的地址,通過地址加法器合成一個20位的地址,進而通過輸入輸出電路將20位地址經由地址總線傳送到外部存儲區進行尋址。
兩個16位地址通過地址加法器合成20位地址的示意圖如下:
地址加法器計算公式:20位物理地址=16位段地址*16+16位偏移地址。這裏簡單解釋一下,對於二進制數據來講當進行移位操作的時候,左移動一位相當於*2, 地址1230H*16即向左移位4位,變為12300H。這時候再加上偏移地址00C8H,結果為123C8H,該地址即為我們合成後的20位物理地址。
舉個例子來說明這一問題,學校,體育館,圖書館位於一條直線上,學校位於這條線的起點。示意圖如下:
如果路人問路,圖書館在哪兒,那麽可以有如下兩種方式回答:
1.從學校直走2826m即可達到圖書館
2.從學校直走2000m到達體育館,再直走826m達到圖書館
第一種方法是直接給出圖書館的物理地址(直接地址),第二種方式是通過體育館作為中介間隔告訴圖書館的位置。
進一步來想,如果只能通過紙條告訴路人圖書館得位置。但是只有兩張可以寫三位數的紙條,此時怎麽辦呢,那麽我們可以在第一張紙條上寫上200作為段地址,第二張紙條寫上826作為偏移地址。那麽我們可以通過:段地址200*10+偏移地址826=2826來獲知圖書館的位置。
2.4 段的概念和段寄存器
首先要明確一個概念,內存並沒有分段,是CPU在尋址的時候進行分段的,如圖所示:
我們可以認為10000H-100FFH組成一個段,該段的起始地址為10000H,段地址為1000H,大小為100H,我們也可以認為10000H-1007FH和10080H-100FFH位兩個段,兩個段的起始地址分別為10000H和10080H,段地址為1000H和1008H,段的大小為80H。如果一個段的偏移地址長度為N位,那麽這個段的大小為2^N。
前面講過CPU內部提供兩個16位的地址通過加法器合成20位物理地址,那麽提供16位段地址的部件是什麽呢,顯然是CPU內部的寄存器啦,8086CPU內部有四個段寄存器分別為CS,SS,DS,ES
2.5 CS和IP
CS和IP作為兩個非常重要寄存器,其中CS為代碼段寄存器,IP為偏移量,通過公式CS*16+IP便可合成CPU當前要讀取指令的物理地址。比如當前CS中存儲為M,IP存儲為N,那麽CPU將從M*16+N的合成地址中取一條指令執行。
通過CS和IP合成當前指令並取指令的邏輯圖如上圖所示。主要步驟如下:
(1)將CS和IP送入地址加法器合成20位物理地址為2000H*16+0000H=20000H
(2)通過輸入輸出控制電路將20位物理地址送到地址總線進行尋址
(3)將尋址到的匯編指令mov ax,0123H對應的機器碼0123B8H依次通過數據總線傳輸到CPU中的指令緩沖器中。
(4)執行指令,此時IP=IP+執行指令的長度,跳轉步驟1.
說明一點,8086CPU加點復位後,CS和IP分別被設置為CS=FFFFH,IP=0000H,即開機後的第一條執行指令地址為FFFF0H。
2.6 修改CS和IP,代碼段的介紹
CS與IP組成CPU當前執行指令的位置,可以通過修改CS與IP改變CPU執行指令的順序。然而問題來了,如何改變CS與IP 的值呢,這裏要註意的是不能使用MOV指令改變CS和IP寄存器的值,因為8086CPU沒有提供這樣的功能。其實修改CS與IP的值方式有很多種,這裏僅介紹jmp。 jmp 段地址:偏移地址 可改變CS與IP寄存器中的值,從而完成CPU執行指令順序的跳轉。比如jmp 12:34 這裏CS=0012H IP=0034H 執行jmp 12:34之後將直接跳轉到00154H處取指令執行。若僅僅想改變IP的值不改變CS的值,可以使用jmp 某一個合法寄存器
代碼段為存放代碼的一段內存區域,比如如下一段匯編代碼:
mov ax,0000
add ax,123H
mov bx,ax
jmp bx
以上一段代碼段存儲在內存為123B0H-123B9H這段內存區域中,共十個字節,那麽我們可以成為這段內存區域為代碼段,前面已經介紹過要執行這段代碼要把CS:IP指向mov ax,0000的內存區域即可。
匯編語言第二章