相关疑难解决方法(0)

签名与无符号整数

我是否正确地说有符号和无符号整数之间的区别是:

  1. 无符号可以保持较大的正值,而不是负值.
  2. 无符号使用前导位作为值的一部分,而带符号版本使用最左侧位来标识数字是正数还是负数.
  3. 有符号整数可以包含正数和负数.

还有其他差异吗?

language-agnostic unsigned signed integer

378
推荐指数
11
解决办法
35万
查看次数

如何在Java 8和Java 9中使用unsigned Integer?

在Oracle"原始数据类型" 页面中,它提到Java 8增加了对无符号整数和长整数的支持:

int:默认情况下,int数据类型是32位带符号的二进制补码整数,其最小值为-2 31,最大值为2 31 -1.在Java SE 8及更高版本中,您可以使用int数据类型表示无符号的32位整数,其最小值为0,最大值为2 32 -1.使用Integer该类将int数据类型用作无符号整数.有关更多信息,请参阅数字类一节.像静态方法compareUnsigned,divideUnsigned等已被添加到Integer类,以支持算术运算的无符号整数.

long:long数据类型是64位二进制补码整数.签名long的最小值为-2 63,最大值为2 63 -1.在Java SE 8及更高版本中,您可以使用long数据类型表示无符号64位long,其最小值为0,最大值为2 64 -1.当需要比int提供的值更宽的值时,请使用此数据类型.本Long类也包含类似的方法compareUnsigned,divideUnsigned等支持算术运算的无符号long.

但是,我发现无法声明无符号长整数或整数.例如,下面的代码给出了编译器错误消息"文字超出范围"(我当然使用的是Java 8),当它应该在范围内时(指定的值恰好是2 64 -1) :

public class Foo {
    static long values = 18446744073709551615L;

    public static void main(String[] args){
        System.out.println(values);
    }  
} …
Run Code Online (Sandbox Code Playgroud)

java unsigned java-8

78
推荐指数
5
解决办法
10万
查看次数

装配 - CMP后的JG/JNLE/JL/JNGE

我不理解JG/JNLE/JL/JNGECMP之后的说明.

例如,如果我有:

CMP al,dl
jg label1
Run Code Online (Sandbox Code Playgroud)

al=101; dl =200.

我们问jg什么?是al>dl吗?还是al-dl>0

在下一个代码上相同的prolbem:

test al,dl
jg label1
Run Code Online (Sandbox Code Playgroud)

我不明白我们比较什么,以及我们问什么" jg".

换句话说,我不明白我们何时会跳转到label1,何时不会.

谢谢.

x86 assembly eflags

53
推荐指数
2
解决办法
12万
查看次数

为什么在x86(-64)上有符号和无符号乘法不同的指令?

我认为2的补码的重点是对于有符号和无符号数字的操作可以采用相同的方式.维基百科甚至特别列出了多重作为其中一项有益的操作.那么为什么x86对每个都有单独的指令,mul并且imul?x86-64仍然如此吗?

x86 assembly x86-64 twos-complement

23
推荐指数
3
解决办法
1万
查看次数

来自VS 2008/2010的x86 MUL指令

Visual Studio或Visual C++ Express的现代(2008/2010)版本是否会在编译代码中生成x86 MUL指令(无符号乘法)?我似乎无法找到或设想它们出现在编译代码中的示例,即使使用无符号类型也是如此.

如果VS不使用MUL进行编译,是否有理由说明原因?

c++ compiler-construction x86 assembly visual-studio

16
推荐指数
2
解决办法
4106
查看次数

如果只需要结果的低部分,那么可以使用哪个2的补码整数运算而不将输入中的高位置零?

在汇编编程中,想要从寄存器的低位计算某些东西是相当普遍的,这些位不能保证将其他位置零.在像C这样的高级语言中,你只需将输入转换为小尺寸,让编译器决定是否需要分别将每个输入的高位归零,或者是否可以在输出之后切断结果的高位.事实.

这是为x86-64的(又名AMD64),出于各种原因尤其常见1,其中的一些是存在于其它的ISA.

