みんなの「教えて(疑問・質問)」にみんなで「答える」Q&Aコミュニティ

こんにちはゲストさん。会員登録(無料)して質問・回答してみよう!

締切り済みの質問

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で復帰している。
  }
}

投稿日時 - 2011-05-11 16:53:57

QNo.6730174

すぐに回答ほしいです

このQ&Aは役に立ちましたか?

0人が「このQ&Aが役に立った」と投票しています

回答(5)

ANo.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で見た記憶があります。

投稿日時 - 2011-05-14 13:34:06

お礼

レジスタの保存は試しましたが効果はありませんでした。
と言うより、アセンブラーの記述が殆どで関数呼び出しはごく一部になります。

>・インライン展開の対象にしてはならない。
>・呼び出し規約を__fastcallにしてはならない。
この回答は参考になりました。

また、「実際にインラインアセンブラを使用する時には」についても情報ありがとうございました。

投稿日時 - 2011-05-14 18:07:51

ANo.4

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

投稿日時 - 2011-05-13 23:13:31

お礼

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

投稿日時 - 2011-05-14 18:16:07

ANo.3

ん, まぁそういう反応があることは想定してたけどね....

そこはよく読んでほしいところで, 「問題が発生する完全なプログラム」と書いたのであって, 「あなたが今まさに作っているプログラム」ではない. つまり, 「今あるプログラムが大きすぎて入らない」というのであれば, 「同じ問題を起こすもっと小さなプログラム」をだせばいい.

ま, #2 に書かれているようにアセンブリコードを見るとか, あるいはメモリマップから変数の割り付けを調べるとかはできそうだけど.

投稿日時 - 2011-05-13 13:37:52

補足

ご指摘の
>「同じ問題を起こすもっと小さなプログラム」・・・

これについては、最初の質問に記載したコードになります。

しかし、短過ぎて原因を特定出来ないと思いますが、まさに、このような状況で変数の内容が変わっているのです。
信じられないことが起こっているのです。
コンパイラを6から2010にバージョンアップしたら、どうしてこのようになるのでしょうか?

対策を教えてください。
よろしくお願いします。

投稿日時 - 2011-05-13 17:04:10

ANo.2

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

投稿日時 - 2011-05-13 12:54:01

補足

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

投稿日時 - 2011-05-13 16:53:13

ANo.1

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

投稿日時 - 2011-05-12 01:13:59

補足

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

以上よろしくお願いします。

投稿日時 - 2011-05-12 10:33:22

あなたにオススメの質問