彙編語言(王爽)第十一章

第十一章

8086CPU的標誌寄存器(簡稱flag)有16位,其中存儲的信息稱爲程序狀態字(PSW),其作用主要有3個

1、存儲相關指令的某些存儲結果

2、爲CPU執行相關指令提供行爲依據

3、控制CPU 的相關工作方式

其他寄存器存放數據時,是整個寄存器具有一個含義,而flag寄存器按位起作用,即每一位都有專門的含義,下圖爲8086CPU的flag寄存器結構

在這裏插入圖片描述
某些空白位不具有任何含義

11.1 ZF標誌

flag的第6位,零標誌位,相關指令執行後,若結果爲0,zf=1,否則zf=0

在8086CPU的指令集中,有些指令的執行影響標誌寄存器,如add、sub等,而mov、push、pop等即轉移指令則沒有影響

mov ax,1
and ax,0	; 執行後zf=1

11.2 PF標誌

flag的第2位,奇偶標誌位,相關指令執行後,其結果的所有bit位中1的個數若爲偶數,pf=1,否則pf=0

mov al,1
add al,10		; 結果爲00001011b,其中有3個1,則pf=0

sub al,al		; 結果爲00000000b,0個1,pf=1

11.3 SF標誌

flag的第7位,符號標誌位,相關指令執行後,如果結果爲負,sf=1,否則sf=0

SF標誌,是CPU對有符號數運算的記錄,如果我們把數據當作無符號數來運算,則SF的值沒有意義,雖然相關的指令勢必會影響它的值

某些指令會影響標誌寄存器的多個標記位,如

sub al,al		; ZF=1 PF=1 SF=0

11.4 CF標誌

flag的第0位是CF,進位標誌位,在進行無符號運算時,記錄了運算結果的最高有效位向更高位的進位值,或從更高位的借位值

在這裏插入圖片描述

兩個數據相加時,如98H+98H,將產生進位,這個進位值在8位數中無法保存,但是會由CF位來記錄這個進位值

mov al,98H
add al,al		; 執行後,(al)=30H,CF=1
add al,al		; 執行後,(al)=60H,CF=0

當兩個數據做減法的時候,有可能向更高位借位,如97H-98H,借位後,相當於計算197H-98H,CF位記錄這個借位值

mov al,97H
sub al,98H		; 執行後,(al)=FFH,CF=1
sub al,al		; 執行後,(al)=0,CF=0

11.5 OF標誌

flag的第11位是OF,溢出標誌位,OF記錄有符號數運算的結果是否發生了溢出,如果發生溢出,OF=1,否則OF=0

注意CF是對無符號數運算有意義的標誌位

mov al,98		; CF=0 OF=1
add al,99		; 看作無符號數運算,沒有產生進位
				; 看作有符號數,結果197超出了最大8位有符號數127,有溢出
		
mov al,0F0H		; CF=1 OF=1
add al,88H		; 看作有符號數,按照十進制結果-136,超過-128,溢出

mov al,0F0H		; CF=1 0F=0
add al,88H		

11.6 adc指令

adc是帶進位加法指令,利用CF位上記錄的進位值

格式 adc 操作對象1,操作對象2

mov ax,2
mov bx,1
sub bx,ax	; CF=1
adc ax,1	; (ax)=4 (ax)+1+CF=2+1+1=4

adc指令和add指令相配合可以對更大的數據進行加法運算

計算1EF000H+201000H,結果放在ax(高16位)和bx(低16位)

兩個數都大於16位,不能直接用add

mov ax,001EH
mov bx,0F000H
add bx,1000H
adc ax,0020H		; 兩個數據的低16位運算結束後會設置CF的值爲0或1

處理更大的數據也可以

計算1EF0001000H+2010001EF0H,結果放在ax(最高16位),bx(次高16位),cx(低16位)中

mov ax,001EH
mov bx,0F000H
mov cx,1000H
add cx,1EF0H
adc bx,1000H
adc ax,0020H

將兩個128位數據進行相加

ds:si指向存儲第一個數的內存空間,ds:si指向存儲第二個數的內存空間,由低地址單元到高地址單元依次存放128位數據由低到高的各個字,運算結果存儲在第一個數的存儲空間中

add128:		push ax			; 子程序中用到的寄存器可能對下面程序有影響
			push cx			; 用棧暫存
			push si
			push di
			
			sub ax,ax		; 將CF設置爲0
			
			mov cx,8
	s:		mov ax,[si]
			adc ax,[di]
			mov [si],ax
			
			inc si			; 不能改成add si,2,會產生進位影響CF的值
			inc si
			inc di
			inc di
			
			loop s
			
			pop di			; 注意出棧順序
			pop si
			pop cx
			pop ax
			
			ret

關於inc指令:將指定的操作數的內容加一,再將結果送回到該操作數

inc指令影響SF、AF、ZF、PF、OF標誌位,但不影響CF標誌位

對於內存單元,要指明是字節還是字操作

11.7 sbb指令

帶借位減法指令,利用CF位上記錄的借位值

sbb 操作對象1,操作對象2

功能:操作對象1=操作對象1-操作對象2-CF

利用sbb指令可以對任意大的數據進行減法運算

計算003E1000H-00202000H,結果存放再ax,bx中

mov bx,1000H
mov ax,003EH
sub bx,2000H
sbb ax,0020H

11.8 cmp指令

比較指令,功能相當於減法指令,但不保存結果 ,對標誌寄存器產生影響

格式:cmp 操作對象1,操作對象2

功能:操作對象1-操作對象2,根據計算結果對標誌寄存器進行設置

