有汇编指令ADC
。我发现这意味着“随身携带”。但我不知道 意味着什么。或者如何用C ++编写这个指令。我知道它与ADD
不一样。所以做一个简单的求和是不正确的。
信息:
在Windows中编译。我正在使用32位Windows安装。我的处理器是英特尔的Core 2 Duo。
答案 0 :(得分:22)
ADC与ADD相同,但如果设置了处理器的进位标志,则会额外增加1。
答案 1 :(得分:7)
但是,英特尔处理器 有一个叫做adc的特殊指令。 此命令的行为与 添加命令。唯一的额外的事情是 它还添加了值进位标志 沿。所以,这可能非常方便 添加大整数。假设你喜欢 添加一个16位的32位整数 寄存器。我们怎么做?好, 让我们说第一个整数是 寄存器对DX:AX,和 第二个是BX:CX。这是 方法:
add ax, cx adc dx, bx
啊,首先,低16位被添加 添加ax,cx。然后是更高的16位 使用adc而不是add添加。它是 因为:如果有溢出, 进位自动添加 更高的16位。所以,没有繁琐 检查。这种方法可以扩展 到64位等等...注意:如果 32位整数加法溢出 在更高的16位,结果也是如此 将不正确和进位标志 设定,例如增加50亿到5 十亿。
从这里开始的一切,请记住,它几乎落入了实现定义行为的区域。
这是一个适用于VS 2010(32位,WinXp)的小样本
警告:$ 7.4 / 1-“asm声明是有条件支持的;它的含义是实现定义的。[注意:通常它用于通过实现将信息传递给汇编程序。-end note]”
int main(){
bool carry = false;
int x = 0xffffffff + 0xffffffff;
__asm {
jc setcarry
setcarry:
mov carry, 1
}
}
答案 2 :(得分:6)
可以在C和C ++中模拟ADC行为。以下示例添加了两个数字(存储为unsigned数组,因为它们太大而无法放入单个无符号数组中)。
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;
希望这有帮助。
答案 3 :(得分:4)
这有一个错误。试试这个输入:
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]);
修复它。
答案 4 :(得分:3)
C ++语言没有任何进位标志的概念,因此围绕ADC
instruction制作内在函数包装器是笨重的。但是,英特尔无论如何都做到了:unsigned char _addcarry_u32 (unsigned char c_in, unsigned a, unsigned b, unsigned * out);
。最后我检查了一下,gcc做得很差(将进位结果保存到整数寄存器中,而不是将其保留在CF中),但希望英特尔自己的编译器做得更好。
另请参阅x86标记wiki以获取程序集文档。
当添加比单个寄存器更宽的整数时,编译器将为您使用ADC,例如:在32位代码中添加int64_t
,或在64位代码中添加__int128_t
。
#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
来自Godbolt compiler explorer的asm输出。 clang的-fverbose-asm
并不是很宽松,但gcc 5.3 / 6.1浪费了两条mov
指令,因此它的可读性较差。
答案 5 :(得分:0)
unsigned long result;
unsigned int first;
unsigned int second;
result = first + second;
result += (result & 0x10000) ? 1 : 0;
result &= 0xFFFF