代码之家  ›  专栏  ›  技术社区  ›  Martijn Courteaux

汇编ADC(加载进位)到C++

  •  15
  • Martijn Courteaux  · 技术社区  · 15 年前

    有汇编指令 ADC . 我发现这意味着“加上进位”。但我不知道 那个 手段。或者如何在C++中编写这个指令。我知道这和 ADD

    信息:

    6 回复  |  直到 8 年前
        1
  •  24
  •   Simone    15 年前

    ADC与ADD相同,但如果设置了处理器的进位标志,则会额外添加1。

        2
  •  8
  •   SuperGeo    9 年前

    here (破碎)或 here

    不过,英特尔处理器 有一个称为adc的特殊指令。 此命令的行为与 添加命令。唯一额外的是 它还添加了值进位标志 添加大整数。如果你愿意 添加16位的32位整数 登记册。我们怎么能做到?好, 保持在寄存器对DX:AX上,并且 怎样:

    add  ax, cx
    adc  dx, bx
    

    啊,那么首先,低16位加上 使用adc而不是add添加。它是 因为:如果有溢流 更高的16位。所以,不麻烦 检查。这种方法可以推广 到64位等等。。。注意:如果 在更高的16位,结果 不会是正确的 已设置,例如将50亿添加到5 十亿。

    下面是一个适用于VS2010的小示例(32位,WinXp)

    注意:$7.4/1-“asm声明是有条件支持的;它的含义是实现定义的。[注:通常用于将信息通过实现传递给汇编程序。尾注]“

    int main(){
       bool carry = false;
       int x = 0xffffffff + 0xffffffff;
       __asm {
          jc setcarry
    setcarry:
          mov carry, 1
       }
    }
    
        3
  •  6
  •   Sparky    15 年前

    可以在C和C++中模拟ADC行为。下面的示例添加了两个数字(存储为无符号数组,因为它们太大,无法放入单个无符号数组)。

    unsigned first[10];
    unsigned second[10];
    unsigned result[11];
    
    ....   /* first and second get defined */
    
    unsigned carry = 0;
    for (i = 0; i < 10; i++) {
        result[i] = first[i] + second[i] + carry;
        carry = (first[i] > result[i]);
    }
    result[10] = carry;
    

    希望这有帮助。

        4
  •  4
  •   Oshkosher    15 年前

    这里面有个虫子。尝试此输入:

    unsigned first[10] =  {0x00000001};
    unsigned second[10] = {0xffffffff, 0xffffffff};
    

    结果应该是{0,0,1,…},但结果是{0,0,0,…}

    carry = (first[i] > result[i]);
    

    对此:

    if (carry)
        carry = (first[i] >= result[i]);
    else
        carry = (first[i] > result[i]);
    

        5
  •  4
  •   Peter Cordes    9 年前

    C++语言没有任何进位标志的概念,因此在内部生成一个内部函数包装器。 ADC instruction unsigned char _addcarry_u32 (unsigned char c_in, unsigned a, unsigned b, unsigned * out); . 上次我检查时,gcc对此做得很差(将进位结果保存到整数寄存器中,而不是将其留在CF中),但希望英特尔自己的编译器做得更好。

    另请参见 为程序集文档标记wiki。


    int64_t 32位代码,或 __int128_t 64位代码。

    #include <stdint.h>
    #ifdef __x86_64__
    __int128_t add128(__int128_t a, __int128_t b) { return a+b; }
    #endif
        # clang 3.8 -O3  for x86-64, SystemV ABI.
        # __int128_t args passed in 2 regs each, and returned in rdx:rax
        add     rdi, rdx
        adc     rsi, rcx
        mov     rax, rdi
        mov     rdx, rsi
        ret
    

    来自的asm输出 Godbolt compiler explorer -fverbose-asm 不是很烦人,但是GCC5.3/6.1浪费了两个 mov

        6
  •  1
  •   Serg Stetsuk    9 年前
    unsigned long result;
    unsigned int first;
    unsigned int second;
    
    result = first + second;
    result += (result & 0x10000) ? 1 : 0;
    result &= 0xFFFF
    
    推荐文章