前言
感觉好长一段时间没写文章了,希望写文章的水平不要退步得太快。今天讲标志寄存器(EFLAGS)。当然只挑几个位来讲。这标志寄存器挺重要,关系到程序怎么跳转,也是学习后面JCC的基础,搞懂这个,对理解C语言中的if等判断语句也有帮助。
今天介绍的标志寄存器有32位,每一位都有它具体的含义,在网上个很全的解析图。
本id针对今天讲的,稍微做了些简化。凑合着看吧,注意蓝色部分的东西是固定的。
为了让大家有更深刻的理解,在OD上,标志寄存器在EFL那一行中。
注意:OD上已经把标志寄存器(EFL)中的内容进行了拆分,得到对应的C、P、A、Z、S、T、D、O几个位。大家有空可以试着把EFL中的值转成二进制,看看对应的位的值对不对。
几个标志的介绍
进位标志CF(Carray Flag):
如果运算(这里的运算是指那些逻辑运算、加、减这些,mov指令不是运算。)结果的最高位产生一个进位或借位,则CF的值是1,否则是0。
我们可以在OD上进行测试:为了方便查看测试的结束,可以双击标志寄存器后面的值,就可以修改寄存器中的值。
测试1:0xef + 0x2
mov al,0xef
add al,0x2
因为16进制的ef和2相加,计算过程如下图,可以知道运算后,最高为没有产生进位或借位,所以CF位是0.
在OD上测试:
按F8运行后的结果如下图:
测试2:1 - 2
mov al,0x1
sub al,0x2
计算过程如下图,可以知道运算后,最高位产生结尾,所以CF位是1。
在OD上进行测试:
按F8运行后的结果如下图。
其他的就自己测试了,注意数据宽度,只有数据宽度确定了,最高位才能确定。
2.奇偶标志PF(Parity Flag):
在运算的结果中,最低有效字节(即最低的8位)中“1”的个数的奇偶性。如果“1”的个数为偶数,则PF的值为1,否则为0。这个就不进行测试了。比较少用。
3.辅助进位标志AF(Auxiliary Carry Flag):
在发生如下的几种情况时,AF位为1,否则为0。
(1)在字节(8位)操作中,发生低4位向高4位进位或借位。
(2)在字(16位)操作中,发生低字节向高字节进位或借位。
测试1:
mov al,0x4E
add al,0x2
运算过程如下图:al是8位寄存器,可以发现红色的E有没有进位或借位,很明显E是向高位进位的,所以运算后AF位是1 。
在OD上的测试如下。
按F8运行后的结果如下:
根据上面的测试,可以发现辅助位的判断是根据操作的宽度,主要看宽度位数中间那一位是否向前进位或借位。
4.零标志ZF(Zero Flag):
如果运算的结果是0,则ZF的值为1,否则为0。
测试:
XOR eax,eax
两个相同的数异或运算后的结束是0
在OD上的测试如下:
按F8运行后,可以看到eax寄存器中的值为0,ZF位的值为1 。
5.溢出标志OF(Overflow Flag):
有符号数进行加减运算的结束是否溢出。即运算的结果如果超过当前运算位数所能表示的范围,则溢出,OF位的值为1,否则为0。如果没有看过之前本id写的关于数据宽度的文章,建议看看。
测试:
mov al,0x1
sub al,0x2
1-2的结果肯定没有超过8位数据所能表示的负数的范围,没有溢出,所以OF位是0.
按F8运行后的结果如下图:
CPU是如何计算OF位的呢?
(1)判断符号位是否有进位,若有进位,则为1,否则为0.
(2)判断最高有效数值位(即符号位的后一位)是不向符号位产生进位,有进位则为1,没有则为0.
(3)最后把(1)(2)得到的结果进行异或运算,运算的结束就是OF的值。
就写这么多吧!
写于2020.6.7 23:44