[過去ログ] Visual Studio 2008 Part 22 (314レス)
上下前次1-新
このスレッドは過去ログ倉庫に格納されています。
次スレ検索 歴削→次スレ 栞削→次スレ 過去ログメニュー
203(2): 2018/09/16(日)08:02 ID:SOVIz+sV(6/15) AAS
?-2 デフォルト設定(Release)
↓このコードの逆アセンブルコード
外部リンク:ideone.com
【実行結果】
↓実行結果を書き込めないからこっちに書き込んどいた
外部リンク:ideone.com
0x0007F2C44DFFF8F1:1.1053482540585101e-308
204: 2018/09/16(日)08:05 ID:SOVIz+sV(7/15) AAS
?-1 最適化無効 (/Od)(Release)
※ コードは?-1(>>200)と同じ
↓このコードの逆アセンブルコード
外部リンク:ideone.com
【実行結果】
0x0007F2C44DFFF8F1:1.1053482540585101e-308
205: 2018/09/16(日)08:09 ID:SOVIz+sV(8/15) AAS
?-2 最適化無効 (/Od)(Release)
※ コードは?-2(>>202)と同じ
↓このコードの逆アセンブルコード
外部リンク:ideone.com
【実行結果】
※ ?-2(>>203)と同じ
省1
206(1): 2018/09/16(日)08:20 ID:SOVIz+sV(9/15) AAS
?-1、?-2の逆アセンブルの出力結果を比較すると原型をとどめてないぐらいグチョグチョに違う(最適化のせいと考えられる)
?-1、?-2の逆アセンブルの出力結果を比較すると差異はほとんどない(?は両方ともまったく最適化されてないから当然)
?-1と?-1の逆アセンブルの出力結果を比較すると原型をとどめてないぐらいグチョグチョに違う(?-1のコード(>>200)ははげしくウンコ最適化されてると考えられる)
?-2と?-2の逆アセンブルの出力結果を比較すると差異はほとんどない(?-2のコード(>>202)はあまり最適化されてないと考えられる)
はっきりいって、これ以上見る気もしないしテキトーだが
ウンコみたいな最適化で演算の順序が入れ替わったせいで、誤差が発生しているものと考えられる
207: 2018/09/16(日)08:28 ID:zL1WUjLu(1/27) AAS
>>198以降、
すまん、入れ替わりになるかもしれんが後で確認する。
まず>>194その他について回答する。
>>194
SSEは /arch:SSE または /arch:SSE2 でないと出ないことになっており、勿論設定はしていない。
また、逆アセンブル結果では x87 命令のみであるのも確認している。
ただ今回の問題は、本当にReleaseビルドのバイナリを逆アセンブルしているか怪しい事だが。
>>195
小さい値なのは偶々だ。
辿って行ってそれが1回目にヒットする入力データだっただけのこと。
省10
208(1): 2018/09/16(日)08:29 ID:zL1WUjLu(2/27) AAS
>>194
FPU control registor については何故か安定した結果を得られていない。
インラインアセンブラは以下の通りで、
#pragma unmanaged
inline void fpu_getcw(unsigned short* cw) {
__asm{
fnstcw [cw];
}
}
#pragma managed
省14
209(3): 2018/09/16(日)08:29 ID:zL1WUjLu(3/27) AAS
>>194
直後のみに配置:
0x027F (倍精度) = Debug(IDE起動)のIDE内表示、Release(IDE起動)のIDE内表示、
0x03a5 (拡張倍精度) = Debug(IDE起動)、Release(IDE起動)、
0x3fdc (拡張倍精度) = Debug(コマンドプロンプト)、
0xf280, 0xf290, 0xf160, 0xf010等、不安定 = Release(コマンドプロンプト)
直前のみに配置:
直後のみと同じ結果。(つまり『何故か』安定している)
Release(コマンドプロンプト)は不安定なのも同じ。
直前と直後に配置:
省11
210: 2018/09/16(日)12:52 ID:haV9TZ8e(1/12) AAS
>>209
興味深い結果だ。
211(1): 2018/09/16(日)13:21 ID:haV9TZ8e(2/12) AAS
>>209
>命令自体は rdtsc と同じで非同期に実行されている雰囲気だが、
>rdtsc命令の注意書きにある「シリアル化命令ではない」という但し書きが無く、状況は不明。
>正直、正しく読み出せているか怪しい。(あてにならない)
インラインアセンブラを使わずに、
_control87(), _controlfp() : Get and set the floating-point control word.
unsigned int _control87( unsigned int new, unsigned int mask );
unsigned int _controlfp( unsigned int new, unsigned int mask );
を使ってみたらどうなる?
212(1): 2018/09/16(日)13:31 ID:Q5j4SiHR(1/2) AAS
win32コンソールなら結果が同じ。 もう理由は分かったのに何が問題なんだ?こんなの何の影響もないだろう。
213(1): 2018/09/16(日)13:33 ID:zL1WUjLu(4/27) AAS
>>198
再現実験ありがとう。
しかし色々問題がある。
1. 俺は起動方法による違いについてフォーカスしているが、
君はRelease/Debugの違いにフォーカスしている。
2. VC++2008では再現しない。(VC++2010では再現する)
3. ソース改変しすぎ。それでは意味がない。
4. >>206の結論は間違い。
まず問題なのはソースの改変だ。
ループ回数を16回と決め打ちしたことで 8*2 に展開されている。
省14
214: 2018/09/16(日)13:33 ID:zL1WUjLu(5/27) AAS
>>198
問題は、俺の環境で俺が提供したコード>>191だと、
同様に展開されないにも関わらず、『起動方法によって』結果が異なってしまう点だ。
俺の環境でのRelease/Debugの逆アセンブル結果のdiffは以下。
17c17
< 0000000c cmp dword ptr ds:[001C2E14h],0
---
> 0000000c cmp dword ptr ds:[00702E14h],0
19c19
< 00000015 call 68302BA9
省21
215: 2018/09/16(日)13:53 ID:haV9TZ8e(3/12) AAS
>>213
なるほど、全く別の2つの理由で、精度が変わっている可能性(というより多分、確実)があると。
それは以下の2つ:
1. Debug版とRelease版では、最適化の結果、x87 FPU命令の使われ方が変わる。
x87では、メモリに書き戻さずに st(0)〜st(7)レジスタに入っている途中では、
拡張倍精度の80BITで計算されるが、書き戻すとdoubleの場合でも64BITに丸め
られる。なるべくメモリに書き戻さずにレジスタった方が高速なので、Release版
では、80BITで計算される「期間」が多くなる。そのため、Debug版とRelese版では
結果が僅かに違ってくる。
2. fpu control word が違っていて、st(0)〜st(7)に入っていても、計算が
省5
216: 2018/09/16(日)13:58 ID:haV9TZ8e(4/12) AAS
まず、
__asm{
fnstcw [cw];
}
ではなく、_control87() を使ってみて欲しい。
インラインアセンブラは、独立した *.asm で書くより危険な場合が
あるかも知れないので。特にC関数の引数、今の場合は、「cw」を
インライン・アセンブラで用いた場合、正しいコードが出ているかどうか
は注意が必要。
217: 2018/09/16(日)14:05 ID:haV9TZ8e(5/12) AAS
>>208
よく見ると、それは、かなり複雑な事情が絡みそうなコード。
以下のようにした方が安心。なお、「cw」という短すぎる引数名
も長年のプログラミング経験からすると、インラインアセンブラでは
怖い。また、
TTTT reg,引数名
や
TTTT 引数名
は大丈夫でも、
TTTT reg,[引数名]
省14
218(4): 2018/09/16(日)14:17 ID:haV9TZ8e(6/12) AAS
あ、後、インライン・アセンブラで実験する場合は、関数名の inline は
「取った」方がいい。つまり、以下の方が安心:
#pragma unmanaged
void fpu_getcw(unsigned short *pCW) {
__asm{
mov edx,pCW
fnstcw [edx];
}
}
#pragma managed
219(2): 2018/09/16(日)15:23 ID:h8nMbN0G(1) AAS
また基本に戻るが、>>192で/MDになってるので
/MTや/MTdでも発生するかしてみた方がいい
220(1): 2018/09/16(日)15:37 ID:Q5j4SiHR(2/2) AAS
.netはx87コンテキストをすべて保持しませんって分かったんだからもう十分。
win32かx64にすれば解決。そもそも問題になる仕様バグじゃない。
221(1): 2018/09/16(日)15:40 ID:haV9TZ8e(7/12) AAS
>>219
ホントだ。/MDだと、Runtime Library として DLL のものを使ってしまう。
これは、今回の現象に非常に重要な影響を与えているかも知れない。
222: 2018/09/16(日)15:42 ID:haV9TZ8e(8/12) AAS
>>220
いや、まだまだ興味深い。
ここで終わらせずにもっと徹底して追及すべきだ。
223: 2018/09/16(日)15:48 ID:zL1WUjLu(6/27) AAS
>>211
それはどうやらclrでは使えないらしい。
> These functions are ignored when you use /clr (Common Language Runtime Compilation) or /clr:pure to compile
> because the common language runtime (CLR) only supports the default floating-point precision.
> 外部リンク[aspx]:msdn.microsoft.com
とはいえ無理矢理やってみた。警告は出るがコンパイルは通る。
結果は、どこに置いても、Debug/Releaseでも、常に 0x9001f が読み出される。
ただし、これは上記の仕様からして、当てにならない。
224(1): 2018/09/16(日)15:49 ID:zL1WUjLu(7/27) AAS
>>218
218のコードで試してみた結果、209で言った不安定さはなくなり、
全てにおいて 0x027f が安定して読み出せるようになった。
ただしその過程で気づいたが、
IDEから起動した場合はReleaseビルドであっても、「未初期化のスタック値」も0x00が読み出せるようだ。
どうやらこれが原因の可能性が出てきた。(はっきり言って俺のバグだが)
コードは以下の通りだが、
unsigned short fpu_cw, fpu_cw_after;
// fpu_getcw(&fpu_cw);
double norm = calc_norm_and_regulate(count, inputs, false);
省12
225(2): 2018/09/16(日)15:51 ID:zL1WUjLu(8/27) AAS
>>218
なお、逆アセンブルでコードバイトを表示させて確かめることは出来る。
正しいコードは出ている。(ただし不安定)
inline void fpu_getcw(unsigned short* cw) {
00DA1540 55 push ebp
00DA1541 8B EC mov ebp,esp
__asm{
fnstcw [cw];
00DA1543 D9 7D 08 fnstcw word ptr [cw]
}
省20
226: 2018/09/16(日)15:51 ID:zL1WUjLu(9/27) AAS
>>218
218のコードだと、
00381002 EC in al,dx
__asm{
mov edx,pCW
00381003 8B 55 08 mov edx,dword ptr [pCW]
fnstcw [edx];
00381006 D9 3A fnstcw word ptr [edx]
}
}
省4
227(1): 2018/09/16(日)16:02 ID:haV9TZ8e(9/12) AAS
>>225
をを。やはり、ある意味ではVCが間違ったアセンブリコードを出していたよ。
それだと、
fnstcw [EBP+08]
という意味になってしまって、
fnstcw pCW
の意味になっている。つまり:
pCW = control_word;
あなたが、やりたいのは、
*pCW = control_word;
省9
228(2): 2018/09/16(日)16:06 ID:zL1WUjLu(10/27) AAS
すまん、間違いの修正
>>224
× > どうやらこれが原因の可能性が出てきた。(はっきり言って俺のバグだが)
× > まあこれに当たっているのなら確実に俺のバグだし、これなら辻褄は合ってしまうのだが。
今回は俺はあくまで俺の本番コードのデバッグを念頭に置いていて、この発言だった。
ただし>>191の再現コードで『不定スタック領域』を掴んでいるわけもなく、
一応IDE起動とコマンドプロンプト起動での挙動の違いを再現出来ているわけだから、
これだけが問題ではないのも事実だ。
俺にとっては一つ新しい知見として、
・IDEから起動した場合、スタックが初期化されるっぽい
省6
229(1): 2018/09/16(日)16:11 ID:haV9TZ8e(10/12) AAS
>>225
>正直、/7の意味が分からないのだが、
ModRM とは、
mod reg r/m
76 543 210
のようなオペランドを指しているのだけど、/7 は、regの部分を2進数の111、
10進数の「7」にするという意味。このタイプのマシン語は、
mod ttt r/m
とも書かれる。tttの部分は、命令の主幹部分(ニモニック部分)によって変わる。
普通は、レジスタ番号を入れるところに、命令の種類を表す3BITの値を入れる
省12
230(1): 2018/09/16(日)16:17 ID:haV9TZ8e(11/12) AAS
>>228
>ただし>>191の再現コードで『不定スタック領域』を掴んでいるわけもなく、
>一応IDE起動とコマンドプロンプト起動での挙動の違いを再現出来ているわけだから、
>これだけが問題ではないのも事実だ。
そうだよ。精度が変わるのはあなたの間違いではない。スタック領域が0クリア
されようがれまいが、あなたのコード自体には特に不安定さはない。
非初期化領域を参照しているコードは見当たらないし。
231(3): 2018/09/16(日)16:20 ID:haV9TZ8e(12/12) AAS
逆アセンブラ結果を見てないで言うけど、もし、sqrt() が call文で関数呼び出し
されているんだったら、そこで精度の違いが出てるかもしれない。
232(1): 2018/09/16(日)16:23 ID:zL1WUjLu(11/27) AAS
>>227
なるほど、了解した。
つまり、>>209は全面的に間違いで、正しくは、
・fpu control register は 0x027F で、IDEからも正しく読めている
だな。
俺がやるべきだったのは fnstcw [[cw]] なのだと思うが、これはSyntaxErrorだ。
そして、こんな命令はないから、
[]内に変数を書かず、レジスタ名にしろ、ということだったのだな。
全くもって了解だ。
VCの問題ではなくて、
省4
上下前次1-新書関写板覧索設栞歴
あと 82 レスあります
スレ情報 赤レス抽出 画像レス抽出 歴の未読スレ AAサムネイル
ぬこの手 ぬこTOP 0.029s