奥普瓯江 发表于 2018-12-27 18:01:10

监测点11.2

本帖最后由 奥普瓯江 于 2018-12-27 18:14 编辑

                                CF OF SF ZF PF
1. sub al, al                NC NV PL ZR PE
2. mov al, 10h                NC NV PL ZR PE
3. add al, 90h                NC NV PL NZ PE
4. mov al, 80h                 NC NV PL NZ PE
5. add al, 80h                 CY OV PL ZR PE
6. add al, 0fch                CY OV PL ZR PE
7. add al, 05h                CY NV PL NZ PO
8. mov al, 7dh                CY NV PL NZ PO
9. add al, 0bh                NC OV NG NZ PE
这里面有个疑问地7行和第8行
在第六行中al被赋予了FC16进制的,换算程2进制的话应该是1111 1100,第7行中的add al, 05h中05换算成2进制应该是0000 0101这就相当于:


1111 1100加上0000 0101他应该等于1 0000 0001,在这里产生了溢出符号位改变了但是OF显示的是NV(NV代表没有溢出)为什么呢?,

千锦襄 发表于 2018-12-27 19:37:49

表示不懂,这是什么

行客 发表于 2018-12-27 20:50:50

本帖最后由 行客 于 2018-12-27 23:51 编辑

以下是我用了将近2个小时,本着以最直白的语言,弄到将近深夜12点才写完的材料,希望你能认真看,认真理解。因为这里我不只是解释了你上面的问题,而是从根本上帮助你进行理解:

计算机数值一律用补码来表示(存储)。0xFC(即上面的0fch)在al中,表示为补码,是负数,即-4;0x5(即上面的05h)是正数5。所以add后结果为1。你可以看一下执行完第7行后al是0x1(EAX显示为FFFFFF01)。

如果还有疑问,你可以测试一下以下三条指令:

SUB   AL, AL
MOV    AL,0FFh
MOV    AL,02h

执行完后看一下al结果和标志位。

我再详细给你一下,你之所以会提出这个问题,是因为你对CF和OF没有区分开:

CF为进位标志(Carry Flag),OF为溢出标志(Overflow Flag)。

我们通常理解的溢出是,我们假设有一个杯子,然后向杯子倒水,如果水满了,这就是溢出了。那么这个杯子到底有多大?按照你上面的理解,你会不会觉得OF和CF没什么区别?其实,这里面涉及到杯子真实大小的问题。

不过,真实的情况是,虽然,我们通常认为溢出(上溢),认为就是因为进位时当前存储格式(1B、2B、4B等)的位数(8bit、16bit、32bit)不够而引起的。比如8位寄存器:11111111B+1B=100000000B超过了八位的1被认为是溢出寄存器(放不下),当然这里也是进位进上去的1。但是实际上,CF标志位的进位标志与OF标志位的溢出标志是不同的概念。

那么好,为了好理解,接下来我们假设寄存器为8位寄存器(al)。

首先,你要理解,CF针对的是无符号数运算(将寄存器中的操作数都看作是无符号数) ;OF针对有符号数运算(将寄存器中的操作数都看作是有符号数) 。有符号无符号指的是最高位是否(注意,我这里说的是“是否”)是符号位,即我们是是以原码的形式(即无符号数,或者说就是正数)看待这个操作数还是以补码的形式(有符号数,有正数也有负数)看待这个操作数。

你要记清楚,CF看的是无符号运算(原码),OF看的是有符号运算(补码)。

如果以原码的形式看待操作数,也就是从CF角度去看,那么这个数的范围是00h~FFh,也就是十进制0~255(注意,计算机中的无符号数(所谓的正数)包含0)。
如果以补码的形式看待操作数,也就是从OF角度去看,那么这个数的范围80h~7Fh,也就是十进制-128~127。注意,80h~FF等同于-128~-1;0~7F等同于0~127。

这就是杯子的真实大小。

我再补充一句,加强你的理解:一个操作数在寄存器或内存中,这个数是无符号数还是有符号数,不是这个数或者是计算机决定的,而是我们程序员来决定的。所以,到底溢出不溢出,如果我们把这个数要看成无符号数,那么我们就要去看CF;如果看成有符号数,那么就要去看OF。

所以,我们的结论来了

CF和OF其监测的结果数据范围是不同的:

以8位寄存器作为操作种数据来源为例,如果一个运算的结果最终超过[-128,127]无论是大于127还是小于-128就被认为是溢出,OF被置为1,如果结果在[-128,127]就认为没溢出OF被置为0,。
而对于OF:如果计算的结果超过的范围,就有进位,CF就被置为1,如果结果再[-128,127]范围内,就是没有进位CF被置为0。

说到这里你应该明白了。为了继续加强你的理解,我再举几个例子:
(1)、8H+8H:
对于signed(有符号数):(8)+(8)=16,没超过[-128,127]的范围,OF为0
对于unsigned(无符号数):(8)+(8)=16,没超过的范围,CF为0
(2)、80H+81H:
对于signed:(-128)+(-127)=-255,超过[-128,127]的范围,OF为1
对于unsigned:(128)+(129)=257,超过的范围,CF为1
(3)、FCH+05H:
对于signed:(-4)+(5)=1,没有超过[-128,127]的范围,OF为0
对于unsigned:(252)+(5)=257,超过的范围,CF为1
(4)、7FH+2H:
对于signed:(127)+(2)=129,超过[-128,127]的范围,OF为1
对于unsigned:(127)+(2)=129,没超过的范围,CF为0

你一定要记住,操作数看成有符号还是无符号,不是计算机决定的,是你作为程序开发人员决定的。所以,如果你认为这个数是无符号数,那么你就看CF,不用理会OF;如果你人为这个数是有符号数,那么你就看OF,不用理会CF。OF、CF的0与1是没有直接联系的。只要记住有符号与无符号的数据范围,并且记住OF是对于有符号数,CF对于无符号数即可。

人造人 发表于 2018-12-27 23:38:11

https://fishc.com.cn/thread-50833-1-1.html

奥普瓯江 发表于 2018-12-28 14:06:40

人造人 发表于 2018-12-27 23:38
https://fishc.com.cn/thread-50833-1-1.html

谢谢明白了
页: [1]
查看完整版本: 监测点11.2