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