2009年11月15日日曜日

VC++でインラインアセンブラ

Check
おもろそうな記事を見つけたので試してみた。
生でアセンブル言語を使用するのはちと敷居が高いので、インラインアセンブラから入ってみようという企画。ゆとりPGの自分にはちょうどいい。

用語の整理
  • ロード メモリからレジスタに値を読み込むこと
  • ストア レジスタの値をメモリに書き込むこと
  • 汎用レジスタ いろんな計算に使える便利なやつ。EAX~EDXまであるようだ

とりあえず実践。出力は普通にcoutを使うよ。
#include <iostream>
using namespace std;
// iに100を代入して表示するだけのプログラム
int main()
{
    int i;
    __asm
    {
        mov i, 100;
    }
    cout << i << endl;
}
次にレジスタを使ってみる。
#include <iostream>
using namespace std;
// レジスタに0xFFFF0000をロードしてiにストアするプログラム
int main()
{
    int i;
    __asm
    {
        mov eax, 0xFFFF0000;
        mov i, eax;
    }
    cout << hex << i << endl;// ffff0000
}
配列を扱うときは、インデクスの値に注意。インデクスを1つ増やしてもアセンブラでは1バイトしか移動しないようだ。そこで、Cでいうところの[sizeof(int)]と同じ役割を持つ[type 変数名]をインデクス値にかけてやる必要がある。
#include <iostream>
using namespace std;
//配列arrayに値を代入するプログラム
int main()
{
    int array[4];

    __asm
    {
        mov array[0], 100;
        mov array[1*type array], 200;//1*sizeof(int)と同じ。これでポインタが4バイト移動する
        mov array[2*type array], 300;
        mov array[3*type array], 400;
    }
 
    for(int i=0;i<4; ++i)
    {
        cout << "array[" << i << "] = " << array[i] << endl;
    }
    return 0;
}

みんな大好きポインタ篇
#include <iostream>
using namespace std;
int main()
{
    int i;
    int *p = &i;//pにiのアドレスを格納
    __asm
    {
        mov ebx, p;ポインタ用のレジスタEBXにpをロード
        mov [ebx], 100;*pに100をストア
    }
    cout << i << endl;//100
    return 0;
}

ポインタが指す実体を参照したい場合は、レジスタ名を[]で囲むといいようだ。ポインタ変数pに対する*pと同じことが、レジスタEBXに対する[EBX]で行えるというわけだ。

なお、__asmブロック内ではC/C++のコメント//や/**/が使えるほか、;の後ろも1行コメントとして認識されるらしい。

構造体も扱えちゃう
#include <iostream>
using namespace std;
//適当に構造体を作成
struct FOO
{
    int val1, val2;
};

int main()
{
    FOO a;//実体を作る
    FOO *p = &a;//aへのポインタ
    __asm
    {
        mov ebx, p//aのアドレスをレジスタEBXにロード
        mov [ebx]a.val1, 100/*ポインタを参照してa.val1に100をストア*/
        mov [ebx]a.val2, 200;同様にa.val2に200をストア
    }
    cout << "a.val1 = " << a.val1 << endl;// a.val1 = 100
    cout << "a.val2 = " << a.val2 << endl;// a.val2 = 200
    return 0;
}
次回は演算を勉強しよう…

0 件のコメント:

コメントを投稿