谁能解释为什么这里设置了溢出标志?我了解到,如果您添加正数并获得负数,或者减去负数并获得正数,它就会被设置!
LDR r0,=0X80000000
LDR r1,=0X40000000
SUBS r7,r10,r0
谁能解释为什么这里设置了溢出标志?我了解到,如果您添加正数并获得负数,或者减去负数并获得正数,它就会被设置!
LDR r0,=0X80000000
LDR r1,=0X40000000
SUBS r7,r10,r0
我非常喜欢这个问题,我认为它非常有用。但由于时间过去了,我无法编辑和格式化它。尽管如此,这是我的看法(我喜欢发布冗长、详细和冗长的答案)。
无符号二进制(“正常”二进制)
如果您有 4 位可用于表示二进制数,那么您可以表示以下无符号数:
(0) - 0000
(1) - 0001
(2) - 0010
...
(15) - 1111
所以基本上,如果我们有 N 位可用,我们可以写下的最小数字是 0,最大的是 2^N-1(总共 2^N 个数字)。
二进制补码
PC 需要使用正整数和负整数。大多数 PC 使用“二进制补码”来表示二进制数 [1]。根据许多人的说法,它是表示有符号数的最简单、最方便的方法(因此,无论是正数还是负数)。
现在,当使用有符号数时,我们需要为符号保留 1 位。补码使我们能够非常简单地做到这一点:
符号保留为前缀,因此二进制数的 MSB(即左侧的“第一位”)。0 用于正数,1 用于负数。
正数不变。
负数在正数之上“继续”。
因此,例如,如果我们有 4 位可用:
(1) - 0 001
(2) - 0 010
(3) - 0 100
...
(6) - 0 110
(7) - 0 111
(-8) - 1 000
(-7) - 1 001
...
(-1) - 1 110
(0) - 1 111
正如我们所看到的,所有负数都以 MSB 为“1”开始。我们能写出的最小数是 2^(N-1),最大的是 2^(N-1) - 1。
在上面的表格中,我首先展示了正面,然后展示了负面的数字。我这样做是为了强调负面因素在正面因素之上“继续”。很容易看出,正数与使用无符号二进制时的正数完全相同,但它们具有前缀“0”。这就是为什么在使用 4 位二进制补码符号时最大的正数是 7。当使用无符号二进制时,我们可以表示的最大 3 位数是 7 (111)。当使用二进制补码(有 4 位可用)时,为符号保留 1 个空间,因此有效地,我们有 3 位来表示数字值,因此 0111 是我们可以表示的最大正数,即 7。
添加
无需过多介绍,二进制补码有一个很好的优势——加法、减法和乘法的完成方式与使用无符号二进制时的方式相同。
例如,如果我们想对 3 + 4 求和,当使用二进制补码时,有 4 位可用,我们将有:
3 = 0011
4 = 0100
----
7 = 0111
溢出 - 回答您的问题
当算术运算的结果无法放入结果寄存器 [2] 时,就会发生溢出。
基本上,如果你将两个大的积极因素相加,你可能没有足够的“位”来适应结果,而且结果可能看起来是消极的。那是设置溢出标志的时候。这同样适用于从负数中减去正数。后者也可以定义为:当您将两个负数相加并得到一个正数时 - 这也是溢出。
在问题的代码中,两个寄存器 R0 和 R1 包含:
R0 = 0X80000000 (-2147483648)
R1 = 0X40000000 (1073741824)
这些数字使用 8 个十六进制字符 == 32 位写入。因此,使用 32 位来表示二进制补码,我们有:
R0 = 1000 0000 0000 0000 0000 0000 0000 0000
R1 = 0100 0000 0000 0000 0000 0000 0000 0000
R0 - R1 = 0100 0000 0000 0000 0000 0000 0000 0000
那么这里发生了什么?好吧,从我们现在学到的知识来看,R0 包含我们可以用二进制补码写下来的最小负整数。所以即使减去 1 也会导致溢出!我们知道发生了溢出,因为在从负数中减去正数后,我们的结果最终是正数。我们知道这一点是因为 R0 有前缀“1”——它是负数。R1 有前缀“0”——它是正数。所以,负-正=必须是负数。在我们的例子中,前缀结果是“0” - 正数,这意味着肯定会发生溢出。
奖励:我可以做一个完整的圆圈吗?
您可能会问自己:但是如果我将两个数字相加或相减,那么我会产生如此“大”的溢出并再次得到正确的符号怎么办?(例如,假设您将 7 + 7 相加,产生了溢出,但结果最终是二进制的 +2?当结果是相同的符号时,您将如何检测到溢出发生了?)
当它只有加法和减法时(让我们只保留这 2 个),我们可以轻松地显示我们可以从这 2 个操作中获得的最大和最小数字是:
(又是一个 4 位示例)
正面的
R0 = 0111 (7) (largest positive integer)
R1 = 0111 (7) (largest positive integer)
R1 + R2 = 1110 (-2)
负面的
R0 = 1000 (-8) (smallest negative integer)
R1 = 1000 (-8) (smallest negative integer)
R0 + R1 = 0000 (0)
我给出这个例子的原因是为了表明如果你尝试做最坏的情况(两个最大的整数相加或两个最小的整数相加),你不能做一个完整的圆圈,即结果将是相反的符号. 所以,在两个操作数的情况下,保证你是好的,即如果发生溢出,结果的符号会不同。不可能将两个大整数相加,以创建溢出,通过所有负值并再次以正值结束。
[1] https://en.wikipedia.org/wiki/Two%27s_complement
[2] https://en.wikipedia.org/wiki/Overflow_flag
我使用维基百科作为参考,因为它是我们正在谈论的非常简单的东西。
0x8 - 0x4 应该足以看到这个
0x8 - 0x4 = 0x8 + (0x4)
1
1000
+ 1011
=======
完成数学
10111
1000
+ 1011
=======
0100
msbit 的进位和进位不同,因此设置了有符号溢出 (V)。
是的,如果您查看 msbit 加法器的真值表,您可以从符号位中看出。
编辑 - - -
啊假设那是 r1 而不是 r10 那么
0x4 - 0x8
01111
0100
+ 0111
========
1100
溢出为好。