我认为2补码的全部意义在于可以以相同的方式实现有符号和无符号数字的操作。维基百科甚至特别将乘法列为受益的操作之一。那么为什么x86对每个都有单独的说明,mul
和imul
?x86-64仍然如此吗?
两个16位数字相乘产生32位结果。即使其中一个数字是“1”,处理器也会有效地将另一个数字扩展到32位。将一个数字扩展到更长的位长度的过程是有符号值和无符号值不同的操作之一(符号重要的另一个重要操作是大小比较,这也是除法的重要组成部分)。
除了mul和mul指令在设置CF和OF标志(进位和溢出)方面有所不同之外,2和3操作数版本的结果是相同的。
考虑两种情况:-1*-1与0xFFFFFFFF*0xFFFFFFFF的溢出,你就会明白了。
加法和减法是相同的,乘法的低半部分也是如此。然而,完全乘法不是。简单的例子:
在32位二进制补码中,-1与无符号量2**32 - 1具有相同的表示形式。然而:
-1 * -1 = +1
(2**32 - 1) * (2**32 - 1) = (2**64 - 2**33 + 1)
(注意,两个结果的低32位是相同的;这就是我说的“乘法的下半部分”是相同的意思)。
C语言有符号和无符号类型,如char和int。我不确定它是如何在程序集级别实现的,例如,在我看来,有符号和无符号的乘法会带来不同的结果,那么程序集是同时做无符号和有符号的算术,还是只做一个,这在某种程度上是针对不同情况模拟的?
GCC和Clang似乎对有符号整数和无符号整数之间的加法有不同的解释,这取决于它们的大小。为什么会这样?所有编译器和平台上的转换是否一致? 举个例子: 结果: 在这两种情况下,我们得到了-1,但其中一个被解释为无符号整数和下溢。我本以为两者都会以同样的方式转化。 那么,为什么编译器会以如此不同的方式转换它们,这保证了一致性吗?我用G11.1.0和Clang12.0测试了这个。以及Arch Linu
我在看的书:CS-app 2。c有无符号和有符号的int类型,并且在大多数架构中使用二进制补码算法来实现有符号值;但是学了一些汇编代码之后,发现很少有指令区分无符号和有符号。所以我的问题是: > 区分有符号和无符号是编译器的责任吗?如果是,它是如何做到的? 谁实现两个补码算法——CPU还是编译器? 添加更多信息: 在学习了更多的指令后,实际上有一些指令区分有符号和无符号,例如setg、seta等。
为什么无符号右移(逻辑右移)和有符号右移(算术右移)对负数产生相同的结果? Android Studio Logcat输出
我使用SIMD创建了一个64位*64位到128位的函数。目前我已经使用SSE2(实际上是SSE4.1)实现了它。这意味着它同时生产两个64b*64b到128b的产品。同样的想法可以扩展到AVX2或AVX512,同时提供四个或八个64b*64到128b的产品。我的算法基于http://www.hackersdelight.org/hdcodetxt/muldws.c.txt 该算法执行一次无符号乘法
为什么在C 11中无符号短*无符号短转换为int? int太小,无法处理这行代码显示的最大值。 MinGW 4.9.2溢流 因为(来源) USHRT_MAX=65535 (2^16-1)或更大* INT_MAX=32767 (2^15-1)或更大* 和(2^16-1)*(2^16-1)=~2^32。 这个解决方案会有什么问题吗? 此程序 给出输出 在…上 两者都有 这证明在这些编译器上,被转换为。