1

我正在 Visual Studio 2008 IDE 中开发一个 C++ 项目,我需要在其中使用 Intel 的新RDRAND指令。我进行了快速搜索,MSDN 建议使用_rdrand64_step中定义的内在函数immintrin.h,而我在 VS 2008 中没有。

在 32 位编译代码中,我可以使用asm以下关键字:

    __asm
    {
        xor eax, eax

        ;RDRAND instruction = Set random value into EAX.
        ;Will set overflow [C] flag if success
        _emit 0x0F
        _emit 0xC7
        _emit 0xF0
    }

asm但不支持x64 。

您能否建议我如何使用该RDRAND指令将我的项目编译为 64 位?

4

3 回答 3

5

您要么需要将编译器升级到支持_rdrand64_step内在函数的编译器(自 Visual Studio 2012 起支持),要么使用普通(外部)程序集来创建自己的函数(因为 Visual C++ 不支持 x86-64 目标的内联程序集)。

例如:

_TEXT   SEGMENT

    PUBLIC rdrand32_step
    PUBLIC rdrand32_retry
    PUBLIC rdrand64_step
    PUBLIC rdrand64_retry

    ; int rdrand32_step(unsigned *p)
rdrand32_step PROC
    xor     eax, eax
    rdrand  edx
    ; DB    0fh, 0c7h, 0f2h
    setc    al
    mov     [rcx], edx
    ret
rdrand32_step ENDP

    ; unsigned rdrand32_retry()
rdrand32_retry PROC
retry:
    rdrand  eax
    ; DB    0fh, 0c7h, 0f0h
    jnc     retry
    ret
rdrand32_retry ENDP

    ; int rdrand64_step(unsigned long long *p)
rdrand64_step PROC
    xor     eax, eax
    rdrand  rdx
    ; DB    048h, 0fh, 0c7h, 0f2h
    setc    al
    mov     [rcx], edx
    ret
rdrand64_step ENDP

    ; unsigned long long rdrand64_retry()
rdrand64_retry PROC
retry:
    rdrand  rax
    ; DB    048h, 0fh, 0c7h, 0f0h
    jnc     retry
    ret
rdrand64_retry ENDP

_TEXT   ENDS

    END

如果您使用 Visual Studio 2008 中的 MASM 版本,您可能必须注释掉 RDRAND 指令并取消注释它们后面的 DB 指令。

于 2016-06-27T01:52:54.843 回答
0

哇,我花了一段时间才弄清楚。以下是仅用于x64编译的 Visual Studio 2008 的步骤:

(A)创建一个空白项目:File -> New -> Project。然后单击“Visual C++”并选择“空项目”。命名它,然后单击确定创建。

(B)转到您的 VS 安装文件夹,在我的情况下C:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\VCProjectDefaults,复制masm.rules文件并命名masm64.rules

(C)在记事本中打开masm64.rules并搜索Microsoft Macro Assembler并将其更改为x64 Microsoft Macro Assembler. 将有两个地方可以做到这一点。然后搜索ml.exe并将其更改为ml64.exe. 然后保存该文件并关闭记事本。

(D)在“解决方案资源管理器”中右键单击您的项目并选择“自定义构建规则”并检查x64 Microsoft Macro Assembler并单击确定。

(E)在“解决方案资源管理器”中右键单击您的项目并选择添加 -> 新项目,选择Text File (.txt)并命名为带有.asm扩展名的名称。我会打电话funcs_asm_x64.asm的。然后单击确定。

(F)打开funcs_asm_x64.asm并输入您的 x64 asm。对我来说,我对RDRAND使用 64 位操作数调用很感兴趣。我做了以下。该函数将一个参数作为一个指向 64 位整数的指针,它将用随机位填充。如果成功则返回 1 rax,否则返回 0。

这里要记住的一件事是 x64 代码仅使用__fastcall 调用约定,这意味着函数的前 4 个参数在寄存器中传递:RCXRDXR8R9

.code

RdRand64  PROC
    ; RCX = pointer to receive random 64-bit value
    ; RETURN: [RAX] = 1 if success, 0 if failed

    xor         rax, rax

    test        rcx, rcx
    jz          lbl_out

    ;push       rdx
    xor         rdx, rdx
    DB          048h, 0fh, 0c7h, 0f2h       ;RDRAND RDX

    setc        al
    mov         [rcx], rdx
    ;pop        rdx

 lbl_out:
    ret

RdRand64  ENDP

END

(G)然后在“解决方案资源管理器”中右键单击您的项目并选择添加 -> 新建项目,选择C++ File (.cpp)并命名它main.cpp并单击确定创建。然后将以下内容添加到main.cpp文件中:

extern "C" __int64 __fastcall RdRand64(unsigned __int64* pRndVal);

 void main()
{
}

主要部分是extern "C"定义。main()需要方法来满足 MASM 要求。

(H)然后转到构建 -> 配置管理器并打开显示“活动解决方案平台”的下拉列表并选择新建。然后在“类型或选择新平台”中选择“x64”,然后单击“确定”。然后选择“x64”作为“活动解决方案平台”,并在“活动解决方案配置”中选择“发布”。

(I)关闭配置管理器窗口并构建解决方案。如果成功,请funcs_asm_x64.obj在文件\x64\Release夹中为您的解决方案查找文件。将该文件复制到您的主要解决方案文件夹中(您需要使用RDRAND说明的位置。)

(J)然后在您需要使用RDRAND指令的主要解决方案中,在“解决方案资源管理器”中右键单击您的项目并转到属性。然后转到链接器-> 命令行并添加您的 obj 文件名。显然,这样做仅适用于和的x64平台。就我而言,它是。单击确定保存。DebugReleasefuncs_asm_x64.obj

(K)然后要使用我刚刚创建的这个函数,首先extern "C"像在第一个项目中一样添加定义:

extern "C" __int64 __fastcall RdRand64(unsigned __int64* pRndVal);

然后你可以这样称呼它(显然它不能被内联):

unsigned __int64 randomNumber = 0;
__int64 bResult = RdRand64(&randomNumber);

(1) 显然,以上所有对于Win32orx86构建都不是必需的。为此,只需使用我在原始帖子中展示的内联汇编。

(2) 同样显然您需要调用__cpuid命令以确保RDRAND支持该指令。在许多 CPU 上仍然不是。所以如果不是,那么不要调用我的RdRand64方法,因为它会崩溃!您可以使用此代码检查结果并将其存储在全局变量中的某处:

#include <intrin.h>

bool is_RDRAND_supported()
{
    int name[4] = {0};
    __cpuid(name, 0);

    if(name[1] == 0x756e6547 &&         //uneG
        name[2] == 0x6c65746e &&        //letn
        name[3] == 0x49656e69)          //Ieni
    {
        int data[4] = {0};
        __cpuid(data, 1);

        //Check bit 30 on the 2nd index (ECX register)
        if(data[2] & (0x1 << 30))
        {
            //Supported!
            return true;
        }
    }

    return false;
}

(3) 有一种方法可以asm将同一项目中的文件包含在VS 2008. 不幸的是,如果您这样做,您将无法在需要时将项目切换回Win32并编译。因此,如果您仅编译它,x64则保存一个步骤并在同一个解决方案中完成所有操作。

于 2016-06-27T06:10:09.023 回答
0

这相当简单,虽然是间接的:为_rdrand64_step. . VS2008 编译器可能不知道该指令,但 VS2008 链接器并不关心。

于 2016-06-27T10:50:27.423 回答