问题描述
由于似乎没有 ADC 的内在函数,而且我不能使用 Visual C++ 对 x64 体系结构使用内联汇编器,如果我想使用带进位的加法编写函数但将其包含在一个C++ 命名空间?
Since there doesn't seem to be an intrinsic for ADC and I can't use inline assembler for x64 architecture with Visual C++, what should I do if I want to write a function using add with carry but include it in a C++ namespace?
(不能使用比较运算符进行模拟.这个 256 兆位的增加对性能至关重要.)
(Emulating with comparison operators is not an option. This 256 megabit add is performance critical.)
推荐答案
有现在是 MSVC 中 ADC
的内在:_addcarry_u64
.以下代码
#include <inttypes.h>
#include <intrin.h>
#include <stdio.h>
typedef struct {
uint64_t x1;
uint64_t x2;
uint64_t x3;
uint64_t x4;
} uint256;
void add256(uint256 *x, uint256 *y) {
unsigned char c = 0;
c = _addcarry_u64(c, x->x1, y->x1, &x->x1);
c = _addcarry_u64(c, x->x2, y->x2, &x->x2);
c = _addcarry_u64(c, x->x3, y->x3, &x->x3);
_addcarry_u64(c, x->x4, y->x4, &x->x4);
}
int main() {
//uint64_t x1, x2, x3, x4;
//uint64_t y1, y2, y3, y4;
uint256 x, y;
x.x1 = x.x2 = x.x3 = -1; x.x4 = 0;
y.x1 = 2; y.x2 = y.x3 = y.x4 = 0;
printf(" %016" PRIx64 "%016" PRIx64 "%016" PRIx64 "%016" PRIx64 "
", x.x4, x.x3, x.x2, x.x1);
printf("+");
printf("%016" PRIx64 "%016" PRIx64 "%016" PRIx64 "%016" PRIx64 "
", y.x4, y.x3, y.x2, y.x1);
add256(&x, &y);
printf("=");
printf("%016" PRIx64 "%016" PRIx64 "%016" PRIx64 "%016" PRIx64 "
", x.x4, x.x3, x.x2, x.x1);
}
从 Visual Studio Express 2013 生成以下程序集输出
produces the following assembly output from Visual Studio Express 2013
mov rdx, QWORD PTR x$[rsp]
mov r8, QWORD PTR x$[rsp+8]
mov r9, QWORD PTR x$[rsp+16]
mov rax, QWORD PTR x$[rsp+24]
add rdx, QWORD PTR y$[rsp]
adc r8, QWORD PTR y$[rsp+8]
adc r9, QWORD PTR y$[rsp+16]
adc rax, QWORD PTR y$[rsp+24]
按预期有一个 add
和三个 adc
.
which has one add
and three adc
as expected.
对于 _addcarry_u64
的作用似乎有些混乱.如果您查看我在本答案开头链接的 Microsoft 文档,它表明它不需要任何特殊硬件.这会生成 adc
并且它可以在所有 x86-64 处理器上运行(并且 _addcarry_u32
可以在更旧的处理器上运行).它在我测试过的 Ivy Bridge 系统上运行良好.
There seems to be some confusion as to what _addcarry_u64
does. If you look at Microsoft's documentation for this which I linked to at the start of this answer it shows that it does not require any special hardware. This produces adc
and it will work on all x86-64 processors (and _addcarry_u32
would work on even older processors). It works fine on the Ivy Bridge system I tested it on.
但是,_addcarryx_u64
确实需要 adx
(如 MSFT 的文档中所示)并且确实无法在我的 Ivy Bridge 系统上运行.
However, _addcarryx_u64
does require adx
(as shown in MSFT's documentation) and indeed it fails to run on my Ivy Bridge System.
这篇关于Visual C++ x64 加进位的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!