程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> C++ 通過二進制詳細查看各標志位

C++ 通過二進制詳細查看各標志位

編輯:C++入門知識

在比如使用匯編指令如:ADC, SBB等指令時,我們為了心裡那份好奇感就不得不去了解下FLAG寄存器(EFL)裡面的東西。通過二進制詳細的查看各標志位的值。然後這些需要用到標志寄存器的指令等就一目了然了。 - -

迫不及待寫了段測試代碼來看看其中的秘密:
#include <iostream>
int main( void )
{
    __asm
    {
        mov al, 0xff
        mov dl, 0x01

        add al, dl
        adc al, dl
    }
    return 0;

}
還是用內斂匯編的形式來說明。 這裡想AL給了一個0xff,為什麼給AL為0xff是為了能夠進位,我覺得這個數很方便,當然你可以弄成其它數字,只要兩個數之和發生進位就行(這裡為了測試進位的CF位)。DL我給了個0x01之和剛好進位且可以測試奇偶和零值。

我們在上邊紅色的代碼出打下斷點,然後運行程序斷到這裡,然後打開VC的寄存器窗口,我們可以看到各個寄存器的值。這裡著重看EFL = ? 標志寄存器的值。

這裡查看標志寄存器各標志位的值有兩種查看方法:

第一: 把EFL的值轉成二進制,通過二進制位來查看個標志位的值。

第二: 如果你的寄存器窗口裡面沒有顯示標志的話,可以在寄存器窗口裡面點鼠標右鍵,選擇“標志”就會顯示個標志位的值了,形如:
OV = ? UP = ? EI = ? PL = ? ZR = ? AC = ? PE = ? CY = ?

這裡有個對照表:

可以根據EFL的二進制數據進行位對照就知道各個標志位的值了。

我們在開始的斷點那裡看到標志的各值:
OV = 0 UP = 0 EI = 1 PL = 0 ZR = 0 AC = 0 PE = 0 CY = 0
這裡EI = 1表示處於中斷狀態  - -。。
再看EFL = 0x00000202(1000000010) 對號入座:
1    0   0   0   0   0    0    0    1    0
IF  TF  SF ZF      AF         PF        CF
只有IF(EI|DI)為1, VC寄存器窗口裡邊只用括號中的一種來表示。。。

好!看完了各標志位,下面按F10執行完ADD AL, DL這句。

看看各標志位的值:OV = 0 UP = 0 EI = 1 PL = 0 ZR = 1 AC = 1 PE = 1 CY = 1

再來看看標志寄存器的值: EFL = 0x00000257(1001010111)
1    0    0    1   0   1   0   1   1   1
IF  TF   SF  ZF      AF       PF      CF

這裡IF表示已經中斷, ZF表示目的操作數結果為零, AF表示(AL為一個字節)相加進行到一半(低4位)有沒有向另一半(高4位)進位,也可以表示是否借位(減法)。 PF表示為偶數, CF表示已經發生進位,也可以表示借位。

再按F10執行完 ADC AL, DL 這句, ADC是帶進位的加法, 結果為: AL = AL DL CF。

這時AL: 0 0x1 1 = 0x02。
標志位值: OV = 0 UP = 0 EI = 1 PL = 0 ZR = 0 AC = 0 PE = 0 CY = 0 這裡就不做解釋了吧 - -

這裡特別說下:

DF:是控制標志位為方向標志,在串處理指令中控制處理信息的方向用。當DF為1時,每次操作後使變址寄存器SI和DI減小,這樣就使串處理從高地址向低地址方向處理。當DF為0時相反。。

TF:當TF被置為1時,CPU進入單步執行方式,即每執行一條指令,產生一個單步中斷請求。這種方式主要用於程序的調試。

在這裡我們要獲得標志寄存器的值的話有以下這些指令:

LAHF     標志寄存器傳送,把標志裝入AH.
SAHF     標志寄存器傳送,把AH內容裝入標志寄存器.
PUSHF   標志入棧.
POPF     標志出棧.
PUSHD  32位標志入棧.
POPD    32位標志出棧.

在上邊的AF位讓我想到用ADC或者SBB來進行進位或借位的一個常用方法就是,我們可以在加/減兩個4字節的數據是可以高2字節、低2字節分別相加。通過ADC/SBB可以在計算高2字節想加/減時獲得CF值,用來進行進位或借位。

例如:
mov ax, low1
add ax,  low2
mov sumLow, ax
mov ax, high1
adc  ax, high2
mov sumHigh, ax

這樣就實現了進位, low1, low2分別表示第一個數和第二個數的低2字節, high1, high2分別表示第一個數和第二個數的高2字節。 當 add ax,  low2 產生了進位時, CF = 1。 後邊在執行高2字節相加時用ADC會去獲取CF的值。 sumHigh = high1 high2 CF。 最後得到的數就是高2字節之和(sumHigh)與低2字節之和(sumLow)的合並。形如:

DWORD var = 0;
WORD   sumHigh = 0;
WORD   sumLow = 0;

C :
var |= sumHigh;
var <<= 16;
var |= sumLow;
ASM:

movzx eax, word ptr[ sumHigh ]
shl   eax, 10h
or    eax, dword ptr[ sumLow ]
mov   var, eax

這便實現了進位。 借位的道理是一樣的, 這裡就不闡述了。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved