基本原理
2.1 8086/8088
IBM PC中央處理單元(Central Processing Unit)是微處理器Inter 8088,8088是8086是小的版本.對于編寫程序而言,兩者幾乎完全相同.兩者之間的差別是在于:它們對外的溝通.8086和外界溝通時是經(jīng)由16位的輸入輸出通道,內(nèi)存存取也是每次以16位為單位,8088和8086極為相似,但是它和外界溝通時就必須經(jīng)由16位的通道.
2.1.1 寄存器
8086/8088的結(jié)構(gòu)簡單,其中包含了一組一般用途的16位寄存器.AX,BX,CX,DX,BP,SI,DI.其中AX,BX,CX,DX還可以分成8位的寄存 器,譬如:AX可分為AH,AL;BX可分為BH,BL;CX可分為CH,CL;DX可分為DH,DL.寄存器BP,SI,DI的用途也沒有特別的限制,但是卻不能分成兩個字節(jié).另外寄存器SP主要是用來當(dāng)做堆棧指針.除此之外,還有四個非常重要的段寄存器(Segment Register):CS,DS,SS,ES.指令指針(Instru -ction pointer)IP是用來控制目前CPU執(zhí)行到哪一個指令.
8086設(shè)計時考慮到要和8位的CPU8080兼容.8位的計算機是使用兩個字節(jié)(亦即16位)來定址,因此其定址空間可以達64K字節(jié).16位的CPU在地址設(shè)定上選擇了完全不同的方法.CPU以段(Segment)為單位,每一段范圍內(nèi)包括64K字節(jié),而內(nèi)存中則可以包含許多段.所以,操作系統(tǒng)可以在一個段內(nèi)執(zhí)行.而使用者的程序則可以在另一個段內(nèi)執(zhí)行.在一個段內(nèi),程序包可以把計算機視為只有64K字節(jié)內(nèi)存空間.因此原先8位計算機上執(zhí)行的程序就可以很容易地移植到16位計算機上.除此之外,內(nèi)存段也可以彼此重疊,因而兩個不同的程序就可以共用某一塊內(nèi)存.段值是以寄存器來設(shè)定的,而實際的地址值則是把段值(16位)往左移4位,然后再加上16位的位移(Offset),因此構(gòu)成20位的地址值.所以8086可以直接做20位的地址,也就是可能存取到一兆字節(jié)的內(nèi)存.在這一兆字節(jié)的內(nèi)存中,IBM PC保留了最前面的320K字節(jié)給系統(tǒng)的ROM BIOS和顯示內(nèi)存,因此使用者最多也就能使用640K字節(jié).
2.1.2 尋址方式
尋址方式(Addressing mode)是一臺計算機上許多復(fù)雜操作的關(guān)鍵所在.8086提供了以下幾種尋址方法:立即尋址,內(nèi)存間接尋址, 寄存器間接尋址等.
立即尋址,直接使用數(shù)字.
內(nèi)存間接尋址,數(shù)值存放在數(shù)據(jù)段中的某個位置.
mov bx,foo
foo dw 5
寄存器間接尋址.有兩種寄存器可以使用在這種尋址方式下:基址寄存器(Base Register)和索引寄存器(Index Register).基址寄存 器分別是BX和BP,索引寄存器則是SI和DI.在這種尋址方式下,寄存器存放了數(shù)據(jù)段中的地址值.
mov ax,0F000h
mov es,ax
mov si,0FFFEh
mov dl,byte ptr es:[si]
上面的程序使用間接尋址方式,由寄存器SI讀出位于F000:FFFE位置的數(shù)據(jù).寄存器間接存取時,最多只能使用瑪個基址寄存器各 一個索引寄存器.
以上的尋址方式可以做不同的結(jié)合,因此組合后的結(jié)果很多.
2.1.3 標志
8086有9個一位的標志(Flag),它們可以用指示CPU的各種狀態(tài).以下是9個標志的簡介:
CF(Carry Flag):CF為1時就表示算術(shù)運算的結(jié)果超出正確的長度.
PF(Parity Flag):PF為1就表示使用偶校驗,PF為0就表示使用奇校驗.
AF(Auxiliary Carry Flag):和CF相同,只是它使用在低4位的結(jié)果.AF通常都使用在20位的地址計算上.
ZF(Zero Flag):ZF為1就表示運算結(jié)果是0,否則ZF就為0.
SF(Sign Flag):SF為1就表示運算結(jié)果的最高位是1,否則SF就為0.
TF(Trap Flag):TF為1,CPU就單步地執(zhí)行,在這種模式下每完成一個指令就發(fā)生一個特殊的中斷.
IF(Interrupt Enable Flag):IF為1,允許CPU接收外界的中斷,否則IF就為0.
DF(Direction Flag):這個標志使用在循環(huán)指令,譬如:MOVS,MOVSB,MOVSW,CMPS,CMPSB和CMPSW.如果DF為1,循環(huán)運行時就使地 址值往前增加.如果DF為0,則使地址往后減少.
OF(Over Flag):OF為1,表示一個考慮正負號的運算超出了正確的字節(jié)的長度.
2.1.4 循環(huán)
所有的循環(huán)指令都是以CX作為計數(shù)器.一個循環(huán)會反復(fù)地執(zhí)行直到CX等于某一特定值為止.以下的程序就是利用反復(fù)地相加,完成 兩個數(shù)的相乘.
mov ax,0
mov cx,4
next: add ax,6
loop next
在上面的程序中,LOOP指令執(zhí)行時會把CX減1,并且檢查CX的內(nèi)容;如果CX等于0,就轉(zhuǎn)移到下一條指令,否則就跳到NEXT標示的地方 執(zhí)行.
也可以用下面的程序完成相同的功能:
mov ax,0
mov cx,4
next:
add ax,6
dec cx
cmp cx,0
jne next
2.1.5 內(nèi)存的數(shù)據(jù)結(jié)構(gòu)
8088是以字節(jié)為存取數(shù)據(jù)的基本單位.計算機的存儲結(jié)構(gòu)是8位的字節(jié),但是CPU本身處理數(shù)據(jù)則是以16位為單位.在內(nèi)存中,都遵 循一個原則,即:高高低低的存儲方式.高字節(jié)對應(yīng)高地址,低字節(jié)對應(yīng)低地址.
下面是一個簡單程序,在AX中放入一個字節(jié)的內(nèi)容并顯示:
cseg segment
org 100h
assume cs:cseg,ds:cseg
start:
mov bx,cs
mov ds,bx
mov ah,'H'
mov al,'L'
mov test,ax
mov al,[si] ;First byte of test
call dchar
mov al,[si+1] ;Second byte of test
call dchar
ret
;Display the character contained in AL
dchar proc
push ax
push bx
mov bh,1
mov ah,0eh
int 10h
pop bx
pop ax
ret
dchar endp
test dw ?
cseg ends
end start
2.1 8086/8088
IBM PC中央處理單元(Central Processing Unit)是微處理器Inter 8088,8088是8086是小的版本.對于編寫程序而言,兩者幾乎完全相同.兩者之間的差別是在于:它們對外的溝通.8086和外界溝通時是經(jīng)由16位的輸入輸出通道,內(nèi)存存取也是每次以16位為單位,8088和8086極為相似,但是它和外界溝通時就必須經(jīng)由16位的通道.
2.1.1 寄存器
8086/8088的結(jié)構(gòu)簡單,其中包含了一組一般用途的16位寄存器.AX,BX,CX,DX,BP,SI,DI.其中AX,BX,CX,DX還可以分成8位的寄存 器,譬如:AX可分為AH,AL;BX可分為BH,BL;CX可分為CH,CL;DX可分為DH,DL.寄存器BP,SI,DI的用途也沒有特別的限制,但是卻不能分成兩個字節(jié).另外寄存器SP主要是用來當(dāng)做堆棧指針.除此之外,還有四個非常重要的段寄存器(Segment Register):CS,DS,SS,ES.指令指針(Instru -ction pointer)IP是用來控制目前CPU執(zhí)行到哪一個指令.
8086設(shè)計時考慮到要和8位的CPU8080兼容.8位的計算機是使用兩個字節(jié)(亦即16位)來定址,因此其定址空間可以達64K字節(jié).16位的CPU在地址設(shè)定上選擇了完全不同的方法.CPU以段(Segment)為單位,每一段范圍內(nèi)包括64K字節(jié),而內(nèi)存中則可以包含許多段.所以,操作系統(tǒng)可以在一個段內(nèi)執(zhí)行.而使用者的程序則可以在另一個段內(nèi)執(zhí)行.在一個段內(nèi),程序包可以把計算機視為只有64K字節(jié)內(nèi)存空間.因此原先8位計算機上執(zhí)行的程序就可以很容易地移植到16位計算機上.除此之外,內(nèi)存段也可以彼此重疊,因而兩個不同的程序就可以共用某一塊內(nèi)存.段值是以寄存器來設(shè)定的,而實際的地址值則是把段值(16位)往左移4位,然后再加上16位的位移(Offset),因此構(gòu)成20位的地址值.所以8086可以直接做20位的地址,也就是可能存取到一兆字節(jié)的內(nèi)存.在這一兆字節(jié)的內(nèi)存中,IBM PC保留了最前面的320K字節(jié)給系統(tǒng)的ROM BIOS和顯示內(nèi)存,因此使用者最多也就能使用640K字節(jié).
2.1.2 尋址方式
尋址方式(Addressing mode)是一臺計算機上許多復(fù)雜操作的關(guān)鍵所在.8086提供了以下幾種尋址方法:立即尋址,內(nèi)存間接尋址, 寄存器間接尋址等.
立即尋址,直接使用數(shù)字.
內(nèi)存間接尋址,數(shù)值存放在數(shù)據(jù)段中的某個位置.
mov bx,foo
foo dw 5
寄存器間接尋址.有兩種寄存器可以使用在這種尋址方式下:基址寄存器(Base Register)和索引寄存器(Index Register).基址寄存 器分別是BX和BP,索引寄存器則是SI和DI.在這種尋址方式下,寄存器存放了數(shù)據(jù)段中的地址值.
mov ax,0F000h
mov es,ax
mov si,0FFFEh
mov dl,byte ptr es:[si]
上面的程序使用間接尋址方式,由寄存器SI讀出位于F000:FFFE位置的數(shù)據(jù).寄存器間接存取時,最多只能使用瑪個基址寄存器各 一個索引寄存器.
以上的尋址方式可以做不同的結(jié)合,因此組合后的結(jié)果很多.
2.1.3 標志
8086有9個一位的標志(Flag),它們可以用指示CPU的各種狀態(tài).以下是9個標志的簡介:
CF(Carry Flag):CF為1時就表示算術(shù)運算的結(jié)果超出正確的長度.
PF(Parity Flag):PF為1就表示使用偶校驗,PF為0就表示使用奇校驗.
AF(Auxiliary Carry Flag):和CF相同,只是它使用在低4位的結(jié)果.AF通常都使用在20位的地址計算上.
ZF(Zero Flag):ZF為1就表示運算結(jié)果是0,否則ZF就為0.
SF(Sign Flag):SF為1就表示運算結(jié)果的最高位是1,否則SF就為0.
TF(Trap Flag):TF為1,CPU就單步地執(zhí)行,在這種模式下每完成一個指令就發(fā)生一個特殊的中斷.
IF(Interrupt Enable Flag):IF為1,允許CPU接收外界的中斷,否則IF就為0.
DF(Direction Flag):這個標志使用在循環(huán)指令,譬如:MOVS,MOVSB,MOVSW,CMPS,CMPSB和CMPSW.如果DF為1,循環(huán)運行時就使地 址值往前增加.如果DF為0,則使地址往后減少.
OF(Over Flag):OF為1,表示一個考慮正負號的運算超出了正確的字節(jié)的長度.
2.1.4 循環(huán)
所有的循環(huán)指令都是以CX作為計數(shù)器.一個循環(huán)會反復(fù)地執(zhí)行直到CX等于某一特定值為止.以下的程序就是利用反復(fù)地相加,完成 兩個數(shù)的相乘.
mov ax,0
mov cx,4
next: add ax,6
loop next
在上面的程序中,LOOP指令執(zhí)行時會把CX減1,并且檢查CX的內(nèi)容;如果CX等于0,就轉(zhuǎn)移到下一條指令,否則就跳到NEXT標示的地方 執(zhí)行.
也可以用下面的程序完成相同的功能:
mov ax,0
mov cx,4
next:
add ax,6
dec cx
cmp cx,0
jne next
2.1.5 內(nèi)存的數(shù)據(jù)結(jié)構(gòu)
8088是以字節(jié)為存取數(shù)據(jù)的基本單位.計算機的存儲結(jié)構(gòu)是8位的字節(jié),但是CPU本身處理數(shù)據(jù)則是以16位為單位.在內(nèi)存中,都遵 循一個原則,即:高高低低的存儲方式.高字節(jié)對應(yīng)高地址,低字節(jié)對應(yīng)低地址.
下面是一個簡單程序,在AX中放入一個字節(jié)的內(nèi)容并顯示:
cseg segment
org 100h
assume cs:cseg,ds:cseg
start:
mov bx,cs
mov ds,bx
mov ah,'H'
mov al,'L'
mov test,ax
mov al,[si] ;First byte of test
call dchar
mov al,[si+1] ;Second byte of test
call dchar
ret
;Display the character contained in AL
dchar proc
push ax
push bx
mov bh,1
mov ah,0eh
int 10h
pop bx
pop ax
ret
dchar endp
test dw ?
cseg ends
end start