生でアセンブル言語を使用するのはちと敷居が高いので、インラインアセンブラから入ってみようという企画。ゆとり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 件のコメント:
コメントを投稿