当结果对于寄存器来说太大时进位和溢出标志如何表现

How does the carry and overflow flag behave when result is to big for register

下面的例子应该同时设置进位和溢出标志:

mov eax, -120
add al, 140

add al, 140 将类似于以下位操作:

 10001000
+10001100
---------
= 100010100

所以结果有 9 位,而可以放入 al 的最大位数是 8。 但是我理解 overflow-flag 的方式只有在操作结果“错误”时才会设置。对于例如当将一个正数添加到一个正数但随后设置 sign-flag 时,它会产生负结果。

关于我到目前为止所做的示例中的进位标志,我只是在从较大的值中减去较小的值时才设置它。

所以我的问题归结为当操作的大小无法在寄存器中表示时进位和溢出标志的行为方式。

好的,您在这里遇到的问题是计算机数据类型的工作方式与您正在做的事情不匹配。

一般来说,计算机可以处理(即添加)有符号数据类型或无符号数据类型 — 但要求计算机将有符号值添加到无符号值可能会有问题。

这里-120是负数,所以必须用有符号表示。

但是,140本身不适合8位有符号,所以在8位中,必须使用无符号表示。

硬件不支持这种组合 — 虽然加法会产生截断的结果,但如果您执行 8 位加法,硬件将不会在标志中为您提供有意义的信息。

(如果两个操作数都是 8 位有符号的,或者如果两个操作数都是 8 位无符号的,则 8 位加法的标志是有意义的,但是当混合两种数据类型时,它们并不总是有意义:特别是当所涉及的值足够大以至于高位被使用时,例如 -120signed 8 bit 和 140unsigned 8 bit)

在这里获得正确结果的方法是将两个数字转换为更大的数据大小以容纳两个数字(它将是有符号数据类型,因此它可以容纳 -120,当然,方法两个操作数的转换将不同,因为它们是不同的数据类型)。

因此,通过符号扩展将-120 从 8 位转换为 16 位(或更大)。

然后,通过零扩展将 140 从 8 位转换为 16 位(或更大)。

然后你可以执行加法并得到一个带符号的结果,带有一个有意义的溢出标志。当然,特定计算不会在 16 位中溢出——事实上,以两个 8 位值开头的 16 位加法不会溢出。

但是,如果您想将其恢复为 8 位,您可以检查它是否适合该大小和数据类型。出于所有实际目的,在这种情况下,16 位结果的高 8 位包含有关低 8 位结果的感兴趣的溢出信息,而不是标志中的信息 (overflow/carry)。

首先,确定要检查的 8 位数据类型:有符号或无符号。有几种可行的方法,但一个简单的方法是将 16 位值截断为 8 位,然后将其从 8 扩展回 16,然后查看新扩展的 16 是否等于原始 16 位结果。

对于带符号的 8 位,您会将 16 位结果截断为 8 位,然后将其符号扩展回 16 位,然后与原始 16 位值进行比较。如果不同,则该值不适合 8 位带符号。

与无符号8位相同:将16位结果截断为8位,并将其零扩展回16位与原始比较,如果比较不相等则不适合8 -位无符号。

或者,从16位原始结果中,您可以检查低8位值的符号位和高8位的值。如果所有高位与低8位的符号位的位值相同,则16位结果将适合8位带符号而不会丢失。

对于无符号,如果高8位为0,则低8位将放入8位无符号中而不会丢失。