为什么 CMP(比较)有时会在 8086 汇编中设置进位标志?

发布于 2024-12-13 18:24:34 字数 194 浏览 5 评论 0原文

我一直在阅读 8086 指令集,它说 CMP(比较)可以设置进位标志。我知道比较会减去两个操作数,但我想知道在这种情况下是否有人可以提供一个示例。

我只是无法理解添加数字和负数将设置进位标志的想法。我已经阅读了借用标志,但我只需要一个示例来阐明我对比较指令的理解。

另外,我知道如果 3 - 5 = -2 会设置负标志...什么时候设置进位?

I've been reading around and with the 8086 Instruction Set, it says that a CMP (compare) can set the Carry Flag. I understand that a compare subtracts two operands but I was wondering if anyone can provide an example when that is the case.

I just can't grasp the idea of adding a number and a negative number will set the carry flag. I've read into the borrow flag but I just needed an example to clarify my understanding of a compare instruction.

Also, I understand that if 3 - 5 = -2 would set the negative flag... when is carry set?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

世界等同你 2024-12-20 18:24:34
  • 在导致下溢或溢出的操作之后设置进位标志。例如,从 6 减去 10 将导致下溢并设置进位标志。同样,寄存器的最大值加1将导致溢出并设置进位标志。
  • 进位标志也在移位操作期间被修改,它被设置
    到从目标寄存器移出的最后一位的值。
  • 位测试会将测试位的值放入进位
    旗帜。执行此操作的操作码:BT、BTC、BTR 和 BTS。
  • 直接影响进位标志的指令:CLC、CMC 和 STC。
  • 在比较期间,进位标志被设置,就像两个
    操作数已被减去。
  • 在求反 (NEG) 期间,进位标志被设置,除非操作数是
    零,在这种情况下它被清除。
  • The carry flag is set after an operation that resulted in an underflow or overflow. For example, subtracting 10 from 6 will result in an underflow and set the carry flag. Similarly, adding 1 to the maximum value of the register will result in an overflow and set the carry flag.
  • The carry flag is also modified during a shift operation, it is set
    to the value of the last bit shifted out of the destination register.
  • Bit testing will place the value of the tested bit into the carry
    flag. Opcodes that do this: BT, BTC, BTR, and BTS.
  • Instructions that affect the Carry Flag directly: CLC, CMC, and STC.
  • During a comparison, the carry flag is set just as if the two
    operands had been subtracted.
  • During a negation (NEG), the carry flag is set unless the operand is
    zero, in which case it is cleared.
凯凯我们等你回来 2024-12-20 18:24:34

使用无符号算术时通常设置进位标志。例如,添加两个无符号(其结果不适合寄存器)数字不会引发溢出标志,而只会引发进位标志。然而,当使用有符号算术时,在这种情况下会设置溢出标志。

Carry flag is normally set when using unsigned arithmetic. For example, adding two unsigned (whose result does not fit in register) numbers would not raise the overflow flag but only carry flag. However, when using signed arithmetic, overflow flag is set in such event.

独木成林 2024-12-20 18:24:34

您可以在 此答案相关问题。
您还可以找到示例 C 代码,模拟 8 位数字的进位加法和借位指令减法,您可以使用它,也许可以获得更多示例。

输出格式是这样的:
127( 127) - 255( -1) - 1 = 127( 127) CY=1 OV=0
其中每个数字都表示为无符号和旁边带括号的有符号(2 的补码)。 =之前的数字是ADC/SBB之前的进位标志。 CY=OV= 显示 ADC/SBB 后的进位和溢出标志。

比较与无借位减法几乎相同,只是它只影响进位、溢出、符号和零标志(以及奇偶校验和辅助进位,但它们在这里并不重要),而不修改寄存器/内存中的任何数字。

You can find examples of when the carry and overflow flags are set to 0 and 1 following addition or subtraction of integer numbers in this answer to a related question.
You can also find there sample C code emulating the add with carry and subtract with borrow instructions for 8-bit numbers and you can play with that, maybe get more examples.

The output format there is something like this:
127( 127) - 255( -1) - 1 = 127( 127) CY=1 OV=0
Where each number is represented as both unsigned and parenthesized signed (2's complement) next to it. The number before = is the carry flag before ADC/SBB. CY= and OV= show the carry and overflow flags after ADC/SBB.

Compare does pretty much the same thing as subtract without borrow, except it only affects the carry, overflow, sign and zero flags (and parity and auxiliary carry, but they're unimportant here) without modifying any number in a register/memory.

枕梦 2024-12-20 18:24:34

https://www.hellboundhackers.org/articles/read-article。 php?article_id=729

作为一个快速总结,我写这篇文章有两个目的。首先,这很有趣,更多地了解计算机的工作原理总是有帮助的。其次,总有一些程序会直接操作标志,了解它们对跳转的影响是有帮助的。例如,像这样简单的事情
CMP eax,ebx
JC某处
可能会让大多数逆向新手感到困惑,但希望在读完这篇文章后不会再困惑。享受吧:)

[重要提示:当我写出二进制数时,我将使用 8 位整数作为示例。请记住,虽然 8 位整数在编程中并不常用,但我讨论的相同规则也适用于具有更多位的整数]

CMP 指令:

CMP 指令通过执行两个操作数的隐式减法来进行操作。这意味着结果不存储在内存中。减去它们后,它会进行一些快速测试,更新 Z、O、C、S 和 P 标志。 P(即奇偶校验)标志很少使用,因此为了简洁起见,我们将在本文中忽略它。

二进制减法是通过将第一个操作数的第二个操作数的取反版本相加来执行的。这就像你在中学学到的,4+3 = 4 - (-3),反之亦然。
在文章的最后,我将解释这是如何完成的,但现在我将转向更重要的问题,因为破解或编码并不真正需要这些知识。

符号和零标志:

CMP 指令可以设置的四个标志 - Z、O、C 和 S,分别称为零、溢出、进位和符号标志。每当减法结果等于零时,就会设置零标志。当然,只有当操作数相等时才会发生这种情况。当减法结果为负时,设置符号标志。尽管我们倾向于认为这意味着符号标志与零标志的组合足以测试所有>。 >=<和 <=,这是不正确的,因为即使第一个数字大于第二个数字,结果也可能为负数。这是因为溢出。

溢出标志:

有符号整数以二进制表示,其位数与无符号整数相同。当然,这意味着符号必须设置在整数的一位中。有符号整数将符号存储在 MSB(最高有效位)中。这意味着,00000001 转换为十进制 1,而 10000001 转换为 -127。我将在本文后面讨论为什么它是 -127 而不是 -1 或 -2。
当处理器执行减法时,如果减法低于 00000000 或高于 11111111,则会回绕。因此,如果您从正数中减去负数,或从负数中减去正数,则答案有可能是溢出边界。例如,100 - (-100) 等于 200,但 8 位有符号整数的最大值是 127,因此 200 将穿过上边界并最终成为负数,即使它应该是正数。 -100 - 100 也会出现同样的问题;它环绕低端并在本应为负值时变为正值,从而导致下溢。请注意,下溢还会设置溢出标志,并且溢出将在本文中进一步指上溢和下溢。 CPU 对此进行检查,如果发生则设置溢出标志。

进位标志:

如果两个操作数都被解释为无符号整数,则第一个操作数较大时,设置进位标志。这很容易确定,因为只要减法经过 00000000 进入更高的范围 (11111111),就会发生这种情况。
例如,00000001 - 00000010 = 11111111,因此设置了进位。然而,00000010 - 00000001 = 00000001,因此未设置进位。

https://www.hellboundhackers.org/articles/read-article.php?article_id=729

Just as a quick summary, I wrote this article for two purposes. First, It is interesting, and more knowledge of how your computer works is always helpful. Secondly, there are always programs where flags will be manipulated directly, and it is helpful to know the effects they will have on jumps. For example, something as simple as
CMP eax,ebx
JC somewhere
might confuse most beginning reversers, but hopefully not after this article. Enjoy :)

[Important Note: I will use 8 bit integers for my examples when I write out binary numbers. Just remember that, although 8 bit integers are not commonly used in programming, the same rules that I discuss apply to integers with more bits]

The CMP Instruction:

The CMP instruction operates by performing an implied subtraction of the two operands. This means that the result is not stored in memory. After subtracting them, it does a few quick tests, updating the Z,O,C,S, and P flags. The P, or parity, flag is rarely used, so we'll ignore it in this article for the purpose of brevity.

Binary subtraction is performed by adding the negated version of the second operand from the first. This is just like what you learned in middle school, about how 4+3 = 4 - (-3), and visa versa.
At the end of the article I will explain how this is done, but I'll move onto the more important matters for now since that knowledge is not really needed for cracking or coding.

Sign and Zero Flag:

The four flags that the CMP instruction can set - Z,O,C, and S, are known as the zero, overflow, carry, and sign flags respectively. The zero flag is set whenever the result of the subtraction is equal to zero. This, of course, only occurs when the operands are equal. The sign flag is set when the result of the subtraction is negative. Although we are inclined to think that this means the sign flag in combination with the zero flag are enough to test all > >= < and <=, this is not true, because the result can be negative even if the first number is greater than the second. This is because of overflow.

Overflow Flag:

Signed integers are represented in binary with the same amount of bits as unsigned integers. This means, of course, that the sign must be set in one of the bits of the integer. Signed integers store the sign in the MSB (most significant bit). This means that, while 00000001 converts to 1 in decimal, 10000001 converts to -127. I will discuss why it is -127 and not -1 or -2 later in the article.
When the processor performs subtraction, It wraps around if the subtraction goes below 00000000 or above 11111111. Therefore, if you subtract a negative number from a positive one, or subtract a positive number from a negative one, there is the possibility that the answer will overflow over the boundary. For example, 100 - (-100) is equal to 200, but the highest value an 8 bit signed integer can be is 127, so 200 will wrap through the upper boundary and end up as a negative number, even though it should be positive. The same problem occurs with -100 - 100; It wraps through the low end and ends up positive when it should be negative, causing an underflow. Note that an underflow also sets the overflow flag, and overflow will refer to both overflows and underflows further in the article. The CPU checks for this, and sets the overflow flag if it occurs.

Carry Flag:

The carry flag is set when, if both operands are interpreted as unsigned integers, the first one is greater. This is easy to determine because it occurs whenever the subtraction passes through 00000000 into the higher range (11111111).
For example, 00000001 - 00000010 = 11111111, so carry is set. However, 00000010 - 00000001 = 00000001, so carry is not set.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文