简体   繁体   English

为什么零旗存在?

[英]Why does the Zero Flag exist?

I understand the use of the carry and overflow flags exist for error checking in arithmetic, but why is the zero flag useful to the system/programmer?我知道在算术中使用进位和溢出标志进行错误检查,但为什么零标志对系统/程序员有用?

An extremely common task for any computer is to compare two integers (or pointers) for being greater / less / equal, and conditionally jump according to the result.对于任何计算机来说,一个极其常见的任务是比较两个整数(或指针)的大于/小于/相等,并根据结果有条件地跳转。 This is how you implement higher-level constructs like if (x < y) , if (x == y) , and so on.这就是您如何实现更高级别的构造,例如if (x < y)if (x == y)等等。

On x86, as in many other architectures, this task is broken into two instructions: CMP or some similar instruction to perform the arithmetic of the comparison, and the conditional Jcc instructions to perform the jump.在 x86 上,与许多其他架构一样,此任务分为两条指令: CMP或一些类似的指令来执行比较的算术,以及条件Jcc指令来执行跳转。 There has to be some kind of state in the CPU for CMP to communicate its result for Jcc to use, and that's what the FLAGS register is for. CPU 中必须有某种 state 以便CMP传达其结果供Jcc使用,这就是FLAGS寄存器的用途。

A test for equality is the most basic of these, so it makes sense that there should be a flag which is set according to whether the two operands of CMP were equal.相等性测试是其中最基本的,因此应该有一个标志,根据CMP的两个操作数是否相等来设置标志。 Since CMP is really a subtraction operation under the hood, this is equivalent to asking whether the result of the subtraction was zero, which is easily done in hardware by OR'ing together all the bits and inverting the one-bit result.由于CMP实际上是一个减法运算,这相当于询问减法的结果是否为零,这很容易在硬件中通过将所有位相或并将一位结果取反来完成。 And that's the zero flag.这就是零标志。 Since it costs basically nothing, the 8086 designers decided to set the zero flag in this way after almost every arithmetic or logical instruction, not only CMP .由于它基本上没有成本,8086 设计者决定在几乎每条算术或逻辑指令之后以这种方式设置零标志,而不仅仅是CMP

Then "jump if equal" is equivalent to "jump if zero flag set".那么“如果相等则跳转”等价于“如果设置了零标志则跳转”。 Indeed, JE and JZ are just different assembly mnemonics for the same machine-code instruction.实际上, JEJZ只是同一机器代码指令的不同汇编助记符。

The other standard arithmetic flags (carry, sign, overflow) are also used in this way.其他标准算术标志(进位、符号、溢出)也以这种方式使用。 This is by far a more common use for them than any kind of error checking.到目前为止,这比任何类型的错误检查都更常见。 (Indeed, many compiled languages do no such error checking and simply ignore overflow if it occurs.) For instance, if you want to jump if AX < BX , where the values in the registers are to be treated as unsigned, you would subtract BX from AX and jump if a borrow occurred, which on x86 sets the carry flag. (事实上,许多编译语言没有这样的错误检查,如果发生溢出则简单地忽略它。)例如,如果你想在AX < BX时跳转,其中寄存器中的值将被视为无符号,你可以减去 BX如果发生借位,则从 AX 跳转,在 x86 上设置进位标志。 Then your code simply looks like CMP AX, BX / JC label .然后您的代码看起来就像CMP AX, BX / JC label The assembler lets you use JB instead of JC so that you can think of it as "jump if below".汇编器允许您使用JB而不是JC ,以便您可以将其视为“如果低于则跳转”。 You can also combine it with the zero flag;您也可以将它与零标志结合使用; if you want to jump if AX <= BX , then you write CMP AX, BX; JBE label如果你想跳转 if AX <= BX ,那么你写CMP AX, BX; JBE label CMP AX, BX; JBE label , where JBE will jump if either of the carry or zero flags is set. CMP AX, BX; JBE label ,如果设置了进位标志零标志, JBE将跳转。

The sign and overflow flags are used similarly for signed compares, though the rules are a little more complicated.符号和溢出标志类似地用于有符号比较,尽管规则稍微复杂一些。

The flags are far more useful than just coming out of CMP.这些标志比仅仅从 CMP 出来的有用得多。 Think of code like: "if(.--x) {...}"想像这样的代码:“if(.--x) {...}”

This could easily be implemented with a DEC/JZ pair without any need of an intervening CMP.这可以通过 DEC/JZ 对轻松实现,无需任何干预 CMP。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM