没有溢出标志的处理器如何执行带符号算术? [英] How does a processor without an overflow flag perform signed arithmetic?

查看:106
本文介绍了没有溢出标志的处理器如何执行带符号算术?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我知道可以通过进位标志实现两个大于给定处理器总线大小的无符号整数相加.通常,使用溢出标志的带符号整数也是如此.但是,Intel 8085仅拥有一个Sign标志,没有Overflow标志,那么它如何处理带符号整数算术呢?

I know that addition of two unsigned integers larger than the bus size of a given processor can be achieved via the carry flag. And normally, the same is true for signed integers using the overflow flag. However, the Intel 8085 only possesses a Sign flag, not an Overflow flag, so how does it deal with signed integer arithmetic?

推荐答案

如您所知,溢出标志仅与有符号整数运算有关.在ALU既有溢出标志又带有进位标志的处理器(如x86)上,这些标志的 both 均根据二进制算术运算的结果进行设置,但这取决于 programmer >决定如何解释它们.有符号算术使用溢出标志;无符号算术使用进位标志.查看错误的数据会给您毫无意义的数据.

As you know, the overflow flag is only relevant for signed integer arithmetic. On processors whose ALU has both overflow and carry flags (like x86), both of these flags get set according to the result of a binary arithmetic operation, but it's up to the programmer to decide how to interpret them. Signed arithmetic uses the overflow flag; unsigned arithmetic uses the carry flag. Looking at the wrong one gives you meaningless data.

在两种情况下,在二进制算术运算中会打开溢出标志:

There are two cases where the overflow flag would be turned on during a binary arithmetic operation:

  1. 两个输入的符号位均为 off ,而结果的符号位为 on .
  2. 两个输入的符号位均为 on ,而结果的符号位为 off .
  1. The inputs both have sign bits that are off, while the result has a sign bit that is on.
  2. The inputs both have sign bits that are on, while the result has a sign bit that is off.

然后,基本上,当结果的符号位与输入操作数的符号位不匹配时,将置位溢出标志.在所有其他情况下,溢出标志都将关闭.

Basically, then, the overflow flag gets set when the sign bit of the result does not match the sign bit of the input operands. In all other cases, the overflow flag is turned off.

举几个例子:

  • 0100 + 0001 = 0101(溢出标志关闭)
  • 0100 + 0100 = 1000( on 上的溢出标志)
  • 0110 + 1001 = 1111(溢出标志关闭)
  • 1000 + 1000 = 0000(溢出标记 on )
  • 1000 + 0001 = 1001(溢出标志关闭)
  • 1100 + 1100 = 1000(溢出标志 off )
  • 0100 + 0001 = 0101 (overflow flag off)
  • 0100 + 0100 = 1000 (overflow flag on)
  • 0110 + 1001 = 1111 (overflow flag off)
  • 1000 + 1000 = 0000 (overflow flag on)
  • 1000 + 0001 = 1001 (overflow flag off)
  • 1100 + 1100 = 1000 (overflow flag off)

请注意,溢出标志的状态仅取决于三个数字的符号位;因此,您只需要查看这些位.这很直观.如果将两个正数相加得到负数,则答案肯定是错误的,因为两个正数应给出正数结果.相反,如果您将两个负数相加并得到一个正数,那肯定是错误的.加到负数上的正数永远不会溢出,因为总和位于两个输入值之间.因此,混合符号值的算术永远不会打开溢出标志.

Notice that the state of the overflow flag depends only on the sign bits of the three numbers; thus, you need only look at these bits. This makes intuitive sense. If you add two positive numbers to get a negative, then the answer must be wrong because two positive numbers should give a positive result. Conversely, if you add two negative numbers and get a positive number, that also must be wrong. A positive number added to a negative number can never overflow because the sum lies between the two input values. Thus, arithmetic of mixed-signed values never turns on the overflow flag.

(显然,所有这些都假设为二进制补码).

(Obviously this all assumes two's-complement arithmetic.)

因此,即使处理器的ALU不会自动为您执行此操作,您也可以轻松计算溢出标志的状态.您需要做的就是查看这三个值的符号位,特别是符号位的二进制进位 to 和符号位的二进制进位 out .当一个位被带入符号位位置而没有发生相应的进位时,就会发生溢出.

Thus, you can easily calculate the state of the overflow flag even if the processor's ALU doesn't do it for you automatically. All you need to do is look at the sign bits of the three values, specifically the binary carry into the sign bit and the binary carry out of the sign bit. Overflow occurs when a bit is carried into the sign-bit place and no corresponding carry out occurs.

这些C函数实现了逻辑:

These C functions implement the logic:

// For the binary (two's complement) addition of two signed integers,
// an overflow occurs if the inputs have the same sign AND ALSO the
// sign of the result is different from the signs of the inputs.
bool GetOverflowFlagForAddition(int op1, int op2, int result)
{
   return (~(op1 ^ op2) & (op1 ^ result)) < 0;
}

// For the binary (two's complement) subtraction of two signed integers,
// an overflow occurs if the inputs have the same sign AND ALSO the
// sign of the result matches the signs of the inputs.
bool GetOverflowFlagForSubtraction(int op1, int op2, int result)
{
   return ((op1 ^ op2) & (op1 ^ result)) < 0;
}

(当然,您可以用许多不同的方式来编写它.)

(There are many different ways that you could write this, of course.)

或者,用 in 与该位(最左边)的进位 out 不相等,则会发生溢出.

Or, to put it in the terms that Iwillnotexist Idonotexist did in a comment: "Overflow can be defined as the XOR of the carry into and out of the sign bit." Overflow has occurred if the carry in does not equal the carry out at that particular (leftmost) bit.

一个更正式的定义是,溢出标志是结果的高两位进行进位的XOR.象征性地,对于8位值: O = C 6 ^ C 7 ,其中 O 表示溢出", C 表示携带".这只是对我已经给出的定义的重述:如果进位与最高位(在本例中为7位)的进位不同,则会发生溢出.

A more formal definition is that the overflow flag is the XOR of the carry-out of the high two bits of the result. Symbolically, for an 8-bit value: O = C6 ^ C7, where O means "overflow" and C means "carry". This is just a restatement of the definition I already gave: overflow happens if the carry out is different from the carry into the highest-order bit (in this case, bit 7).

另请参见肯·希尔里夫(Ken Shirriff)的文章中有关溢出标志的方式可以算术运算(这是在另一种流行的8位处理器6502的背景下). 他还解释了溢出标志的实现在6502的硅水平上.

See also Ken Shirriff's article on how the overflow flag works arithmetically (this is in the context of the 6502, another popular 8-bit processor). He also explains the implementation of the overflow flag at the silicon level in the 6502.

好的,那么进位标志是什么意思?进位标志以 unsigned 算术表示溢出条件.再次有两种情况被设置:

Okay, so what does the carry flag mean? The carry flag indicates an overflow condition in unsigned arithmetic. There are again two cases where it is set:

  1. 如果对最高有效位(符号位)进行进位,则在加法期间设置进位标志.

  1. The carry flag is set during addition if there is a carry out of the most significant bit (the sign bit).

如果在最高有效位(符号位)有借位,则在减法期间设置进位标志.

The carry flag is set during subtraction if there is a borrow into the most significant bit (the sign bit).

在所有其他情况下,进位标志均关闭.再次举例:

In all other cases, the carry flag is turned off. Again, examples:

  • 1111 + 0001 = 0000(在 on 上带有标志)
  • 0111 + 0001 = 1000(进位标志关闭)
  • 0000-0001 = 1111(在上带有标志)
  • 1000-0001 = 0111(进位标志关闭)
  • 1111 + 0001 = 0000 (carry flag on)
  • 0111 + 0001 = 1000 (carry flag off)
  • 0000 - 0001 = 1111 (carry flag on)
  • 1000 - 0001 = 0111 (carry flag off)

只是在不太明显的情况下,它必须明确指出减法与两者的补码求反相同,因此后两个示例可以用加法重写为:

Just in case it isn't obvious, it bears explicitly pointing out that subtraction is the same as addition of the two's-complement negation, so the latter two examples can be rewritten in terms of addition as:

  • 0000 + 1111 = 1111(在上带有标志)
  • 1000 + 1111 = 0111(进位标记关闭)
  • 0000 + 1111 = 1111 (carry flag on)
  • 1000 + 1111 = 0111 (carry flag off)

…但是请注意,减法的进位与加法设置的进位相反.

…but note that the carry for subtraction is the inverse of the carry set by addition.

将所有这些放在一起,就可以绝对地根据进位和符号标志实现溢出标志.如果您有最高有效位(符号位)的进位,则进位标志将置1.如果结果的符号位已置1,则符号标志将置1,这意味着最高有效位中有一个进位.根据上面对溢出标志的定义,OF == CF ^ SF,因为溢出是符号位的进位输出与进位的进位进入 .如果进位 in 不等于进位 out ,则发生签名溢出.

Putting all of this together, then, you can absolutely implement the overflow flag in terms of the carry and sign flags. The carry flag gets set if you have a carry out of the most-significant bit (the sign bit). The sign flag gets set if the result has its sign bit set, which means that there was a carry into the most-significant bit. By our definition of the overflow flag above, OF == CF ^ SF, because overflow is the carry coming out of the sign bit XORed with the carry coming into the sign bit. If the carry in does not equal the carry out, then signed overflow occurred.

有趣的是,肯·希尔里夫(Ken Shirriff)的反向工程8085处理器表明它确实有一个溢出标志-只是没有记载.这是8位标志状态寄存器的位1.它被称为"V",并且被称为 Ken在此处进行了解释是通过将进位进入最高有效位与最高有效位的进位 XOR异或而以上述完全相同的方式实现的strong> C 6 ^ C 7 ,这些值直接来自ALU. (他在同一篇文章中还描述了如何用"V"标志和正负号标志来实现另一个未记录的正负号"K"标志,产生了一个在正负比较中有用的标志,但超出了此答案的范围.)

Interestingly, though, Ken Shirriff's reverse-engineering of the 8085 processor shows that it does, in fact, have an overflow flag—it's just undocumented. This is bit 1 of the 8-bit flag status register. It is known as "V" and, as Ken explains here, is implemented in exactly the way discussed above, by XORing the carry into the most-significant bit with the carry out of the most-significant bit—C6 ^ C7, with these values coming directly from the ALU. (He also describes in the same article how the other undocumented flag, the "K" flag, is implemented in terms of the "V" flag and the sign flag, yielding a flag that is useful in signed comparisons, but a bit beyond the scope of this answer.)

这篇关于没有溢出标志的处理器如何执行带符号算术?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