• 締切済み

VC++2010expressのアセンブラについて

下記の2個のファイルを持つプログラムでインラインアセンブラのcall命令で配列変数の1部が消滅する原因を教えてください。 main.cpp int *disp; int data[2]; WinMain() { _asm mov disp,offset disp_top ・ ・ ・ メッセージループへ _asm{ disp_top: 下記move()からcallされた時、ここの時点でdata[0]の内容が消滅している。data[1]の内容は1のまま存在する。 ・ ・ ・ ret   } } move.cpp extern int *disp; extern int data[2]; void move() { data[0]=1; data[1]=1; _asm{ call disp callから復帰した、ここの時点ではdata[0]の内容は1で復帰している。   } }

みんなの回答

回答No.5

 こんにちは。  インラインアセンブラは殆ど使用したことが無いので、当たっているかどうかは保障できませんが、レジスタの内容を退避しておかないといけないのでは。  「実際にインラインアセンブラを使用する時には」  http://7ujm.net/C++/asm1.html  pushad, popadで手っ取り早く出来る筈です。 void move() { data[0]=1; data[1]=1; _asm { //追加 pushad call disp callから復帰した、ここの時点ではdata[0]の内容は1で復帰している。 //追加 popad } }  VC6.0のインラインアセンブラは、レジスタの退避が自動で行われると言う話もありますが、真相は定かではありません。  後は、__asmキーワードが使用されている関数は、 ・インライン展開の対象にしてはならない。 ・呼び出し規約を__fastcallにしてはならない。  上記の条件を無視すると、不正なコードが作成される、と言うのは、昔のMSDNで見た記憶があります。

7777777v
質問者

お礼

レジスタの保存は試しましたが効果はありませんでした。 と言うより、アセンブラーの記述が殆どで関数呼び出しはごく一部になります。 >・インライン展開の対象にしてはならない。 >・呼び出し規約を__fastcallにしてはならない。 この回答は参考になりました。 また、「実際にインラインアセンブラを使用する時には」についても情報ありがとうございました。

すると、全ての回答が全文表示されます。
  • Tacosan
  • ベストアンサー率23% (3656/15482)
回答No.4

この質問に書かれたプログラムはコンパイルできるのですか?

7777777v
質問者

お礼

いつもありがとうございます。 実は、最初に提示したコードはあくまでエラーになる状況を踏まえたイメージになります。 実際にエラーを起こす場所を特定できないため、そのコードも提示出来ません。 今後は小さなプログラムから確認しながら積み上げる以外に方法はないと考えます。 ただ、コンパイラが変わった為に起きる不具合ですので、その違いを知りたかっただけです。 ありがとうございました。

すると、全ての回答が全文表示されます。
  • Tacosan
  • ベストアンサー率23% (3656/15482)
回答No.3

ん, まぁそういう反応があることは想定してたけどね.... そこはよく読んでほしいところで, 「問題が発生する完全なプログラム」と書いたのであって, 「あなたが今まさに作っているプログラム」ではない. つまり, 「今あるプログラムが大きすぎて入らない」というのであれば, 「同じ問題を起こすもっと小さなプログラム」をだせばいい. ま, #2 に書かれているようにアセンブリコードを見るとか, あるいはメモリマップから変数の割り付けを調べるとかはできそうだけど.

7777777v
質問者

補足

ご指摘の >「同じ問題を起こすもっと小さなプログラム」・・・ これについては、最初の質問に記載したコードになります。 しかし、短過ぎて原因を特定出来ないと思いますが、まさに、このような状況で変数の内容が変わっているのです。 信じられないことが起こっているのです。 コンパイラを6から2010にバージョンアップしたら、どうしてこのようになるのでしょうか? 対策を教えてください。 よろしくお願いします。

すると、全ての回答が全文表示されます。
  • toshiyuk
  • ベストアンサー率41% (36/87)
回答No.2

それほど詳しいわけではないですが 最適化されて使われてないとか、 逆アセンブルのコードを見ると分かるかも知れません。

7777777v
質問者

補足

わかりました、デバグを活用するのですね。 回答ありがとうございました。

すると、全ての回答が全文表示されます。
  • Tacosan
  • ベストアンサー率23% (3656/15482)
回答No.1

この問題が発生する ・完全なプログラム ・環境 を出すことはできませんか?

7777777v
質問者

補足

Tacosan毎度ありがとうございます。 開発マシンはNECバリュースター,OSはWindows7(64bit)Homeです。 プロジェクトはFalconと言うDirectXを使った3Dポリゴンゲームになります。 プラットホームはWIN32です。 プログラム全体のソース行は5832+8462+2144です。 ここでは質問文字数に制限があり、すべて紹介することはできません。 リンク方法に、/INCREMENTALを指定したいのですが次のようなエラーが出て指定できません。 LINK : warning LNK4075: /INCREMENTAL は /LTCG の指定によって無視されます。 また、/LTCG の指定を解除することができないのです。 フルリンクの設定方法も教えてください。 以下コマンドラインの指定です。 /Zi /nologo /W3 /WX- /O2 /Ob2 /Ot /Oy- /GL /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /Gm- /EHa /MT /Zp8 /GS- /Gy- /fp:fast /Zc:wchar_t /Zc:forScope /Fp"Release\FalconII.pch" /Fa"Release\" /Fo"Release\" /Fd"Release\vc100.pdb" /Gr /analyze- /errorReport:queue 以下はリンカの指定です。 /OUT:"D:\FalconII\Release\FalconII.exe" /INCREMENTAL /NOLOGO "kernel32.lib" "user32.lib" "gdi32.lib" "winspool.lib" "comdlg32.lib" "advapi32.lib" "shell32.lib" "ole32.lib" "oleaut32.lib" "uuid.lib" "odbc32.lib" "odbccp32.lib" /MANIFEST /ManifestFile:"Release\FalconII.exe.intermediate.manifest" /ALLOWISOLATION /MANIFESTUAC:"level='asInvoker' uiAccess='false'" /DEBUG /PDB:"D:\FalconII\Release\FalconII.pdb" /SUBSYSTEM:WINDOWS /LARGEADDRESSAWARE:NO /OPT:NOREF /OPT:NOICF /PGD:"D:\FalconII\Release\FalconII.pgd" /TLBID:1 /DYNAMICBASE /NXCOMPAT:NO /MACHINE:X86 /ERRORREPORT:QUEUE 以上よろしくお願いします。

すると、全ての回答が全文表示されます。

関連するQ&A