【匯編基礎(chǔ)】2.寄存器
一個典型的CPU(此處討論的不是某一具體的CPU)由運算器、控制器、寄存器(CPU工作原理)等器件構(gòu)成,這些器件靠內(nèi)部總線相連。
匯編基礎(chǔ)1里面所說的總線,相對于CPU內(nèi)部來說是外部總線。內(nèi)部總線實現(xiàn)CPU內(nèi)部各個器件之間的聯(lián)系,外部總線實現(xiàn)CPU和主板上其他器件的聯(lián)系。簡單地說,在CPU中:
- 運算器進行信息處理;
- 寄存器進行信息存儲:
- 控制器控制各種器件進行工作;
- 內(nèi)部總線連接各種器件,在它們之間進行數(shù)據(jù)的傳送。
對于一個匯編程序員來說,CPU中的主要部件是寄存器。寄存器是CPU中程序員可以用指令讀寫的部件。程序員通過改變各種寄存器中的內(nèi)容來實現(xiàn)對CPU的控制。
不同的CPU,寄存器的個數(shù)、結(jié)構(gòu)是不相同的。8086CPU有14個寄存器,每個寄存器有一個名稱。這些寄存器是:AX、BX、CX、DX、SI、DI、SP、BP、IP、CS、SS、DS、ES、PSW。我們不對這些寄存器進行一次性的介紹,在課程的進行中,需要用到哪些寄存器,再介紹哪些寄存器。
2.1 通用寄存器
8086CPU的所有寄存器都是l6位的,可以存放兩個字節(jié)。AX、BX、CX、DX這4個寄存器通常用來存放一般性的數(shù)據(jù),被稱為通用寄存器。
以AX為例,寄存器的邏輯結(jié)構(gòu)如圖所示。
一個16位寄存器可以存儲一個16位的數(shù)據(jù),數(shù)據(jù)在寄存器中的存放情況如圖2.2所示。
想一想,一個16位寄存器所能存儲的數(shù)據(jù)的最大值為多少?
8086CPU的上一代CPU中的寄存器都是8位的,為了保證兼容,使原來基于上代CPU編寫的程序稍加修改就可以運行在8086之上,8086CPU的AX、BX、CX、DX這4個寄存器都可分為兩個可獨立使用的8位寄存器來用:
- AX可分為AH和AL;
- BX可分為BH和BL;
- CX可分為CH和CL;
- DX可分為DH和DL;
以AX為例,8086CPU的16位寄存器分為兩個8位寄存器的情況如下圖所示。
AX的低8位(0位~7位)構(gòu)成了AL寄存器,高8位(8位~15位)構(gòu)成了AH寄存器。
AH和AL寄存器是可以獨立使用的8位寄存器。下圖展示了16位寄存器及它所分成的兩個8位寄存器的數(shù)據(jù)存儲的情況
2.2 字在寄存器中的存儲
出于對兼容性的考慮,8086CPU可以一次性處理以下兩種尺寸的數(shù)據(jù)。
- 字節(jié):記為byte,一個字節(jié)由8個bit組成,可以存在8位寄存器中。
- 字:記為word,一個字由兩個字節(jié)組成,這兩個字節(jié)分別稱為這個字的高位字節(jié)和低位字節(jié),如圖2.5所示。
一個字可以存在一個16位寄存器中,這個字的高位字節(jié)和低位字節(jié)自然就存在這個寄存器的高8位寄存器和低8位寄存器中。如圖2.4所示,一個字型數(shù)據(jù)20000,存在AX寄存器中,在AH中存儲了它的高8位,在AL中存儲了它的低8位。AH和AL中的數(shù)據(jù),既可以看成是一個字型數(shù)據(jù)的高8位和低8位,這個字型數(shù)據(jù)的大小是20000;又可以看成是兩個獨立的字節(jié)型數(shù)據(jù),它們的大小分別是78和32。
關(guān)于數(shù)制的討論
任何數(shù)據(jù),到了計算機中都是以二進制的形式存放的。為了描述不同的問題,又經(jīng)常將它們用其他的進制來表示。比如圖2.4中寄存器AX中的數(shù)據(jù)是0100111000100000,這就是AX中的信息本身,可以用不同的邏輯意義來看待它。可以將它看作一個數(shù)值,大小是20000。
當(dāng)然,二進制數(shù)0100111000100000本身也可表示一個數(shù)值的大小,但人類習(xí)慣的是十進制,用十進制20000表示可以使我們直觀地感受到這個數(shù)值的大小。
十六進制數(shù)的一位相當(dāng)于二進制數(shù)的四位,如0100111000100000可表示成:4(0100)、E(1110)、2(0010)、0(0000)四位十六進制數(shù)。
由于一個內(nèi)存單元可存放8位數(shù)據(jù),CPU中的寄存器又可存放m個8位的數(shù)據(jù)。也就是說,計算機中的數(shù)據(jù)大多是由1-N個8位數(shù)據(jù)構(gòu)成的。很多時候,需要直觀地看出組成數(shù)據(jù)的各個字節(jié)數(shù)據(jù)的值,用十六進制來表示數(shù)據(jù)可以直觀地看出這個數(shù)據(jù)是由哪些8位數(shù)據(jù)構(gòu)成的。比如20000寫成4E20就可以直觀地看出,這個數(shù)據(jù)是由4E和20兩個8位數(shù)據(jù)構(gòu)成的,如果AX中存放4E20,則AH里是4E,AL里是20.這種表示方法便于許多問題的直觀分析。在以后的課程中,我們多用十六進制來表示一個數(shù)據(jù)。
在以后的課程中,為了區(qū)分不同的進制,在十六進制表示的數(shù)據(jù)的后面加H,在二進制表示的數(shù)據(jù)后面加B,十進制表示的數(shù)據(jù)后面什么也不加。如:可用3種不同的進制表示圖2.4中AX里的數(shù)據(jù),十進制:20000,十六進制:4E20H,二進制:0100111000100000B。
2.3 幾條匯編指令
通過匯編指令控制CPU進行工作,看一下表2.1中的幾條指令。
匯編指令 | 控制CPU完成的操作 | 用高級語言的語法描述 |
mov ax,18 | 將18送入寄存器AX | AX=18 |
mov ah,78 | 將78送入寄存器AH | AH=78 |
add ax,8 | 將寄存器AX中的數(shù)值加上8 | AX=AX+8 |
mov ax,bx | 將寄存器BX中的數(shù)據(jù)送入寄存器AX | AX=BX |
add ax,bx | 將AX和BX中的數(shù)值相加,結(jié)果存在AX中 | AX=AX+BX |
注意,為了使具有高級語言基礎(chǔ)的讀者更好地理解指令的含義,有時會用文字描述和高級語言描述這兩種方式來描述一條匯編指令的含義。在寫一條匯編指令或一個寄存器的名稱時不區(qū)分大小寫。如:mov ax,18和MOV AX,18的含義相同;bx和BX的含義相同。
接下來看一下CPU執(zhí)行表2.2中所列的程序段中的每條指令后,對寄存器中的數(shù)據(jù)進行的改變。
原AX中的值:0000H ,原BX中的值:0000H | ||
程序段中的指令 | 指令執(zhí)行后AX中的數(shù)據(jù) | 指令執(zhí)行后BX中的數(shù)據(jù) |
mov ax,4E20H | 4E20H | 0000H |
add ax,1406H | 6226H | 0000H |
mov bx,2000H | 6226H | 2000H |
add ax,bx | 8226H | 2000H |
mov bx,ax | 8226H | 8226H |
add ax,bx | 044CH | 8226H |
上表標(biāo)紅的數(shù)據(jù)為什么不是1044CH嗎?為什么是044CH?
程序段中的最后一條指令add ax,bx,在執(zhí)行前ax和bx中的數(shù)據(jù)都為8226H,相加后所得的值為:1044CH,但是ax為16位寄存器,只能存放4位十六進制的數(shù)據(jù),所以最高位的1不能在ax中保存,ax中的數(shù)據(jù)為:044CH。
程序段中的指令 | 指令執(zhí)行后AX中的數(shù)據(jù) | 指令執(zhí)行后BX中的數(shù)據(jù) |
mov ax,001AH | 001AH | 0000H |
mov bx,0026H | 001AH | 0026H |
add al,bl | 0040H | 0026H |
add ah,bl | 2640H | 0026H |
add bh,al | 2640H | 4026H |
mov ah,0 | 0040H | 4026H |
add al,85H | 00C5H | 4026H |
add al,93H | 0158H | 4026H |
程序段中的最后一條指令add al,93H,在執(zhí)行前,al中的數(shù)據(jù)為C5H,相加后所得的值為:158H,但是al為8位寄存器,只能存放兩位十六進制的數(shù)據(jù),所以最高位的1丟失,ax中的數(shù)據(jù)為:0058H。(這里的丟失,指的是進位值不能在8位寄存器中保存,但是CPU并不真的丟棄這個進位值,關(guān)于這個問題,將在后面的文章中討論。)
注意,此時al是作為一個獨立的8位寄存器來使用的,和ah沒有關(guān)系,CPU在執(zhí)行這條指令時認為ah和al是兩個不相關(guān)的寄存器。不要錯誤地認為,諸如add al,93H的指令產(chǎn)生的進位會存儲在ah中,addal,93H進行的是8位運算。
如果執(zhí)行addax,93H,低8位的進位會存儲在ah中,CPU在執(zhí)行這條指令時認為只有一個16位寄存器ax,進行的是16位運算。指令add ax,93H執(zhí)行后,ax中的值為:0158H。
此時,使用的寄存器是16位寄存器ax,add ax,93H相當(dāng)于將ax中的16位數(shù)據(jù)00c5H和另一個16位數(shù)據(jù)0093H相加,結(jié)果是16位的0158H。
在進行數(shù)據(jù)傳送或運算時,要注意指令的兩個操作對象的位數(shù)應(yīng)當(dāng)是一致的,例如:
mov ax,bx
mov bx,cx
mov ax,18H
mov al,18H
add ax,bx
add ax,20000
等都是正確的指令
而:
mov ax,b1(在8位寄存器和16位寄存器之間傳送數(shù)據(jù))
mov bh,ax(在16位寄存器和8位寄存器之間傳送數(shù)據(jù))
mov a1,20000(8位寄存器最大可存放值為255的數(shù)據(jù))
add al,100H(將一個高于8位的數(shù)據(jù)加到一個8位寄存器中)
等都是錯誤的指令,錯誤的原因都是指令的兩個操作對象的位數(shù)不一致。