assembly - 对一对有符号和无符号数字进行算术运算是否合法?

标签 assembly integer math unsigned signed

我已经学习了一半以上的汇编,并且熟悉有符号和无符号整数如何以位表示的概念,我知道这似乎是一个奇怪的问题,答案很明显,但我我想知道对一对数字(其中一个被认为是有符号的,而另一个被认为是无符号的)使用加法之类的算术运算是否有意义,我想过如下多个示例,它们将产生正确的结果:

10000001(1 字节整数,视为无符号,相当于 129)
+
11111111(1 字节整数并被视为有符号(二进制补码系统),相当于 -1)

10000000(1 字节整数,在无符号逻辑中等于 128)

现在,如果上限值在 AL 寄存器中,并且我们有以下指令代码(GAS 格式):

addb -1, %al

然后 EFLAGS 寄存器的进位标志(CF)将在操作完成后设置,并会通知实际上尚未发生的溢出,也许是因为在溢出方面有一个无符号数,EFLAGS 寄存器的溢出标志(OF)应该引用。所以我很困惑这样做是否明智。

最佳答案

从数学上讲,您不会添加有符号或无符号数字。只有模 232 的值(假设您有 32 位寄存器)。这些值涵盖了 232 个连续整数的范围,但您可以自由地将该范围解释为几乎从任何地方开始。 “Signed”和“unsigned”就是这样的两种解释。

换句话说,对于 4 位寄存器,“1011”的无符号解释为 11,而有符号解释为负 5。但只有一个值(数学家通常称之为“11 模 24”,因为数学家传统上喜欢无符号解释)。例如,如果您将“0110”添加到该值(在有符号和无符号解释中都是“6”),那么您会得到“0001”,这是正确的值:减五加六产生一,加十一次6 是 17,它在减少模 24 时也等于 1(17 是 1 加 16;“减少模 24”是关于除以 16 [即 24] 并只保留余数)。

另一种说法如下:数值的(二进制)位数在概念上向左是无限的。 CPU 寄存器只保留最右边的 32 位。无符号解释通常假设所有最左边的位都为零。签名解释是关于假设,传统上,所有最左边的位都具有与位 31 相同的值(即全部为零,或全部为 1)。无论哪种方式,当您执行加法(或减法或乘法)时,进位是从右向左传播,而不是相反,因此这些被忽略位的值对 32 位结果没有任何影响。所以只有一个“加”操作码,它一点也不关心它的操作数在程序员的大脑中是“有符号”还是“无符号”。

在执行与模算术不兼容的运算时,必须考虑有符号性。转换成十进制数字序列进行显示就是这样一种操作。然而,更常见的情况是比较。取模 232 的值未排序;它们处于一种循环循环中(当您将 1 添加到 232-1 并减少模 232 时,您会返回到 0)。仅当您考虑整个整数范围内的整数时,比较才有意义。此时,您必须决定是使用签名解释还是未签名解释。这就是为什么 x86 处理器同时提供 jg (如果更大则跳转,签名解释)和 ja (如果高于,则跳转,未签名的解释)。

关于assembly - 对一对有符号和无符号数字进行算术运算是否合法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4645230/

相关文章:

assembly - `teSTL` eax 与 eax?

c - 32 位处理器上的程序集标签地址不正确

algorithm - "Time Aware"指数移动平均线

assembly - 如何在ml64.exe中设置align 64?

assembly - MIPS 汇编语言 - 临时寄存器与保存的寄存器

integer - CG 中的定点数据类型整数精度范围(12 位)

c - 如何在 C 中从 .txt 文件读取数字

mysql - 通过将两个表与整数值进行比较,获取完成一组所需的自有零件的百分比

c++ - 计算球形多边形面积?

python - 如何在 Python 中得到 10**20 + 10**-20 的精确结果?它给了我 1e+20