2.SSE2命令の実装

2-2.構造体をアセンブリに渡す(64ビット版)

 今回は構造体をアセンブリコードに渡してみて、問題なく計算できるかを確認します。
 ソリューションエクスプローラのソースファイルにあるSource.asmがアセンブラのコードです。
 以下に内容を紹介します。
.code

;float funcSample(Vector* v)
funcSample  proc
    movss   xmm0,   dword ptr [rcx]
    addss   xmm0,   dword ptr [rcx+4]
    addss   xmm0,   dword ptr [rcx+8]
    addss   xmm0,   dword ptr [rcx+12]
    ret 
funcSample  endp
        end
 この関数は浮動小数点で形成された構造体のポインタを受け取ってその要素をすべて加算し返す関数です。
 単純な内容ですが構造体の受け渡しのテストになります。
 以下がC/C++側です。
#include <iostream>

struct Vector {
    float x;
    float y;
    float z;
    float w;
};


extern "C" float funcSample(Vector* v);

int main()
{
    Vector v = { 1.5f,2.3f,3.4f,4.5f };

    std::cout << funcSample(&v) << "\n";
}
 リビルドして実行すると
11.7

...\ProjectMASM\Sample202\x64\Debug\SampleMASM.exe (プロセス 15952) は、コード 0 を伴って終了しました。
このウィンドウを閉じるには、任意のキーを押してください . . .
 と表示されます。

コード解説

 アセンブリ側ではまず
    movss   xmm0,   dword ptr [rcx]
 という記述があります。
 ポインタの場合、最初の引数はrcxレジスタに入りますので、そのポインタの指す場所の値をxmm0に代入します。
 この構造体はfloat型のメンバですのでサイズは4バイトです、ですので次の要素の場所は[rcx+4]になります。
    addss   xmm0,   dword ptr [rcx+4]
 同様、4バイト先を読んでいって、xmm0に加算します。
 戻り値は浮動小数点ですのでxmm0の内容がC/C++側にもどされますので、そのままretします。

次のテーマは?

 さて、1章からここまで、C/C++とアセンブリの相互呼び出しをやってきました。
 しかしテキストベースでは、なかなか効果がわかりません。ですので次章からはガラッと趣を変えアセンブリコードをゲームに埋め込むということをやってみたいと思います。