哇,我花了一段时间才弄清楚。以下是仅用于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 个参数在寄存器中传递:RCX
、RDX
、R8
和R9
:
.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
平台。就我而言,它是。单击确定保存。Debug
Release
funcs_asm_x64.obj
(K)然后要使用我刚刚创建的这个函数,首先extern "C"
像在第一个项目中一样添加定义:
extern "C" __int64 __fastcall RdRand64(unsigned __int64* pRndVal);
然后你可以这样称呼它(显然它不能被内联):
unsigned __int64 randomNumber = 0;
__int64 bResult = RdRand64(&randomNumber);
(1) 显然,以上所有对于Win32
orx86
构建都不是必需的。为此,只需使用我在原始帖子中展示的内联汇编。
(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
则保存一个步骤并在同一个解决方案中完成所有操作。