うわー、それを理解するのにしばらく時間がかかりました。x64
コンパイルのみの Visual Studio 2008 の手順は次のとおりです。
(A)空のプロジェクトを作成します: ファイル -> 新規 -> プロジェクト。次に、[Visual C++] をクリックし、[空のプロジェクト] を選択します。何か名前を付けて、[OK] をクリックして作成します。
(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
ます。それを行う場所は2つあります。次に、 を検索しml.exe
て変更しml64.exe
ます。次に、そのファイルを保存してメモ帳を閉じます。
(D) [ソリューション エクスプローラー] でプロジェクトを右クリックし、[カスタム ビルド規則] を選択し、チェックx64 Microsoft Macro Assembler
して [OK] をクリックします。
(E)「ソリューション エクスプローラー」でプロジェクトを右クリックし、[追加] -> [新しい項目] を選択し、拡張子Text File (.txt)
を付けて名前を付けます。.asm
私はそれを呼びますfuncs_asm_x64.asm
。次に、[OK] をクリックします。
(F)funcs_asm_x64.asm
x64 asm を開いて入力します。私にとってはRDRAND
、64 ビットのオペランドで呼び出すことに興味がありました。私は次のことをしました。この関数は、ランダムなビットで埋められる 64 ビット整数へのポインターとして 1 つのパラメーターを受け取ります。rax
成功した場合は 1 を返し、それ以外の場合は 0 を返します。
ここで覚えておくべきことの 1 つは、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
、[OK] をクリックして作成します。次に、main.cpp
ファイルに次を追加します。
extern "C" __int64 __fastcall RdRand64(unsigned __int64* pRndVal);
void main()
{
}
主要部分はextern "C"
定義です。main()
メソッドは、MASM 要件を満たすために必要です。
(H)次に、[ビルド] -> [構成マネージャー] に移動し、[アクティブなソリューション プラットフォーム] と表示されているドロップダウン リストを開き、[新規] を選択します。次に、「新しいプラットフォームを入力または選択します」で「x64」を選択し、「OK」をクリックします。次に、「アクティブ ソリューション プラットフォーム」として「x64」を選択し、「アクティブ ソリューション構成」で「リリース」を選択します。
(I)構成マネージャー ウィンドウを閉じて、ソリューションをビルドします。成功した場合は、ソリューションのフォルダー内のfuncs_asm_x64.obj
ファイルを探します。そのファイルをメインのソリューション フォルダー (手順\x64\Release
を使用する必要がある場所) にコピーします。RDRAND
(J)次に、命令を使用する必要があるメイン ソリューションで、RDRAND
[ソリューション エクスプローラー] でプロジェクトを右クリックし、[プロパティ] に移動します。次に、Linker -> Command Line に移動し、obj ファイル名を追加します。明らかに、およびのx64
プラットフォームに対してのみそうします。私の場合は でした。[OK] をクリックして保存します。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
、ステップを保存して、すべてを同じソリューションで実行します。