Visual C++ x64附带进位

jnm*_*nm2 7 c++ 64-bit inline-assembly intrinsics visual-c++

因为似乎没有ADC的固有内容而且我不能使用Visual C++的x64架构使用内联汇编程序,如果我想使用add with carry编写函数但是将它包含在C++命名空间中,我该怎么办?

(使用比较运算符进行仿真不是一种选择.这256兆位的添加对性能至关重要.)

Han*_*ant 7

VS2010内置支持编译和链接汇编编写的代码并由MASM(ml64.exe)翻译.你只需要跳过一些箍来启用它:

  • 在"解决方案资源管理器"窗口的"生成自定义"中右键单击该项目,勾选"masm".
  • Project + Add New Item,选择C++ File模板,但将其命名为something.asm
  • 确保您已获得该项目的x64平台目标.Build + Configuration Manager,在"Active solution platform"组合中选择"x64".如果缺少,请<New>从第一个组合中选择并选择x64.如果遗漏,您将不得不重新运行安装程序并添加对64位编译器的支持.

使用MASM语法编写汇编代码,参考在这里.快速入门教程就在这里.

汇编代码的框架如下所示:

.CODE
PUBLIC Foo
Foo PROC
  ret                    ; TODO: make useful
Foo ENDP
END
Run Code Online (Sandbox Code Playgroud)

并从C++代码调用如下:

extern "C" void Foo();

int main(int argc, char* argv[])
{
    Foo();
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

可以使用完全调试支持,您通常希望至少使用Debug + Windows + Registers窗口.


Z b*_*son 6

ADC在MSVC中现在有一种内在的:_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 "\n", x.x4, x.x3, x.x2, x.x1);
    printf("+");
    printf("%016" PRIx64 "%016" PRIx64 "%016" PRIx64 "%016" PRIx64 "\n", y.x4, y.x3, y.x2, y.x1);
    add256(&x, &y);
    printf("=");
    printf("%016" PRIx64 "%016" PRIx64 "%016" PRIx64 "%016" PRIx64 "\n", x.x4, x.x3, x.x2, x.x1);
}
Run Code Online (Sandbox Code Playgroud)

从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]
Run Code Online (Sandbox Code Playgroud)

其中有一个add和三个adc如预期的那样.

编辑:

似乎有什么困惑似乎有些混乱_addcarry_u64.如果您查看Microsoft在此答案开头时链接到的文档,则表明它不需要任何特殊硬件.这产生adc并且它将适用于所有x86-64处理器(并且_addcarry_u32甚至可以在较旧的处理器上工作).它在我测试它的Ivy Bridge系统上工作正常.

但是,_addcarryx_u64确实需要adx(如MSFT的文档中所示),实际上它无法在我的Ivy Bridge系统上运行.