インラインアセンブラでの変数アドレス取得

解決


みやざき  2006-04-10 18:49:27  No: 61186  IP: 192.*.*.*

Visual Studio .NET 2003 上の Visual C++ で、
インラインアセンブラを書いています。

ある変数に値を代入する際に、
この変数のアドレスを取得するところでつまずいています。
教科書を見ながら、 

...
int a; 
__asm{ 
     mov ebx, offset a
  mov eax, 12345678
  mov [ebx], eax


と書けば、a に 12345678 が代入されるのかな ? と思ったのですが、
ビルドすると、
「error C2415: オペランドの型が無効です。」
と怒られます。
どのように直せばよいか (どのようにすると変数 a のアドレスを
取得することができるのか)、どなたかご教示下さい。
よろしくお願いします。

編集 削除
tetrapod  2006-04-10 19:04:07  No: 61187  IP: 192.*.*.*

その辺はアセンブラの知識だけでなく、コンパイラがどう変数を取り扱うかの知識が必要です。
ix86 でレジスタ変数に最適化されない自動変数なら bp 経由でアクセスすることになります。
とりあえず a に値を設定するだけなら mov  a, 12345678
どうしてもアドレス値がほしいのなら lea ebx, [a]
ここで [a] は実際には [ebp].a なり [esp].a になっていることを理解してください。
自動変数でなく静的変数なら提示のとおり mov ebx,offset a っすね。

編集 削除
みやざき  2006-04-11 11:11:39  No: 61188  IP: 192.*.*.*

tetrapod さん。
コメントありがとうございました。

まだ完全には理解できていませんが、
最低限の知りたかったことは分かりました。
ありがとうございました。

□ 分かったこと

> 自動変数でなく静的変数なら提示のとおり mov ebx,offset a っすね。
⇒ 元のプログラムで、int a としていたところを static int a とすれば OK であることを確認。

> どうしてもアドレス値がほしいのなら lea ebx, [a]
⇒ 元のプログラムで試してみて、実際に OK であることを確認。

□ まだ理解が進んでいないこと

> ix86 でレジスタ変数に最適化されない自動変数なら bp 経由でアクセスすることになります。

> ここで [a] は実際には [ebp].a なり [esp].a になっていることを理解してください。

の辺り。
もうちょっと勉強してまだ分からなかったら再度質問させて下さい。

ありがとうございました。

編集 削除
tetrapod  2006-04-12 09:32:32  No: 61189  IP: 192.*.*.*

自分で勉強されるとの事ですが、蛇足など。
とりあえず VC++ (with ix86 clones) に話を限定。

とにかくコンパイラにリストファイルを作らせて読んでみるといいです。
コンパイラが何をどう取り扱っているのか、全てそこにあります。

・自動変数は(レジスタ変数に最適化されない場合)スタックに取られる
・スタックに取られる=ESP 相対 (または EBP 相対) でアクセスする必要がある
  つまり [ESP+nn] や [EBP+mm] でアクセスする必要がある
・先の nn や mm が具体的にいくつかはコンパイル時に確定している
・実際に当該関数が呼ばれないと ESP や EBP の値はわからない
ことから、自動変数 a のアドレスは LEA EBX, [ESP+16] のように求めます。
コンパイラの最適化によって ESP を使うか EBP を使うかがが変わり
自動変数の量や定義順などによって +16 などの数値が変わることから
LEA EBX, [a] とだけ書いておけば、コンパイラが勝手に
[a] の部分を [ESP+16] や [EBP-24] のように直してくれます。

この辺を判りやすく(正確さを欠いても)説明した文書ってなかなかないなぁ。
64bit 文書なら
http://msdn2.microsoft.com/ja-jp/library/ew5tede7(VS.80).aspx
68000 系でもよければ
http://hata.cc/docs/software-guide/2-5-2.html

編集 削除