相等数字的 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 个标志位,每个分支指令根据其中一位的值进行分支。
所以,BRLO
和BRCS
都是同一个机器码的助记符,如果设置了进位标志就会跳转。仅当您从较低的无符号值中减去较高的无符号值时,才会设置进位标志。
如果要进行有符号比较,则必须使用BRLT
指令,该指令查看S
标志,等于标志N
的异或和 V
。 N
当运算结果为负符号数时设置标志(设置高位)。 V
标志表示已发生签名溢出。他们的独占或组合表示从较小的数字中减去较大的带符号数。
短背景: 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 个标志位,每个分支指令根据其中一位的值进行分支。
所以,BRLO
和BRCS
都是同一个机器码的助记符,如果设置了进位标志就会跳转。仅当您从较低的无符号值中减去较高的无符号值时,才会设置进位标志。
如果要进行有符号比较,则必须使用BRLT
指令,该指令查看S
标志,等于标志N
的异或和 V
。 N
当运算结果为负符号数时设置标志(设置高位)。 V
标志表示已发生签名溢出。他们的独占或组合表示从较小的数字中减去较大的带符号数。