当前位置: 首页 > 知识库问答 >
问题:

长整数的二补

范弘亮
2023-03-14

我想做一些长整数数学(128位)与英特尔I64汇编和需要创建一个2的补充。假设我的正值在RDX:RAX中。

2的补码是通过“翻转位并加1”来完成的。所以最简单的实现是(4条指令和14字节的代码):

  NOT RAX
  NOT RDX
  ADD RAX,1   ; Can't use INC, it doesn't set Carry
  ADC RDX,0
  NOT RDX
  NEG RAX
  CMC
  ADC RDX,0                  ; fixed, thanks lurker

还是4个指令。但是我可以减去-1,而不是加+1,因为SBB将进位加到了减数,所以当进位是清晰的时,我会加+1。所以我下一个最好的尝试是,用3条指令和10字节的代码:

   NOT RDX
   NEG RAX
   SBB RDX,-1

正如你可以从我冗长的文本中看到的,这是不明显的理解。有没有一个更好的,更容易理解的方法来做一个级联的2的补足在汇编?

共有1个答案

管弘
2023-03-14

更短的指令或更少的指令并不一定意味着更快的执行,因为每个指令的延迟和吞吐量是不同的

例如,enterdadloop······会非常慢,它们只是为了向后兼容。甚至inc有时也比add慢。与上面在一些μArch上使用的cmc相同

因此,可以并行执行的一系列较长的低延迟指令将工作得更快。一些常见的指令组甚至可以融合到一个宏操作中。编译器的优化器总是知道这一点,并将选择最合适的指令发出。

__int128 negate(__int128 x)
{
    return -x;
}
    xor       edx, edx                                      #3.13
    xor       eax, eax                                      #3.13
    sub       rax, rdi                                      #3.13
    sbb       rdx, rsi                                      #3.13

前两个xor指令的开销为零μOP,因为它们是在寄存器重命名阶段处理的。现在您只有2条指令要执行

您可以在上面的Godbolt链接中切换编译器,以查看不同编译器包括MSVC(不幸的是,它还没有128位类型)进行否定的各种方法。下面是GCC和Clang的结果

海湾合作委员会8.3:

    mov     rax, rdi
    neg     rax
    mov     rdx, rsi
    adc     rdx, 0
    neg     rdx
    mov     rax, rdi
    xor     edx, edx
    neg     rax
    sbb     rdx, rsi

请注意,这个操作被称为求反,而不是二的补,后者是对负数进行编码的一种方式

 类似资料:
  • 问题内容: 我已经看到了javascript中最奇怪的事情之一。服务器端(弹簧): 我返回一个长值,并: 它将长整数表示为“ 793548328091516900”,将后两位数字(实际上四舍五入)为0。当我从任何浏览器的地址栏中发出GET请求时,数字均正确表示;因此,我认为这是一个js问题。 从服务器返回一个字符串而不是long并使用以下命令处理它: 显然是一个解决方案。但是我不是很幸运,我必须处

  • 问题内容: 如果我想对整数进行位操作,如何将其加载到?中?如何将其转换回int或long?我不太担心它的大小,它总是32或64位长。我只是想使用,,,和方法,而不是位运算符,但我无法找到一个简单的方法来初始化位集以数字类型。 问题答案: 以下代码从一个长值创建一个位集,反之亦然: 编辑:现在两个方向,@leftbrain:原因,你是对的

  • 这是一个至少为64 bit的整数类型(译注:实际宽度依赖于具体的实现平台),例如: long long x = 9223372036854775807LL; 不过,不要想当然地认为存在long long long或者将long拼写为short long long。 (译注:如同J. Stephen Adamczyk在参考文献中所言,”long long”是一个晦涩的拼写64-bit整数类型的方式

  • 我有3个非常大的有符号整数。 我想计算它们的截断平均值。预期平均值是,即。 不可能计算为: 注:我读了所有关于2个数字的平均值的问题,但我不知道该技术如何应用于3个数字的平均值。 使用BigInteger将非常容易,但假设我不能使用它。 如果我转换为双精度,那么,当然,我会失去精度: 如果我转换为,它可以工作,但也让我们假设我不能使用它。 问题:有没有一种方法可以仅使用长类型来计算3个非常大整数的

  • 问题内容: 我需要解析一个包含一个长数字的json(在Java servlet中产生)。问题在于长整数会四舍五入。 执行此代码时: 输出为: 在此处查看示例:http : //jsfiddle.net/huqUh/ 为什么会这样,我该如何解决呢? 问题答案: 正如其他人所说,这是因为数量太大。但是,可以通过将数字作为字符串发送来解决此限制,如下所示: 然后,您可以使用javascript-bign

  • 我正在使用Hibernate4.2和PostgreSQL。 我有这张表在邮局: 而我的实体是: 当我编写实体时,我将id设置为整数,但是,我从int改为Long,并开始出现以下错误: 谢谢:)