代码之家  ›  专栏  ›  技术社区  ›  NGSBNC

不理解标志状态寄存器

  •  0
  • NGSBNC  · 技术社区  · 6 年前

    我在帮我的一个朋友做一些计算机建筑理论练习。我们无意中发现了这个关于旗子注册的M.C.练习,不知道怎么回答。事情是这样的:

    “假设您已经在两个无符号整数之间执行了一个加法操作,并且它导致了以下标志设置:cf=0;of=1;zf=0;sf=1。我们可以从这个背景下得出什么结论?为什么?”

    正确的选择表明该操作的结果是正确的,并且在说明原因时,它指出“因为cf等于零”。我的问题是,为什么我们只需要在有其他标志设置为1时考虑进位标志?而且,在对无符号整数执行加法操作时,如何可能将溢出和有符号标志设置为1?

    提前谢谢!

    2 回复  |  直到 6 年前
        1
  •  0
  •   Peter Camilleri    6 年前

    进位标志反映从操作的最重要位产生进位。对于无符号操作数,这样的进位将反映溢出。

    对于其他标志,符号标志仅适用于有符号操作数。溢出标志也是如此,因为它是在由于有符号操作溢出而导致符号更改不正确时设置的。

    当结果为零且与溢出检测无关时,将设置最后一个标志零。

    在您给出的示例中,操作数是无符号的,进位标志是清除的。所以没有发生溢出。

        2
  •  1
  •   Peter Cordes Steve Bohrer    6 年前

    cf=0表示加法没有换行。见 this article on Understanding Carry vs. Overflow conditions/flags 是的。

    你可以说加法总是给出正确的 (a + b) modulo 2^32 结果,除非你的电脑坏了。如果加法被包围,则结果与两个输入的无穷精度数学和不同,但它是正确的模运算(免费进行模运算)。所以你必须小心你所说的“正确”!(显然,在本例中,赋值是指数学整数和。)

    术语在这里是混乱的,因为“算术溢出”作为一个一般概念(当数学上精确的结果不适合目的地时)包括有符号和无符号整数情况。在x86上(就像所有正常的CPU一样),行为是有圈套的。但是无符号的包装称为进位,而有符号的包装称为溢出。

    对于浮点,正常的溢出行为是饱和到正负无穷大。这说明了溢出作为一个一般概念和作为整数溢出的特定行为的总括之间的区别。

    有些体系结构具有饱和加法指令,饱和是整数溢出行为。x86具有 paddusw 指令(和有符号版本),用于整数simd,但不用于标量gp寄存器,如eax。

    在C语言中,无符号溢出被定义为环绕,但有符号溢出是未定义的行为(编译器可以在不发生这种情况的假设下进行优化)。

    MIPS有一个 add 捕获有符号溢出的指令。(C编译器通常使用 addu 不过,对于所有的东西,因为mips是2的补码机,所以它的二进制操作相同,只是捕获行为不同。他们只能安全地使用 添加 在添加匹配变量值时捕获有符号溢出ub,该变量值将出现在c抽象机中,而不是优化后。而且有些Bithack代码不安全地依赖于C语言中的有符号环绕,所以用户通常希望环绕而不是陷阱。MIPS没有任何类型的标志寄存器,因此他们决定为溢出检查添加提供硬件支持。)


    其余的标志将为您提供有关结果的更多信息

    其中一些很少有用,但我的回答是“你能得出什么结论?”是的。

    zf=0告诉您结果是非零的 是的。如果你在实施 if (a + b != 0) ,可以对add设置的标志进行分支(或cmov或setcc),而不是单独执行 test eax,eax 是的。除了cmp或test之外,在指令之后使用zf一点也不少见。

    sf=1告诉您结果是>=最大值的一半 是的。即无符号结果有其高位集。对于8位加法,sf=1表示结果为>=128。 这有时可以为您保存一条测试或比较指令。如果将寄存器作为左移位添加到自身,则cf将位移出,sf将当前高位移出。我想告诉你一些关于

    =1(SF=1,CF=0)告诉你,两个输入都小于最大无符号值的一半。 是的。(即,如果解释为有符号数字,则为正。结果的有符号解释为负,因此结果的有符号解释为pos+pos=neg,这只能通过溢出发生)。

    在我写的任何一篇asm中,我从来没有利用过最后一篇,而且它似乎不太可能有用。我所知道的任何架构都没有同时考虑cf和of的分支条件。因此,只有当您已经在cf=0分支中时,它才有用。x86签署了较大/较小的分支 that check SF != OF ,但仍然不能用一条指令检查sf==1和of==1。所以如果你想检查一下,你会 OR 两个输入并检查SF。