cmp ax,ax	; 結果爲0,但不在ax中保存
			; zf=1 pf=1 sf=0 cf=0 of=0

可以根據運算後標誌寄存器的結果來得出兩個操作數的大小

對於cmp,也有無符號和有符號數兩種理解

對於無符號運算,根據是否借位以及結果是否爲0判斷大小

對於有符號數的運算,單憑一個標誌無法判斷兩個操作數的大小,因爲存在溢出

如(ah)=22H,(bh)=0A0H,則(ah)-(bh)=34-(-96)=82H,82H是-126的補碼,sf=1,但不能說明(ah)<(bh)

應該在考察sf的同時考察of

以cmp ah,bh爲例

1、sf=1,of=0

沒有溢出,實際結果爲負,所以(ah)<(bh)

2、sf=1,of=1

因爲溢出而導致結果爲負,所以(ah)>(bh)

3、sf=0,of=1

因爲溢出而導致結果爲正,說明(ah)<(bh)

4、sf=0,of=0

沒有溢出,sf=0表示結果非負,所以(ah)>=(bh)

11.9 檢測比較結果的條件轉移指令

jcxz就是一種條件轉移指令

所有條件轉移指令的轉移位移都是[-128,127]

大多數條件轉移指令都檢測標誌寄存器上的相關標誌位(被cmp影響的那些),來決定是否修改IP,這些條件轉移指令通常都和cmp相配合使用

根據無符號和有符號數有兩種檢測方法

根據無符號數比較結果進行轉移的條件轉移指令(檢測zf和cf)

指令 含義 檢測的標誌位
je 等於則轉移 zf=1
jne 不等於則轉移 zf=0
jb 低於則轉移 cf=1
jnb 不低於則轉移 cf=0
ja 高於則轉移 cf=0 and zf=0
jna 不高於則轉移 cf=1 or zf=1

記憶方法:j:jmp e:equal ne:not equal b:below nb:not below

a:above na:not above

編程實現如下功能:如果(ah)=(bh)則(ah)=(ah)+(ah),否則(ah)=(ah)+(bh)

	cmp ah,bh
	je s			; 檢測zf是否爲1
	add ah,bh
	jmp short ok
 s:	add ah,ah
ok:	……

je之前不一定要使用cmp,只關心zf的值

    mov ax,0
    add ax,0	; 執行後zf=1
    je s
    inc ax
s:	inc ax

cmp和je等指令配合使用類似IF語句

data segment
	db 8,11,8,1,8,5,63,54
data ends

編程,統計data段中數值爲8的字節的個數,用ax保存統計結果

        mov ax,data
        mov ds,ax

        mov bx,0			; ds:bx指向第一個字節
        mov ax,0			; 初始化累加器

        mov cx,8
   s:	cmp byte ptr [bx],8
        jne next
        inc ax
next:	inc bx
		loop s
		
; 另一種寫法
		mov ax,data
        mov ds,ax

        mov bx,0			; ds:bx指向第一個字節
        mov ax,0			; 初始化累加器

        mov cx,8
   s:	cmp byte ptr [bx],8
        je ok
        jmp short next
        
  ok:	inc ax
next:	inc bx
		loop s

有符號數的比較原理相同

11.10 DF標誌和串傳送指令

flag的第10位,方向標誌位,在串處理指令中,控制每次操作後si、di的增減

df=0 每次操作後si、di遞增

df=1 每次操作後si、di遞減

格式:movsb

功能:用匯編語言描述

mov es:[di],byte ptr ds:[si] ;只是一個描述

如果df=0 inc si inc di

如果df=1 dec si dec di

將ds:si指向的內存單元中的字節送入es:di中,然後根據df的值進行si和di的遞增或遞減

也可以傳送一個字 movsw 這種情況下,si和di每次加/減2

一般來說,movsb和movsw都和rep配合使用

rep movsb

用匯編語法解釋

s: movsb

​ loop s

可見,rep根據cx的值,重複執行後面的串傳送指令

同理也可以使用rep movsw

CPU提供相應的指令對df進行設置,從而能決定傳送的方向

8086CPU提供兩條指令

cld:將df置0

std:將df置1

編程,將data段中的第一個字符串賦值到後面的空間中

data segment
	db 'Welcome to masm!'
	db 16 dup (0)
data ends

分析可知cx=16 df=0

mov ax,data
mov ds,ax
mov si,0

mov es,ax
mov di,16

mov cx,16
cld		
rep movsb

編程,將F000H段中最後16個字符複製到data段中

data segemnt
	db 16 dup (0)
data ends

因爲是最後16個字符,因此逆序輸入更好

mov ax,0f00h
mov ds,ax
mov si,0ffffh

mov ax,data
mov es,ax
mov di,15		; 指向data段最後一個字節

mov cx,16
std
rep movsb

11.11 pushf和popf

pushf是將標誌寄存器的值壓棧,popf從棧中彈出數據,送入標誌寄存器中

下面的程序執行後,(ax)=?

mov ax,0
push ax
popf				; 使得我們學到過的標誌位爲0
mov ax,0fff0h	
add ax,0010h		; 標誌位的值發生改變
pushf
pop ax				; 標誌寄存器的值賦給ax ax=000000**010*0101b
					; 用*屏蔽沒學過的標誌位
and al,11000101b	; 這兩條將沒學過的標誌位置0,學過的標誌位的值不變	
and ah,00001000b	; ah=45h al=0h

11.12 標誌寄存器在Debug中的表示

在這裏插入圖片描述

標誌 值爲1的標記 值爲0的標記
OF OV NV
SF NG PL
ZF ZR NZ
PF PE PO
CF CY NC
DF DN UP
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章