【问题标题】:How to determine when zero flag, sign flag, overflow flag and carry flag are set?如何确定何时设置了零标志、符号标志、溢出标志和进位标志?
【发布时间】:2016-08-03 16:00:59
【问题描述】:

整个标志的事情让我很困惑。网络上的定义似乎很简单。对于这一切,我似乎无法得到一个非常好的适用解释。

根据他们的定义, - 进位:表示无符号整数溢出 - 溢出:表示有符号整数溢出 - 零:操作产生零 - 符号:操作产生一个负数

那么下面的句子到底是怎么回事? - 以下指令将设置标志标志:(这里的答案是252不是负数。那么为什么要设置标志标志?)

mov al,0FEh
sub al,2
  • 在 8 位寄存器中添加 7Fh 和 05h 设置溢出标志。(这里的答案是 132。它没有超过 255,为什么会有溢出?)

  • 在8位寄存器中添加0FFh和05h不会设置溢出标志。(答案是300那怎么没有溢出标志呢?在256以上)

  • 在 8 位寄存器中将 5 加到 0FBh 会设置零标志(这里的答案是 256,而不是 0。我知道 8 位只能容纳 255,但“0”从何而来?我只是不明白。)

谁能告诉我我在这里做错了什么以及解决这个问题的正确方法是什么? 谢谢。

【问题讨论】:

  • 您可能想了解负数在二进制补码中的表示方式。
  • “这里的答案是 252 而不是负数” 答案是 0xFC,可以看作 252 或 -4。 Intel手册中对符号标志的描述是“设置等于结果的最高有效位,即有符号整数的符号位。(0表示正值,1表示负值。) ". 0xFC 显然设置了最高有效位。
  • “我知道8位只能容纳255,但“0”是从哪里来的?” 256的8位最低有效位的值是多少?
  • @Michael 0。这是否意味着当第 8 个最低有效位的值为 0 时,零标志才真正打开,而不仅仅是“当操作产生 0 时”?
  • 这个 SO 答案可能有助于理解。它是 4 位,但它同样适用于更宽的寄存器,如 8、16、32、64 等:stackoverflow.com/a/24002847/3857942

标签: assembly


【解决方案1】:

这里的答案是 252 而不是负数。那么为什么要设置标志标志呢?

无符号是252,但无符号不能有符号,所以符号标志只与作为有符号处理的数字有关。不管你如何处理它,处理器总是将它处理为带有符号标志的签名。所以 252 大于 127,因此在 2 的补码中为负数,符号位被置位。

在 8 位寄存器中添加 7Fh 和 05h 设置溢出标志。(这里的答案是 132。它没有超过 255,为什么会有溢出?)

正如你所说,当一个 signed 数字溢出时会设置溢出。有符号的 8 位变量可以从 -128 变为 127。因此从 127 变为 132 是溢出。

在8位寄存器中添加0FFh和05h不会设置溢出标志。(答案是300那怎么没有溢出标志呢?256以上)

同样,溢出是有符号溢出。这会导致 unsigned 溢出,因此 carry 位将被设置。

在 8 位寄存器中将 5 加到 0FBh 会设置零标志(这里的答案是 256,而不是 0。我知道 8 位只能保存 255,但“0”是从哪里来的?我只是不知道)不明白。)

如你所说,8 位可以上升到 255。之后它溢出并且最低 8 位为 0。所以结果为零并且设置了零位。

【讨论】:

  • 非常感谢!我的大脑正在关闭试图弄清楚这一点,但你的答案更有意义。我需要休息一下,更多地处理/练习这个。再次感谢!
【解决方案2】:

另一个优秀的指南:Understanding Carry vs. Overflow conditions/flags 。它有一些很好的分步示例,带有 4 位数字,可以很容易地记住整个事情。它还解释了无符号进位是您在将位解释为无符号时要检查的内容,而有符号溢出是您在将位解释为有符号时要检查的内容。


根据 OP 的评论:

这是否意味着当 8 个最低有效位的值为 0 时,零标志才真正打开,而不仅仅是“当操作产生 0 时”

您需要记住的关键是这是固定宽度整数运算。在 8 位寄存器中,0xFF + 1 确实会产生 0。

在数学术语中,这是modular arithmetic,对于 8 位运算,其模数为 28

所以是的,ZF 是根据dst = (dst+src) % 0x100 设置的。

之所以这样设计,是因为通常您只想知道寄存器是否为零,是否在开始为负数的寄存器上使用inc 朝零计数,或者您是否通过一个开始积极的寄存器。

您仍然可以检查CF==0ZF==1 来检测零而没有进位的情况。 如果ZF 仅在dstCF 均为零时设置,您通常需要另一条指令来测试结果寄存器。


拥有 CF 和 ZF 独立意味着 cmpsub 之后的无符号条件代码的工作方式如下:

JA      Jump if above (CF=0 and ZF=0).
JAE     Jump if above or equal (CF=0).
JB      Jump if below (CF=1).
JBE     Jump if below or equal (CF=1 or ZF=1).

JC      Jump if carry (CF=1).

JE      Jump if equal (ZF=1).

我认为如果 ZF 只能在没有进位的情况下设置,你就无法区分 Above 和 Above-or-Equal。因此,这可能是按照您最初猜测的方式做出设计决定的最具体原因。

这是一个带符号的比较条件:

JLE     Jump  if less or equal (ZF=1 or SF ≠ OF).

完整的条件集在英特尔的 insn 集参考手册( 标签 wiki 中的链接)中,在 jcc(条件代码跳转)指令列表下。

【讨论】:

    猜你喜欢
    • 2013-10-18
    • 2016-02-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多