我将使用64位x86作为示例,但目的是询问/讨论2的补码和无符号二进制算法,因为所有现代CPU都使用它.(注意,C和C++不保证两个补码4,并且有符号溢出是未定义的行为.)

作为示例,考虑一个可以编译为LEA指令2的简单函数.(在X86-64 SysV的(Linux)的ABI 3,前两个函数参数是rdirsi,与在返回rax. int是一个32位的类型.)

; int intfunc(int a, int b) { return a + b*4 + 3; }
intfunc:
    lea  eax,  [edi + esi*4 + 3]  ; the obvious choice, but gcc can do better
    ret
Run Code Online (Sandbox Code Playgroud)

gcc知道即使是负有符号整数,加法也只是从右到左,所以输入的高位不会影响进入的内容eax.因此,它保存了一个指令字节并使用 lea eax, [rdi + rsi*4 + 3]

哪些其他操作具有结果低位的这种属性而不依赖于输入的高位?

为什么它有效?



脚注

1为什么x86-64频繁出现这种情况:x86-64有可变长度指令,其中额外的前缀字节改变了操作数大小(从32到64或16),因此在指令中通常可以保存一个字节.以相同的速度执行.当写入低8b或16b的寄存器(或稍后读取完整寄存器(Intel pre-IvB)时的失速)时,它也具有错误依赖性(AMD/P4/Silvermont):由于历史原因, …

binary x86 assembly integer twos-complement

12
推荐指数
1
解决办法
928
查看次数

SIMD使用无符号乘法对64位*64位到128位进行签名

我创建了一个使用SIMD进行64位*64位到128位的功能.目前我已经使用SSE2(acutally SSE4.1)实现了它.这意味着它可以同时运行两个64b*64b到128b的产品.同样的想法可以扩展到AVX2或AVX512,同时提供四个或八个64b*64到128b的产品.我的算法基于http://www.hackersdelight.org/hdcodetxt/muldws.c.txt

该算法进行一次无符号乘法,一次有符号乘法和两次有符号*无符号乘法.签名的*signed和unsigned*unsigned操作很容易使用_mm_mul_epi32_mm_mul_epu32.但混合签名和未签名的产品给我带来了麻烦.例如,考虑一下.

int32_t x = 0x80000000;
uint32_t y = 0x7fffffff;
int64_t z = (int64_t)x*y;
Run Code Online (Sandbox Code Playgroud)

双字产品应该是0xc000000080000000.但是如果你假设你的编译器知道如何处理混合类型,你怎么能得到这个呢?这就是我想出的:

int64_t sign = x<0; sign*=-1;        //get the sign and make it all ones
uint32_t t = abs(x);                 //if x<0 take two's complement again
uint64_t prod = (uint64_t)t*y;       //unsigned product
int64_t z = (prod ^ sign) - sign;    //take two's complement based on the sign
Run Code Online (Sandbox Code Playgroud)

使用SSE可以这样做

__m128i xh;    //(xl2, xh2, xl1, xh1) high is signed, low unsigned
__m128i …
Run Code Online (Sandbox Code Playgroud)

c x86 integer sse bit-manipulation

9
推荐指数
2
解决办法
4203
查看次数

为什么ARM区分SDIV和UDIV而不是ADD,SUB和MUL?

正如标题中所述,为什么ARM指令集仅区分有符号和无符号?

SDIV和UDIV可用,但ADD,SUB和MUL不是这种情况.

binary assembly arm instruction-set division

2
推荐指数
1
解决办法
1623
查看次数

在机器代码中区分有符号和无符号

我在看一本教科书,上面写着:

重要的是要注意机器代码如何区分有符号和无符号值。与 C 不同,它不将数据类型与每个程序值相关联。相反,它主要对这两种情况使用相同的(汇编)指令,因为许多算术运算对于无符号和补码算术具有相同的位级行为。

我不明白这是什么意思,谁能给我举个例子?

c assembly unsigned

1
推荐指数
2
解决办法
1648
查看次数