0

谁能解释为什么这里设置了溢出标志?我了解到,如果您添加正数并获得负数,或者减去负数并获得正数,它就会被设置!

    LDR     r0,=0X80000000
    LDR     r1,=0X40000000

    SUBS        r7,r10,r0
4

2 回答 2

1

我非常喜欢这个问题,我认为它非常有用。但由于时间过去了,我无法编辑和格式化它。尽管如此,这是我的看法(我喜欢发布冗长、详细和冗长的答案)。

无符号二进制(“正常”二进制)

如果您有 4 位可用于表示二进制数,那么您可以表示以下无符号数:

(0) - 0000
(1) - 0001
(2) - 0010
...
(15) - 1111

所以基本上,如果我们有 N 位可用,我们可以写下的最小数字是 0,最大的是 2^N-1(总共 2^N 个数字)。

二进制补码

PC 需要使用正整数和负整数。大多数 PC 使用“二进制补码”来表示二进制数 [1]。根据许多人的说法,它是表示有符号数的最简单、最方便的方法(因此,无论是正数还是负数)。

现在,当使用有符号数时,我们需要为符号保留 1 位。补码使我们能够非常简单地做到这一点:

  1. 符号保留为前缀,因此二进制数的 MSB(即左侧的“第一位”)。0 用于正数,1 用于负数。

  2. 正数不变。

  3. 负数在正数之上“继续”。

因此,例如,如果我们有 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

我使用维基百科作为参考,因为它是我们正在谈论的非常简单的东西。

于 2021-09-27T22:22:48.840 回答
0

0x8 - 0x4 应该足以看到这个

0x8 - 0x4 = 0x8 + (0x4)

     1
  1000
+ 1011
=======

完成数学

 10111
  1000
+ 1011
=======
  0100

msbit 的进位和进位不同,因此设置了有符号溢出 (V)。

是的,如果您查看 msbit 加法器的真值表,您可以从符号位中看出。

编辑 - - -

啊假设那是 r1 而不是 r10 那么

0x4 - 0x8

  01111
   0100
+  0111
========
   1100

溢出为好。

于 2018-12-10T23:03:08.127 回答