標誌暫存器
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決定。