C++/Debug模式查看EFL(标志寄存器)祥解

系统 2567 0

在比如使用汇编指令如: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 =?

这里有个对照表:

asm

可以根据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 PFCF

只有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

addax, low2

mov sumLow, ax

mov ax, high1

adc ax, high2

mov sumHigh, ax

这样就实现了进位, low1, low2分别表示第一个数和第二个数的低2字节, high1, high2分别表示第一个数和第二个数的高2字节。 当 addax, low2 产生了进位时, CF = 1。 后边在执行高2字节相加时用ADC会去获取CF的值。 sumHigh = high1 + high2 + CF。 最后得到的数就是高2字节之和(sumHigh)与低2字节之和(sumLow)的合并。形如:

DWORDvar = 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

这便实现了进位。 借位的道理是一样的, 这里就不阐述了。。 - -

终于写完了~~累死了。。 有什么错误希望大家帮我纠正 - -

C++/Debug模式查看EFL(标志寄存器)祥解


更多文章、技术交流、商务合作、联系博主

微信扫码或搜索:z360901061

微信扫一扫加我为好友

QQ号联系: 360901061

您的支持是博主写作最大的动力,如果您喜欢我的文章,感觉我的文章对您有帮助,请用微信扫描下面二维码支持博主2元、5元、10元、20元等您想捐的金额吧,狠狠点击下面给点支持吧,站长非常感激您!手机微信长按不能支付解决办法:请将微信支付二维码保存到相册,切换到微信,然后点击微信右上角扫一扫功能,选择支付二维码完成支付。

【本文对您有帮助就好】

您的支持是博主写作最大的动力,如果您喜欢我的文章,感觉我的文章对您有帮助,请用微信扫描上面二维码支持博主2元、5元、10元、自定义金额等您想捐的金额吧,站长会非常 感谢您的哦!!!

发表我的评论
最新评论 总共0条评论