相等数字的 AVR 减法是否设置 SREG C 标志?

Does AVR subtraction of equal numbers set the SREG C-flag?

短背景: BRLO (Branch if Lower) 指令规定为 1. ... 如果 C 标志 == 1,则执行分支; 2. ... 如果 Rd < Rr(来自 CP 指令)

,则执行分支

我的问题: 我将使用 4 位数字进行演示。假设 Rd = Rs = 3 = 0011。从上面的第 2 点来看,分支不应发生。 CP 指令执行 Rd - Rr。如果我们使用二进制补码进行减法,我们有 0011 - 0011 = 0011 + 1100 + 0001 = 0000 带有 C 标志 = 1。因此,上面的第 1 点与第 2 点矛盾。

假设我错了:我哪里搞砸了?

谢谢

简而言之,给出相同结果的操作并不总是等价的操作。因此,您的假设 0011 - 0011 = 0011 + 1100 + 0001 将具有相同的进位标志值 - 是错误的

尽管 A + (~B + 1) 给您的结果与 A - B 相同,但它并不相同,并且不会以相同的方式更新标志。

其实你忘记了一件事。在您的示例中:

0011 + 1100 + 0001 = 0000 - 是错误的。因为 0011 + 1100 + 0001 = 10000

你忘记 A + (~B + 1) 等于 A - B 只有 当考虑补码时 溢出.

现在你可以看到进位标志在两个操作中是完全相反的。事实上,当 A - B 没有借位(下溢)时,A + ~B + 1 将会溢出(在第一次或第二次加法中)。

加法时C标志表示溢出,即从最左边的位从左开始加1

即如果您要添加:

  0110
+ 1101
  ----
 10011
  ^^^^ the result
 ^ the carry flag

也就是说,如果你对一个较长的数字进行加法运算,由多个寄存器组成,你必须在较高的部分加一。例如

 add r16, r18 // adds r18 to r16, C flag is set only when overflow happened
 adc r17, r19 // adds r19 to r18, and add one if C flag is set. updates the C flag by the overflow again
 // in result r17:r16 = r17:r16 + r19:r18

做减法时,C标志表示借位发生在最左边的位的左边,并且是数字的高位部分,因此应该减一

 *  *  - borrow positions
  0110
- 1101
  ----
  0001
 ^ carry flag is set when borrowed at left from the leftmost positions.

在汇编程序中,你有 sbc 指令,它像 sub 指令一样进行减法运算,但如果设置了进位标志

,则结果减一
 sub r16, r18 // subtracts r18 from r16, C flag is set only when underflow happened
 sbc r17, r19 // subtracts r19 from r18, and subtracts one more if C flag is set. updates the C flag by the underflow again
 // in result r17:r16 = r17:r16 - r19:r18

所以,回答你的问题:当你从数字本身减去数字时,进位标志的值被清除,因为没有发生下溢。

AVR 架构具有简单的分支机制。它有 8 个标志位,每个分支指令根据其中一位的值进行分支。

所以,BRLOBRCS都是同一个机器码的助记符,如果设置了进位标志就会跳转。仅当您从较低的无符号值中减去较高的无符号值时,才会设置进位标志。

如果要进行有符号比较,则必须使用BRLT指令,该指令查看S标志,等于标志N的异或和 VN 当运算结果为负符号数时设置标志(设置高位)。 V 标志表示已发生签名溢出。他们的独占或组合表示从较小的数字中减去较大的带符号数。