8086標志寄存器


CPU內部的寄存器中,有一種特殊的寄存器(對於不同的機器,個數和結構都有可能不同)具有以下三個功能:

  • 用來存儲某些相關指令的執行結果
  • 用來為CPU執行相關的指令提供行為依據
  • 用來控制CPU的相關工作方式

這種特殊的寄存器在8086CPU中稱為標志寄存器。8086的標志寄存器有16位,其中存儲的信息通常被稱為程序狀態字(PSW)。

標志寄存器與其他寄存器不一樣,其他寄存器是用來放數據的,都是整個寄存器具有一個含義,而標志寄存器是按位起作用的。

8086中的標志寄存器的結構如下圖所示:

其中1、3、4、12、13、14、15位在8086中沒有使用。另外對於有確切含義的每一位,我們稱為標志位

ZF標志

標志寄存器的第六位是ZF,零標志位。他是記錄相關指令執行后,其結果是否位零。如果為零,那么zf=1,如果不為零,那么zf=0

比如指令:

mov ax, 1
sub ax, 1

執行后,ax的結果為0,所以zf=1

再比如:

mov ax, 2
sub ax, 1

執行后,ax的結果不為0,所以zf=0

在這里,有一點需要注意:在8086的指令集中,有的指令的執行是影響標志位的,比如add、sub、mul、div、inc、or、and等,它們大都是運算指令(進行邏輯或算數運算);有的指令的執行對標志寄存器沒有影響,比如mov、push、pop等,它們大都是傳送指令。

PF標志

標志寄存器的第二位是PF,奇偶標志位。它記錄相關指令執行后,其結果的所有bit位中1的個數是否位偶數。如果是偶數,pf=1,如果位奇數,pf=0

比如指令:

mov al, 1
add al, 10

執行后,al為00001011B,其中有3個1,所以pf=0

再比如:

mov al, 1
or al, 2

執行后結果為00000011B,其中有2個1,所以pf=1

SF標志

標志寄存器的第七位是SF,符號標志位。它記錄相關指令執行后,其結果是否為負。如果為負,sf=1,如果非負,sf=0

這里要明確一點,在計算機中,通常用補碼來表示有符號的數據,計算機中的一個數據既可以看作有符號數,也可以看作無符號數。不管我們如何看待,當CPU在進行運算的時候,就已經包含了兩種含義,也將的到同一種信息來記錄的兩種結果。關鍵在於我們的程序需要那一種。

SF標志,是CPU對有符號數運算結果一種記錄。如果我們將數據當作無符號數來運算,SF標志位則沒有意義,雖然計算過程中影響了他的值。

我個人在這里的更簡單寫的理解是計算后結果的最高位是否為1,為1,這sf=1,否則,sf=0

比如指令:

mov al, 100000001B
add al, 1

執行后結果為10000010B,sf=1,表示如果進行的是有符號運算的話,則結果為負

再比如

mov al, 10000001B
add al, 01111111B

執行后,結果為0,sf=0,表示,如果進行的是有符號運算,這結果為非負

CF標志

標志寄存器的第0為是CF,僅為標志位。一般情況下,在進行 無符號 運算的時候,它記錄了運算結果的最高有效位向更高有效位的進位,或從更高有效位的借位。

比如指令:

mov al, 98H
add al, al  ; 執行后(al)=30H, CF=1, 產生進位
add al, al  ; 執行后(al)=60H, CF=0, 沒有進位,或者說進位為0

再比如:

mov al, 97H
sub al, 98H  ; 執行后(al)=FFH, CF=1, 產生借位
sub al, al   ; 執行后(al)=0, CF=0, 借位為0

OF標志

標志寄存器的第11位是OF,溢出標志位。一般情況下,OF記錄了 有符號數 的運算結果是否發生了溢出。如果發生了溢出,of=1,如果沒有,of=0

{% note success %} 這里一定要注意的是CF和OF的區別,CF是對無符號數運算有意義的標志位,而OF是對有符號數運算有意義的標志位。 它們之間沒有任何關系 {% endnote %}

比如指令:

mov al, 98
add al, 99

執行后,of=1,發生溢出,沒有進位

再比如:

mov al, 0F0H
add al, 78H

執行后:of=0,沒有溢出

DF標志

標志寄存器的第10位是DF,方向標志位。在串傳送指令中,控制每次操作后si、di的增減。

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

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

例如串傳送指令movsb

  • 格式:movsb

  • 功能:執行下面幾步操作:1、((es) x 16 + (di)) = ((ds) x 16 + (si)) 2、如果df=0,(si)=(si)+1, (di)=(di)+1。如果df=1,則(si)=(si)-1, (di)=(di)-1

另外還有movsw,這時候就是一次傳送一個字了,相應的si和di的+1-1也就變更成了+2-2

一般,movsbmovsw一般配合指令rep指令使用,如rep movsb, 相當於

s: movsb  ; 當然啦,在此之前要先設置cx寄存器
   loop s

adc、sbb、cmp、pushf和popf指令

再沒有標志寄存器的時候,我們進行加減運算最多只能進行16位的加減運算,這在實際的應用中顯然是不夠的,那么有了標志寄存器,在結合adcsbb指令,我們就可以進行任意多位的數的加減法了

adc指令

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

  • 指令格式:adc 操作對象1,操作對象2
  • 功能: 操作對象1 = 操作對象1 + 操作對象2 + CF

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

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

更多位數的數相加和以上同理

sbb指令

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

  • 指令格式:sbb 操作對象1,操作對象2
  • 功能:操作對象1 = 操作對象1 - 操作對象2 - CF

比如:計算003E1000H - 00202000H,結果保存在ax,bx中

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

cmp指令

cmp是比較指令,功能相當於減法指令,只是不保存結果。執行后,對標志寄存器產生影響

  • cmp指令格式:cmp 操作對象1,操作對象2
  • 功能:計算操作對象1 - 操作對象2,但不保存結果

經過cmp計算后,我們就可以用jejnejbjnbjajna指令進行跳轉了。

因為比較復雜,在這里就不具體說實現的細節了,具體在更。

pushf和popf指令

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

這兩個指令為直接訪問寄存器提供了一種方法


在這里,我們討論了六種寄存器,另外還有IF,TF,和AF沒有討論,具體再更


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM