1. 程式人生 > 其它 >標誌暫存器

標誌暫存器

EFLAGS暫存器

進位標誌CF(Carry Flag)

如果運算的最高位產生了一個進位或借位,那麼,其值位1,否則其值為0

mov AL,0FF

ADD AL,1

0X80+0X40

0X80:0 1000 0000

0X40:0 0100 0000

結果為:1100 0000 最高位並沒有發生變化,於是CF位為0

0x80-0x40

1000 0000
0100 0000

注意這裡產生了借位1000 0000中的加黑部分

而非0 1000 0000這裡的最高位

結果為:0100 0000 最高位並沒有發生變化,於是CF位0

0x80-0x81

0x80: 1000 0000
0x81: 1000 0001

結果為:1111 1111=-1,最高位被借位,於是CF位為1

奇偶標誌PF(Parity Flag)

奇偶標誌PF用於反映運算結果中最低有效位元組中"1"的個數的奇偶性
如果"1"的個數為偶數,則PF的值為1,否則其值為0

指令 指令執行後的AL的結果 PF
MOV AL,3 0011 1
ADD AL,3 0110 1
ADD AL,2 1000 0
例:
MOV AX,803
ADD AX,1

0x803:0000 1000 0000 0011
執行結果:
0x804:0000 1000 0000 0100 總共2個1,PF應為1,但實際執行結果PF為0
因為PF是根據最低有效位元組來看,即804後面04的這部分
04: 0000 0100總共1個1,所以PF為0

輔助進位標誌AF(Auxiliary Carry Flag)

在發生以下情況時,輔助進位標誌AF的值被置為1,否則其值為0:

  • 在字操作時,發生低位元組向高位元組進位或借位時
  • 在位元組操作時,發生低4位向高4位進位或借位時
    AF與資料寬度
    相關
    32位時 FFFF F FFF
    16位時 FF F F
    8位 F F
    加黑的字型位AF標誌位判斷的位置,如果該位置要向前進位則AF為1,否則為0,和CF相似,不過判斷的位置不同
    32位例:
MOV EAX,55EEFFFF

ADD EAX,2

16位例:

MOV AX,5EFE

ADD AX,2

8位

MOV AL,4E

ADD AL,2

零標誌ZF(Zero Flag)

零標誌ZF用來反映運算結果是否為0
如果運算結果為0,則其值為1,否則其值為0
作用:在判斷運算結果是否為0時,可以使用此標誌位。
例子:

XOR EAX,EAX

通過xor將eax清零,會改變zf標誌位為1

MOV EAX,0

通過MOV將EAX賦值為0,非運算,不改變zf標誌位

符號標誌SF(Sign Flag)

符號標誌SF用來反映運算結果的符號位,它與運算結果的最高位相同
例子:

MOV AL,7F
ADD AL,2

溢位標誌OF(Overflow Flag)

溢位標誌OF用於反映有符號數加減運算所得結果是否溢位
注意與CF區分
最高位進位與溢位得區別:

進位標誌表示無符號數運算結果是否超出範圍。

溢位標誌表示有符號數運算結果是否超出範圍。

溢位主要是給有符號數使用的,在有符號號的運算中,有如下的規律:

  • 正+正 = 正 如果結果是負數,則說明有溢位。

  • 負 + 負 = 負 如果結果是正數,則說明有溢位。

  • 正 + 負 永遠不會有溢位。

無符號、有符號都不溢位例

MOV AL,8
ADD AL,8

AL的資料寬度為8,即
無符號數範圍為0FF即0255
8 + 8 = 16在0~255內 不溢位
有符號數的範圍為:
正數:0~7F 即0~127
負數:80~FF 即-128~0
8+8=16 在0~127內 兩個正數相加的結果仍然為正數,不溢位。

無符號溢位,有符號不溢位例

MOV AL,0FF
ADD AL,2

無符號數時
FF+2 = 255+2 = 257 在0~255外,溢位
有符號數時
FF+2 =-1+2 = 1
正 +負 永遠不會溢位。

無符號不溢位,有符號溢位例

MOV AL,7F
ADD AL,2

無符號數時

7F+2=127+2=129 在0~255內 不溢位

有符號數時
7F+2=0X81在80~FF(負數範圍)內,兩正數相加結果為負數,溢位

無符號、有符號都溢位

MOV AL,0FE
ADD AL,80

無符號數時

FE+2=254+2=256=0X100 在0~255外溢位

有符號數時

FE+2=0X100在0~FF外,溢位

CPU如何計算OF位

首先引入兩個概念:

  • 符號位有進位
  • 最高有效數值位向符號位產生的進位
    對於一個有符號數:如0X80和0XC0
    符號位有進位
    0x80:1 000 0000

0XC0: 1100 0000

最高有效數值位向符號位產生的進位

0X80: 1 0 00 0000
0Xc0:1 1 00 0000
接下來看一組彙編指令

MOV AL,80
ADD AL,0C0

就是運算0x80+0xc0
0x80: 1 0 00 0000

0xc0: 1 1 00 0000

符號位1+1有產生進位,於是符號位有進位為1

最高有效數值位向符號位產生的進位0+1沒有產生進位,於是最高有效數值為向符號位產生的進位為0

OF = 符號位有進位xor最高有效數值位向符號位產生的進位

OF = 1 xor 0 = 1 所以此時OF=1

方向標誌DF(Direction Flag)

DF:方向標誌位
cld指令 清除DF標誌位,結果為0 std指令設定DF標誌位DF,結果為1,
DF = 1時串操作作為減 地址方式 DF = 0 為增地址方式

符號 含義
r 暫存器
m 記憶體
imm 立即數
r8 8位通用暫存器
m8 8位記憶體
imm8 8位立即數

ADC指令:帶進位加法

格式:ADC R/M,R/M,R/M//IMM兩邊不能同時為記憶體,資料寬度要一樣

MOV AL,1
MOV CL,2
手動修改為CF為1
ADC AL,CL

計算結果為4,原本1+2=3,但是現在變成了4,注意與ADD的區別就在於進位

SBB指令:帶錯位減法

格式:SBB R/M,R/M/IMM兩邊不能為記憶體資料寬度要一樣

MOV AL,4
MOV CL,2
手動修改CF為1
SBB AL,CL

計算結果為1,原本4-2=2,但是現在變成了1,注意與SUB的區別就在於進位

XCHG指令:交換資料

格式:XCHG R/M,R/M兩邊不能同時為記憶體,資料寬度要一樣

XCHG AL,CL
XCHG DWORD PTR DS:[12FFC4],EAX
XCHG DWORD PTR DS:[12FFC4],AL

MOV AL,1
MOV CL,2
XCHG AL,CL

執行前:AL=1 CL=2
執行後:AL=2 CL=1

MOVS指令:移動資料 記憶體-記憶體

BYTE/WORD/DWORD
MOVS指令常用與複製字串

MOVS BYTE PTR ES:[EDI],BYTE PTR DS:[EST] 簡寫成MOVSB

MOVS WORD PTR ES:[EDI],WORD PTR DS:[ESI] 簡寫成MOVSW

MOVS DWORD PTR ES:[EDI],DWORD PTR DS:[ESI] 簡寫為:MOVSD

MOV EDI,12FFD8
MOV ESI,12FFD0
MOVS DWORD PTR ES:[EDI],DWORD PTR DS:[ESI]

執行後,EDI記憶體裡的值被修改為ESI記憶體裡的值,且EDI和ESI各加4
為什麼各加4?
和DWORD資料寬度相關,如果為WORD則各加2
為什麼執行完是加而不是減?
由DF(Direction Flag)方向標誌位決定,當DF位為1時為減,當DF位為0時,則為加

STOS指令

將AL/AX/EAX的值儲存到[EDI]指定的記憶體單元,和資料寬度相關

STOS BYTE PTR ES:[EDI]  將AL儲存到[EDI]
STOS WORD PTR ES:[EDI]  將AX儲存到[EDI]
STOS DWORD PTR ES:[EDI] 將EAX儲存到[EDI]

注意這裡使用的是ES:之前寫的都是DS:

當後面為[EDI]時要使用ES: 這和後面學的段暫存器相關,先記住

儲存完資料後EDI地址的變化也受DF標誌控制,1減 0增

REP指令

按計數暫存器(ECX)中指定的次數重複執行指令

MOV ECX,10
REP MOVS DWORD PTR ES:[EDI],DWORD PTR DS:[ESI] 也可以寫成 REP MOVSD

這裡的10為十六進位制,也就是0x10=16
程式碼將會重複執行16次,並且不會往同一個地方覆蓋,因為每執行一次EDI和ESI都會變化,變化方向由DF決定。