1. 程式人生 > >匯編語言——標誌寄存器

匯編語言——標誌寄存器

cpu pla play 都是 aps 技術 影響 close 加法

標誌寄存器

flag 和其他寄存器不一樣,其他寄存器是用來存放數據的,都是整個寄存器具有一個含義。

而flag寄存器是按位起作用的,也就是說,它的每一位都有專門的含義,記錄特定的信息。

8086CPU的flag寄存器的結構:

技術分享圖片

ZF標誌

flag的第6位是ZF,零標誌位(zero flag)。

它記錄相關指令(add、sub、mul、div、inc、or、and操作)執行後,結果是否為0 。ZF = 1結果不為0,ZF = 0結果為0。

mov、push、pop等傳送指令不修改標誌寄存器的信息。

PF標誌

flag的第2位是PF,奇偶標誌位。

它記錄指令執行後,結果的所有二進制位中1的個數是否為偶數

,如果為偶數則PF = 1,為奇數,PF = 0。

SF標誌

flag的第7位是SF,符號標誌位。

它記錄指令執行後,結果是否為負(就是看它二進制的第一位是不是1),如果為負數則SF = 1,結果為正,SF = 0。

例如:

我們可以將add指令進行的運算當作無符號數的運算,那麽add指令相當於計算129+1,結果為130(10000010B),

也可以將add指令進行的運算當作有符號數的運算,那麽add指令相當於計算-(125+1)(補碼=-(原碼取反+1)),結果為-126(10000010B)。

技術分享圖片

CF標誌

flag的第0位是CF,進位標誌位。

一般情況下,在進行無符號數運算的時候,它記錄了運算結果的最高有效位向更高位的進位值

,或從更高位的借位值

比如,兩個8 位數據:98H+98H,將產生進位

由於這個進位值在8位數中無法保存,其實CPU在運算的時候,並不丟棄這個進位值,而是記錄在一個特殊的寄存器的某一位上。

8086CPU 就用flag的CF位來記錄這個進位值

比如,兩個 8 位數據:97H-98H,將產生借位,借位後,相當於計算197H-98H。

flag的CF位也可以用來記錄這個借位值

CF在減法時記錄借位,加法時記錄進位

判斷加法是否有進位:兩個八位數據相加是否大於255(2^8)

判斷減法是否有借位:兩個八位數據相加是否小於-255

OF標誌

在進行有符號數運算的時候,如結果超過了機器所能表示的範圍稱為溢出。

mov al,98

add al,99

add指令運算的結果是(al)=0C5H ,因為進行的是有符如果我們用add 指令進行的是有符號數運算,則98+99=-59這樣的結果讓人無法接受。

造成這種情況的原因,就是實際的結果 197,作為一個有符號數,在 8 位寄存器al中存放不下。

由於在進行有符號數運算時,可能發生溢出而造成結果的錯誤。

則CPU需要對指令執行後是否產生溢出進行記錄。

flag的第11位是OF,溢出標誌位。

一般情況下,OF記錄了有符號數運算的結果是否發生了溢出。如果發生溢出,OF=1,如果沒有,OF=0。

一定要註意CF和OF的區別:

CF是對無符號數運算有意義的標誌位,對於無符號數運算,CPU用CF位來記錄是否產生了進位;

而OF是對有符號數運算有意義的標誌位,對於有符號數運算,CPU 用 OF 位來記錄是否產生了溢出,當然,還要用SF位來記錄結果的符號。

判斷OF是否為1的方法:如果兩個正8位數據相加,值為負數時或兩個負8位數據相加,值為時數時OF的值為1

技術分享圖片

技術分享圖片
 1               al                 CF    OF    SF    ZF    PF
 2 sub al,al     0h/0000 0000b      0     0     0     1     1
 3 mov al,10h    10h/0010 0000b     0     0     0     1     1
 4 add al,90h    a0h/1010 0000b     0     0     1     0     1
 5 mov al,80h    80h/1000 0000b     0     0     1     0     1
 6 add al,80h    0h/0000 0000b      1     1     0     1     1
 7 mov al,0fch   0fch/1111 1100b    1     1     0     1     1
 8 add al,05h    1h/0000 0001b      1     0     0     0     0
 9 mov al,7dh    7dh/1111 1101b     1     0     0     0     0
10 add al,0bh    88h/1000 1000b     0     1     1     0     1
View Code

指令

adc指令

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

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

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

比如:adc ax,bx 實現的功能是:(ax)=(ax)+(bx)+CF

我們來看一下兩個數據:0198H和0183H如何相加的:

01 98

+ 01 83

1

-----------------

03 1B

可以看出,加法可以分兩步來進行:

(1)低位相加;

(2)高位相加再加上低位相加產生的進位值。

下面的指令和add ax , bx具有相同的結果:

add al,bl   ; 低位相加產生進位

adc ah,bh  ; 再用adc,高位相加時,加上進位

看來CPU提供 adc 指令的目的,就是來進行加法的第二步運算的

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

sbb指令

sbb是帶借位減法指令,它利用了CF位上記錄的借位值。

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

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

比如:sbb ax,bx

實現功能:(ax) = (ax) – (bx) – CF

cmp指令***

cmp 是比較指令,功能相當於減法指令,只是不保存結果。

cmp 指令執行後,將對標誌寄存器產生影響

可以通過其他相關指令通過識別這些被影響的標誌寄存器位來得知比較結果。

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

功能:計算操作對象1–操作對象2 但並不保存結果,僅僅根據計算結果對標誌寄存器進行設置。

其實,我們通過cmp 指令執行後,相關標誌位的值就可以看出比較的結果。

例如:cmp ax,bx

技術分享圖片

以上可以得出:

技術分享圖片

上面有CF的值可以判斷大小,那麽通過OF和SF也可以知道(了解就行)

(1)如果SF=1,而OF=0

OF=0,說明沒有溢出,邏輯上真正結果的正負=實際結果的正負;

因SF=1,實際結果為負,所以邏輯上真正的結果為負,所以(ah)<(bh)。

(2)如果SF=1,而OF=1

OF=1 ,說明有溢出,邏輯上真正結果的正負≠實際結果的正負(即OF只要是1,那麽邏輯結果就是反的)

因 SF=1 ,實際結果為負,實際結果為負,而又有溢出,這說明是由於溢出導致了實際結果為負,

簡單分析一下,就可以看出,如果因為溢出導致了實際結果為負,那麽邏輯上真正的結果必然為正。這樣,SF=1,OF = 1 ,說明了(ah)>(bh)。

(3)如果SF=0,而OF=1

OF=1 ,說明有溢出,邏輯上真正結果的正負≠實際結果的正負;

因SF=0,實際結果非負,而OF=1說明有溢出,則結果非 0 ,所以,實際結果為正。實際結果為正,而又有溢出,這說明是由於溢出導致了實際結果非負,

簡單分析一下,就可以看出,如果因為溢出導致了實際結果為正,那麽邏輯上真正的結果必然為負。這樣,SF=0,OF = 1 ,說明了(ah)<(bh)。

(4)如果SF=0,而OF=0

OF=0,說明沒有溢出,邏輯上真正結果的正負=實際結果的正負;

因SF=0,實際結果非負,所以邏輯上真正的結果必然非負。所以(ah)≥(bh)。

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

轉移時 轉移指令 + 標號

技術分享圖片

技術分享圖片

技術分享圖片

技術分享圖片

匯編語言——標誌寄存器