2009年11月15日日曜日

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

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

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

とりあえず実践。出力は普通にcoutを使うよ。
01#include <iostream>
02using namespace std;
03// iに100を代入して表示するだけのプログラム
04int main()
05{
06    int i;
07    __asm
08    {
09        mov i, 100;
10    }
11    cout << i << endl;
12}
次にレジスタを使ってみる。
01#include <iostream>
02using namespace std;
03// レジスタに0xFFFF0000をロードしてiにストアするプログラム
04int main()
05{
06    int i;
07    __asm
08    {
09        mov eax, 0xFFFF0000;
10        mov i, eax;
11    }
12    cout << hex << i << endl;// ffff0000
13}
配列を扱うときは、インデクスの値に注意。インデクスを1つ増やしてもアセンブラでは1バイトしか移動しないようだ。そこで、Cでいうところの[sizeof(int)]と同じ役割を持つ[type 変数名]をインデクス値にかけてやる必要がある。
01#include <iostream>
02using namespace std;
03//配列arrayに値を代入するプログラム
04int main()
05{
06    int array[4];
07 
08    __asm
09    {
10        mov array[0], 100;
11        mov array[1*type array], 200;//1*sizeof(int)と同じ。これでポインタが4バイト移動する
12        mov array[2*type array], 300;
13        mov array[3*type array], 400;
14    }
15  
16    for(int i=0;i<4; ++i)
17    {
18        cout << "array[" << i << "] = " << array[i] << endl;
19    }
20    return 0;
21}

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

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

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

構造体も扱えちゃう
01#include <iostream>
02using namespace std;
03//適当に構造体を作成
04struct FOO
05{
06    int val1, val2;
07};
08 
09int main()
10{
11    FOO a;//実体を作る
12    FOO *p = &a;//aへのポインタ
13    __asm
14    {
15        mov ebx, p//aのアドレスをレジスタEBXにロード
16        mov [ebx]a.val1, 100/*ポインタを参照してa.val1に100をストア*/
17        mov [ebx]a.val2, 200;同様にa.val2に200をストア
18    }
19    cout << "a.val1 = " << a.val1 << endl;// a.val1 = 100
20    cout << "a.val2 = " << a.val2 << endl;// a.val2 = 200
21    return 0;
22}
次回は演算を勉強しよう…

0 件のコメント:

コメントを投稿