[過去ログ]
Visual Studio 2008 Part 22 (314レス)
Visual Studio 2008 Part 22 http://mevius.5ch.net/test/read.cgi/tech/1413180800/
上
下
前
次
1-
新
通常表示
512バイト分割
レス栞
このスレッドは過去ログ倉庫に格納されています。
次スレ検索
歴削→次スレ
栞削→次スレ
過去ログメニュー
226: デフォルトの名無しさん [sage] 2018/09/16(日) 15:51:25.16 ID:zL1WUjLu >>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] } } 00381008 5D pop ebp 00381009 C3 ret D9 3A ならまんま fnstcw [edx] だ。 理由は分からんがこちらだと安定しているので、結果としてはこのやり方が正しい。 http://mevius.5ch.net/test/read.cgi/tech/1413180800/226
227: デフォルトの名無しさん [sage] 2018/09/16(日) 16:02:47.64 ID:haV9TZ8e >>225 をを。やはり、ある意味ではVCが間違ったアセンブリコードを出していたよ。 それだと、 fnstcw [EBP+08] という意味になってしまって、 fnstcw pCW の意味になっている。つまり: pCW = control_word; あなたが、やりたいのは、 *pCW = control_word; だったのだから、アセンブリ・コードが間違ってる。 あなたが指示したのは、 fnstcw [pCW] だった。実際に生成されたコードは、 fnstcw pCW だった。 VC のインラインアセンブラは、エラーも出さずに間違ったコードを 出すことが証明された。 これと、精度が不安定な問題とは全く別ではあるけれど。 http://mevius.5ch.net/test/read.cgi/tech/1413180800/227
228: デフォルトの名無しさん [sage] 2018/09/16(日) 16:06:05.39 ID:zL1WUjLu すまん、間違いの修正 >>224 × > どうやらこれが原因の可能性が出てきた。(はっきり言って俺のバグだが) × > まあこれに当たっているのなら確実に俺のバグだし、これなら辻褄は合ってしまうのだが。 今回は俺はあくまで俺の本番コードのデバッグを念頭に置いていて、この発言だった。 ただし>>191の再現コードで『不定スタック領域』を掴んでいるわけもなく、 一応IDE起動とコマンドプロンプト起動での挙動の違いを再現出来ているわけだから、 これだけが問題ではないのも事実だ。 俺にとっては一つ新しい知見として、 ・IDEから起動した場合、スタックが初期化されるっぽい ということが分かった。とはいえOSは0fillしてから各プロセスにメモリを与えるので、実際は、 ・コマンドプロンプト起動ならmain前に設定した続きでそのまま実行、 ・IDE起動ならmain前に色々やって0fillして実行、 或いはmain前に色々やることが多く、スタックが進み、(例えばデバッガをアタッチする為) 結果的にOSが初期化済みの領域から始動 となって違いが発生するというところか。 http://mevius.5ch.net/test/read.cgi/tech/1413180800/228
229: デフォルトの名無しさん [sage] 2018/09/16(日) 16:11:52.18 ID:haV9TZ8e >>225 >正直、/7の意味が分からないのだが、 ModRM とは、 mod reg r/m 76 543 210 のようなオペランドを指しているのだけど、/7 は、regの部分を2進数の111、 10進数の「7」にするという意味。このタイプのマシン語は、 mod ttt r/m とも書かれる。tttの部分は、命令の主幹部分(ニモニック部分)によって変わる。 普通は、レジスタ番号を入れるところに、命令の種類を表す3BITの値を入れる 仕様になっている。 あなたがインラインアセンブラでVCに出させたかったコードは、意味的には、 fnstcw [[EBP+08]] なのだが、[ ] を二重にしたようなそんなx86/x64命令は存在しないので VC がエラーも出さずに勝手に一重の fnstcw [EBP+08] にしてしまった、という事。本当は、 mov edx,[EBP+08] fnstcw [edx] というコードにしなくてはならなかったのに、VCがある意味では間違った。 これが、単独の *.asm ではなく、VC の asm {・・・} が危険な理由。 VC の asm は特に危険。 http://mevius.5ch.net/test/read.cgi/tech/1413180800/229
230: デフォルトの名無しさん [sage] 2018/09/16(日) 16:17:02.07 ID:haV9TZ8e >>228 >ただし>>191の再現コードで『不定スタック領域』を掴んでいるわけもなく、 >一応IDE起動とコマンドプロンプト起動での挙動の違いを再現出来ているわけだから、 >これだけが問題ではないのも事実だ。 そうだよ。精度が変わるのはあなたの間違いではない。スタック領域が0クリア されようがれまいが、あなたのコード自体には特に不安定さはない。 非初期化領域を参照しているコードは見当たらないし。 http://mevius.5ch.net/test/read.cgi/tech/1413180800/230
231: デフォルトの名無しさん [sage] 2018/09/16(日) 16:20:22.27 ID:haV9TZ8e 逆アセンブラ結果を見てないで言うけど、もし、sqrt() が call文で関数呼び出し されているんだったら、そこで精度の違いが出てるかもしれない。 http://mevius.5ch.net/test/read.cgi/tech/1413180800/231
232: デフォルトの名無しさん [sage] 2018/09/16(日) 16:23:20.75 ID:zL1WUjLu >>227 なるほど、了解した。 つまり、>>209は全面的に間違いで、正しくは、 ・fpu control register は 0x027F で、IDEからも正しく読めている だな。 俺がやるべきだったのは fnstcw [[cw]] なのだと思うが、これはSyntaxErrorだ。 そして、こんな命令はないから、 []内に変数を書かず、レジスタ名にしろ、ということだったのだな。 全くもって了解だ。 VCの問題ではなくて、 俺が fnstcw [cw] と書いたのが間違いで、それをそのままコードにされてしまっただけだな。 正しく書けばSyntaxErrorだったのだし。 なお fnstcw [*cw] もSyntaxErrorだ。手動で一旦レジスタに移さないと駄目だな。 全くもって>>218のコードが正しい。 http://mevius.5ch.net/test/read.cgi/tech/1413180800/232
233: デフォルトの名無しさん [sage] 2018/09/16(日) 16:35:08.59 ID:LrdaMWHl >>232 >俺がやるべきだったのは fnstcw [[cw]] なのだと思うが、これはSyntaxErrorだ。 ちょっと違う。あなたはやるべきことをちゃんと正しく、 fnstcw [cw] と書いた。しかし、cw=[ebp+8]なので、これは、 fnstcw [[ebp+8]] という「意味」になる。でも、x86/x64のマシン語にはこんな[ ]を二重にした オペランドは存在しないので、VCが無断で勝手に[ ]を一重にして、 fnstcw [ebp+8] に改変してしまった。 **(ebp+8) = control_word; としなくてはならないのに、VCが勝手に、 *(ebp+8) = control_word; としたということ。 http://mevius.5ch.net/test/read.cgi/tech/1413180800/233
234: デフォルトの名無しさん [sage] 2018/09/16(日) 16:36:04.13 ID:zL1WUjLu >>229-230 了解だ。ありがとう。 >>231 その部分の逆アセンブラは以下の通り。 普通にcallされている。(行数オーバーなので切るが) ただし、 > そこで精度の違いが出てるかもしれない との繋がりがよくからない。 sqrt()でcallされると、スタックが改変される。おそらくデータ依存か? なら未初期化のスタックを掴みに行っているコードが有ればバグる。 ただし今回の『再現コード』はこの限りではない。 (俺の本番コードはさておき) http://mevius.5ch.net/test/read.cgi/tech/1413180800/234
235: デフォルトの名無しさん [sage] 2018/09/16(日) 16:37:19.30 ID:zL1WUjLu >>231 逆アセンブラ for (int i=0;i<num;i++) norm += (double)r[i] * (double)r[i]; 00000033 33 D2 xor edx,edx 00000035 89 55 E8 mov dword ptr [ebp-18h],edx 00000038 90 nop 00000039 EB 03 jmp 0000003E 0000003b FF 45 E8 inc dword ptr [ebp-18h] 0000003e 8B 45 E8 mov eax,dword ptr [ebp-18h] 00000041 3B 45 FC cmp eax,dword ptr [ebp-4] 00000044 7D 1B jge 00000061 00000046 8B 45 F8 mov eax,dword ptr [ebp-8] 00000049 8B 55 E8 mov edx,dword ptr [ebp-18h] 0000004c DD 04 D0 fld qword ptr [eax+edx*8] 0000004f 8B 45 F8 mov eax,dword ptr [ebp-8] 00000052 8B 55 E8 mov edx,dword ptr [ebp-18h] 00000055 DC 0C D0 fmul qword ptr [eax+edx*8] 00000058 DC 45 F0 fadd qword ptr [ebp-10h] 0000005b DD 5D F0 fstp qword ptr [ebp-10h] 0000005e 90 nop 0000005f EB DA jmp 0000003B norm = sqrt(norm); 00000061 DD 45 F0 fld qword ptr [ebp-10h] 00000064 83 EC 08 sub esp,8 00000067 DD 1C 24 fstp qword ptr [esp] 0000006a E8 0D 50 7B FF call FF7B507C 0000006f DD 5D D8 fstp qword ptr [ebp-28h] 00000072 DD 45 D8 fld qword ptr [ebp-28h] 00000075 DD 5D F0 fstp qword ptr [ebp-10h] http://mevius.5ch.net/test/read.cgi/tech/1413180800/235
236: デフォルトの名無しさん [sage] 2018/09/16(日) 16:37:34.94 ID:zL1WUjLu >>231 逆アセンブラ(続き) if (regulate) for (int i=0;i<num;i++) r[i] = (T)(r[i]/norm); 00000078 0F B6 45 08 movzx eax,byte ptr [ebp+8] 0000007c 85 C0 test eax,eax 0000007e 74 25 je 000000A5 00000080 33 D2 xor edx,edx 00000082 89 55 EC mov dword ptr [ebp-14h],edx 00000085 90 nop 00000086 EB 03 jmp 0000008B 00000088 FF 45 EC inc dword ptr [ebp-14h] 0000008b 8B 45 EC mov eax,dword ptr [ebp-14h] 0000008e 3B 45 FC cmp eax,dword ptr [ebp-4] 00000091 7D 12 jge 000000A5 00000093 8B 45 F8 mov eax,dword ptr [ebp-8] 00000096 8B 55 EC mov edx,dword ptr [ebp-14h] 00000099 DD 45 F0 fld qword ptr [ebp-10h] 0000009c DC 3C D0 fdivr qword ptr [eax+edx*8] 0000009f DD 1C D0 fstp qword ptr [eax+edx*8] 000000a2 90 nop 000000a3 EB E3 jmp 00000088 return norm; 000000a5 DD 45 F0 fld qword ptr [ebp-10h] 000000a8 DD 5D E0 fstp qword ptr [ebp-20h] http://mevius.5ch.net/test/read.cgi/tech/1413180800/236
237: デフォルトの名無しさん [sage] 2018/09/16(日) 16:40:36.14 ID:LrdaMWHl >>234 よく見ると、最小(?)の実験コードでは sqrt() が使われていなかった。 スマン。 http://mevius.5ch.net/test/read.cgi/tech/1413180800/237
238: デフォルトの名無しさん [sage] 2018/09/16(日) 16:42:54.99 ID:zL1WUjLu >>233 ああ、なるほど、了解。 http://mevius.5ch.net/test/read.cgi/tech/1413180800/238
239: デフォルトの名無しさん [sage] 2018/09/16(日) 16:49:54.65 ID:zL1WUjLu >>237 いや、俺が提供した>>191のソースなら使われてるぞ。 >>200のソースでは使われてないが。 ただまあ、彼(200)がsqrtを落としたのも分からなくはない。 誤差が生じる=通常は桁落ちだから、この場合は当然積和部分が怪しい。 あらかじめ彼はそうなると分かっていてそれを落とし、予定調和的な結論にたどり着いてしまった。 それが彼の間違いだった、ということ。 俺は出来るだけ元のソースのままで追跡しようとしている。 元のソースの該当ケースと離れてしまっては意味がないから。 そして元ソースではsqrtを使っている。 http://mevius.5ch.net/test/read.cgi/tech/1413180800/239
240: デフォルトの名無しさん [sage] 2018/09/16(日) 16:53:58.12 ID:/oSJzlqn たぶん2008の最適化ミスだと思う。 static double norm = 0;// ←"static"を追加する にするとか、最適化オプションをいじると Release/コマンドプロンプトからの起動でも 0x1ff68ddfb62221ddになる http://mevius.5ch.net/test/read.cgi/tech/1413180800/240
241: デフォルトの名無しさん [sage] 2018/09/16(日) 16:54:10.71 ID:LrdaMWHl >>237 ああ。また訂正。 sqrt()が使われていないのは、>>200, >>201, >>202, >>203 の場合で、 それは、ループ内にfprintf()を入れた場合と入れない場合とで、 x87 fpuレジスタのst(0)〜st(7)を使う「期間」が変わるために 80BITから 64BITへの書き戻し丸めの問題のために精度が変わっているだけだった。 一方、あなたが指摘した >>191 では、ちゃんと sqrt() 関数が使われていて、 それだと、IDEからの起動とコマンド・プロンプトからの起動とで、精度が変 わってくると。そして、その場合の逆アセンブル結果は >>235 のように sqrt() 関数がその場で x87 fpu の fsqrt 命令を使わずに、call 文によって 実際に本当のサブ・ルーチンを呼び出していると。 これはとても興味深い。そのサブ・ルーチンの中が、時と場合によって 精度が変わってくるような書き方をされている可能性が見えてきた。 http://mevius.5ch.net/test/read.cgi/tech/1413180800/241
242: デフォルトの名無しさん [sage] 2018/09/16(日) 16:56:42.67 ID:LrdaMWHl >>239 >いや、俺が提供した>>191のソースなら使われてるぞ。 > >>200のソースでは使われてないが。 了解。 問題を切り分けるため、sqrt() を使わなかった場合の Release版での、 IDE起動とコマンドrライン起動の精度の違いを実験してみて欲しい。 http://mevius.5ch.net/test/read.cgi/tech/1413180800/242
243: デフォルトの名無しさん [sage] 2018/09/16(日) 17:02:35.56 ID:LrdaMWHl ちょっとしばらく、ここを離れる。 http://mevius.5ch.net/test/read.cgi/tech/1413180800/243
244: デフォルトの名無しさん [sage] 2018/09/16(日) 17:22:07.21 ID:zL1WUjLu >>240 現象確認した。こちらでも再現した。 逆アセンブルは、以下。(肝心のループ部分は次レス内) 正直、fld/fmul/fadd/fstpのループ部分は変わらず、 normのアドレスが [ebp-10h](つまりローカル)から ds:[00A4AD40h](つまりグローバル)に変わっただけであり、 これで結果が変わるのはかなり奇妙な気もするが、何か見落としがあるのかも。 >>240逆アセンブル(static付加版) template<typename T> static double calc_norm_and_regulate(int num, T* r, bool regulate){ // <float> for debug. static double norm = 0; for (int i=0;i<num;i++) norm += (double)r[i] * (double)r[i]; 00000000 55 push ebp 00000001 8B EC mov ebp,esp 00000003 83 EC 20 sub esp,20h 00000006 89 4D FC mov dword ptr [ebp-4],ecx 00000009 89 55 F8 mov dword ptr [ebp-8],edx 0000000c 83 3D 14 2E 38 00 00 cmp dword ptr ds:[00382E14h],0 00000013 74 05 je 0000001A 00000015 E8 FF 52 30 68 call 68305319 0000001a 33 D2 xor edx,edx 0000001c 89 55 F0 mov dword ptr [ebp-10h],edx 0000001f 33 D2 xor edx,edx 00000021 89 55 F4 mov dword ptr [ebp-0Ch],edx 00000024 D9 EE fldz 00000026 DD 5D E8 fstp qword ptr [ebp-18h] 00000029 33 D2 xor edx,edx 0000002b 89 55 F0 mov dword ptr [ebp-10h],edx 0000002e 90 nop 0000002f EB 03 jmp 00000034 http://mevius.5ch.net/test/read.cgi/tech/1413180800/244
245: デフォルトの名無しさん [sage] 2018/09/16(日) 17:22:29.32 ID:zL1WUjLu >>240逆アセンブル(続き)(static付加版) 00000031 FF 45 F0 inc dword ptr [ebp-10h] 00000034 8B 45 F0 mov eax,dword ptr [ebp-10h] 00000037 3B 45 FC cmp eax,dword ptr [ebp-4] 0000003a 7D 21 jge 0000005D 0000003c 8B 45 F8 mov eax,dword ptr [ebp-8] 0000003f 8B 55 F0 mov edx,dword ptr [ebp-10h] 00000042 DD 04 D0 fld qword ptr [eax+edx*8] 00000045 8B 45 F8 mov eax,dword ptr [ebp-8] 00000048 8B 55 F0 mov edx,dword ptr [ebp-10h] 0000004b DC 0C D0 fmul qword ptr [eax+edx*8] 0000004e DC 05 40 AD A4 00 fadd qword ptr ds:[00A4AD40h] 00000054 DD 1D 40 AD A4 00 fstp qword ptr ds:[00A4AD40h] 0000005a 90 nop 0000005b EB D4 jmp 00000031 norm = sqrt(norm); 0000005d DD 05 40 AD A4 00 fld qword ptr ds:[00A4AD40h] 00000063 83 EC 08 sub esp,8 00000066 DD 1C 24 fstp qword ptr [esp] 00000069 E8 0E 50 88 FF call FF88507C 0000006e DD 5D E0 fstp qword ptr [ebp-20h] 00000071 DD 45 E0 fld qword ptr [ebp-20h] 00000074 DD 1D 40 AD A4 00 fstp qword ptr ds:[00A4AD40h] http://mevius.5ch.net/test/read.cgi/tech/1413180800/245
246: デフォルトの名無しさん [sage] 2018/09/16(日) 17:22:46.06 ID:zL1WUjLu >>240逆アセンブル(続き)(static付加版) if (regulate) for (int i=0;i<num;i++) r[i] = (T)(r[i]/norm); 0000007a 0F B6 45 08 movzx eax,byte ptr [ebp+8] 0000007e 85 C0 test eax,eax 00000080 74 28 je 000000AA 00000082 33 D2 xor edx,edx 00000084 89 55 F4 mov dword ptr [ebp-0Ch],edx 00000087 90 nop 00000088 EB 03 jmp 0000008D 0000008a FF 45 F4 inc dword ptr [ebp-0Ch] 0000008d 8B 45 F4 mov eax,dword ptr [ebp-0Ch] 00000090 3B 45 FC cmp eax,dword ptr [ebp-4] 00000093 7D 15 jge 000000AA 00000095 8B 45 F8 mov eax,dword ptr [ebp-8] 00000098 8B 55 F4 mov edx,dword ptr [ebp-0Ch] 0000009b DD 05 40 AD A4 00 fld qword ptr ds:[00A4AD40h] 000000a1 DC 3C D0 fdivr qword ptr [eax+edx*8] 000000a4 DD 1C D0 fstp qword ptr [eax+edx*8] 000000a7 90 nop 000000a8 EB E0 jmp 0000008A return norm; 000000aa DD 05 40 AD A4 00 fld qword ptr ds:[00A4AD40h] 000000b0 DD 5D E8 fstp qword ptr [ebp-18h] } 000000b3 DD 45 E8 fld qword ptr [ebp-18h] 000000b6 8B E5 mov esp,ebp 000000b8 5D pop ebp 000000b9 C2 04 00 ret 4 http://mevius.5ch.net/test/read.cgi/tech/1413180800/246
247: デフォルトの名無しさん [sage] 2018/09/16(日) 17:35:35.70 ID:zL1WUjLu >>242 まだ異なった出力が得られた。 この意味では200がsqrtを外した判断は正しかった。 (彼はそこからさらにループ回数を固定してしまったのが間違いだった) 191ソースを以下に変更した。(sqrtをコメントアウト) ついでに Console::Write(String::Format("{0:E6}, {0:E30}\r\n",norm)); の出力も付けておく。 ソース: template<typename T> static double calc_norm_and_regulate(int num, T* r, bool regulate){ // <float> for debug. double norm = 0; for (int i=0;i<num;i++) norm += (double)r[i] * (double)r[i]; // norm = sqrt(norm); if (regulate) for (int i=0;i<num;i++) r[i] = (T)(r[i]/norm); return norm; } 結果:(Releaseビルド/コマンドプロンプトからの起動) 0.000000, 0x0007f2c44dfff8f2 1.105348E-308, 1.105348254058510600000000000000E-308 結果:(Releaseビルド/IDEからの起動、Debugビルドは起動方法によらずこちら) 0.000000, 0x0007f2c44dfff8f1 1.105348E-308, 1.105348254058510100000000000000E-308 >>243 了解。いずれにしても助かってる。 こちらも後30分くらいでちょっと離れる予定。 http://mevius.5ch.net/test/read.cgi/tech/1413180800/247
248: デフォルトの名無しさん [] 2018/09/16(日) 18:30:34.19 ID:HF0YmRsW >>212 ほんそれ http://mevius.5ch.net/test/read.cgi/tech/1413180800/248
249: デフォルトの名無しさん [sage] 2018/09/16(日) 20:54:27.39 ID:zL1WUjLu >>240 さて再見したが、やはりstaticだけで直る理由は分からない。 なお、最適化ミスの場合は、逆アセンブラを読めば分かる。 今のところそれではない。 一応、>>191ソースのtemplate部の逆アセンブルを上げておく。(ただし重複するので頭のみ) 頭はこれ。続きが>>235,236。 template<typename T> static double calc_norm_and_regulate(int num, T* r, bool regulate){ // <float> for debug. double norm = 0; 00000000 55 push ebp 00000001 8B EC mov ebp,esp 00000003 83 EC 28 sub esp,28h 00000006 89 4D FC mov dword ptr [ebp-4],ecx 00000009 89 55 F8 mov dword ptr [ebp-8],edx 0000000c 83 3D 14 2E 76 00 00 cmp dword ptr ds:[00762E14h],0 00000013 74 05 je 0000001A 00000015 E8 FF 52 1B 68 call 681B5319 0000001a 33 D2 xor edx,edx 0000001c 89 55 E8 mov dword ptr [ebp-18h],edx 0000001f 33 D2 xor edx,edx 00000021 89 55 EC mov dword ptr [ebp-14h],edx 00000024 D9 EE fldz 00000026 DD 5D F0 fstp qword ptr [ebp-10h] 00000029 D9 EE fldz 0000002b DD 5D E0 fstp qword ptr [ebp-20h] 0000002e D9 EE fldz 00000030 DD 5D F0 fstp qword ptr [ebp-10h] http://mevius.5ch.net/test/read.cgi/tech/1413180800/249
250: デフォルトの名無しさん [sage] 2018/09/16(日) 21:25:23.90 ID:zL1WUjLu >>219 >>221 /MTと/clrは同時に指定出来ないらしい。(error D8016) /MTdも同じく無理。 もう一つ /MDd ってのがあるから試してみた。 /MDdの結果: Releaseビルドでコマンドプロンプト起動の時のみ ****de、 ReleaseビルドでIDEからの起動だと ***dd。(Debugビルドは起動方法を問わずこっち) (/MDと全く挙動は同じ) これで有効な指摘については全て回答してるかな? 見落としが有れば指摘よろしく。 (規制に引っかかったので遅くなってすまん) 今のところ、可能性があるのは以下か? ・Releaseビルドをコマンドプロンプトから起動したときのみなぜか精度が高い (>>200から結果的に検出された。今のところ精度が高いときと同じ挙動をしている為) ・ReleaseビルドもIDEから起動すれば結果的にスタックが0初期化されている状態になっており、 俺の本番プログラムに関してはここに当たるバグがある?(>>228) (ただしこれは>>191には該当しない) http://mevius.5ch.net/test/read.cgi/tech/1413180800/250
251: 240 [sage] 2018/09/16(日) 21:43:04.47 ID:/oSJzlqn .netの場合、デバッガ配下では(デバッグのため)違うコードを実行しているような気がする。 デバッガの逆アセンブル表示とかasm出力はあまり当てにならないような気もする。 ループ部分だけど、レジスタのみで処理するか、メモリを使用するかで精度が変わるのかも。 そもそも、どっちが正しいのかよくわからんけど... ループ部分の関数を#pragma unmanagedすると結果が変わるでそれが正しいのかも。 http://mevius.5ch.net/test/read.cgi/tech/1413180800/251
252: 240 [sage] 2018/09/16(日) 21:43:27.78 ID:/oSJzlqn static版 0000000e 33 C0 xor eax,eax 00000010 85 F6 test esi,esi 00000012 7E 16 jle 0000002A 00000014 DD 04 C7 fld qword ptr [edi+eax*8] 00000017 DC C8 fmul st(0),st 00000019 DC 05 00 30 CC 00 fadd qword ptr ds:[00CC3000h] 0000001f DD 1D 00 30 CC 00 fstp qword ptr ds:[00CC3000h] 00000025 40 inc eax 00000026 3B C6 cmp eax,esi 00000028 7C EA jl 00000014 0000002a DD 05 00 30 CC 00 fld qword ptr ds:[00CC3000h] 非static版 0000000e D9 EE fldz 00000010 33 C0 xor eax,eax 00000012 85 F6 test esi,esi 00000014 7E 0C jle 00000022 00000016 DD 04 C7 fld qword ptr [edi+eax*8] 00000019 DC C8 fmul st(0),st 0000001b DE C1 faddp st(1),st 0000001d 40 inc eax 0000001e 3B C6 cmp eax,esi 00000020 7C F4 jl 00000016 http://mevius.5ch.net/test/read.cgi/tech/1413180800/252
253: デフォルトの名無しさん [sage] 2018/09/16(日) 22:27:34.58 ID:zL1WUjLu >>251 とりあえず落ち着け。一つずつ行こう。 > ループ部分の関数を#pragma unmanagedすると結果が変わるでそれが正しいのかも。 こちらでも確認した。 calc_norm_and_regulateをunmanaged関数にすると、違いはなくなる。 (Releaseビルドの`をコマンドプロンプトで起動した際にも、****ddの結果となる) ただしこちらの逆アセンブル結果は以下だ。(fld/fmul/fadd/fstpであることに注意) for (int i=0;i<num;i++) norm += (double)r[i] * (double)r[i]; 0007272C C7 45 F4 00 00 00 00 mov dword ptr [i],0 00072733 EB 09 jmp `anonymous namespace'::calc_norm_and_regulate<double>+1Eh (7273Eh) 00072735 8B 45 F4 mov eax,dword ptr [i] 00072738 83 C0 01 add eax,1 0007273B 89 45 F4 mov dword ptr [i],eax 0007273E 8B 4D F4 mov ecx,dword ptr [i] 00072741 3B 4D 08 cmp ecx,dword ptr [num] 00072744 7D 1A jge `anonymous namespace'::calc_norm_and_regulate<double>+40h (72760h) 00072746 8B 55 F4 mov edx,dword ptr [i] 00072749 8B 45 0C mov eax,dword ptr [r] 0007274C 8B 4D F4 mov ecx,dword ptr [i] 0007274F 8B 75 0C mov esi,dword ptr [r] 00072752 DD 04 D0 fld qword ptr [eax+edx*8] 00072755 DC 0C CE fmul qword ptr [esi+ecx*8] 00072758 DC 45 F8 fadd qword ptr [norm] 0007275B DD 5D F8 fstp qword ptr [norm] 0007275E EB D5 jmp `anonymous namespace'::calc_norm_and_regulate<double>+15h (72735h) http://mevius.5ch.net/test/read.cgi/tech/1413180800/253
254: デフォルトの名無しさん [sage] 2018/09/16(日) 22:33:32.07 ID:zL1WUjLu >>252 そちらの逆アセンブルは以下の違いが出てるだろ。 static版: fld/fmul/fadd/fstp 非static版: fld/fmul/faddp (fstpが無い) この非static版の場合、拡張倍精度(80bit)で演算されるから精度が高いことになり、 static版との演算結果に違いが出るのも仕様通りなんだよ。(これは>>200と同じ間違い) 一応、fstpにも80bit版はあって、Intelのマニュアルによると以下。 > オペコード命令説明 > D9 /2 FST m32fp ST(0) をm32fp にコピーする。 > DD /2 FST m64fp ST(0) をm64fp にコピーする。 > DD D0+i FST ST(i) ST(0) をST(i) にコピーする。 > D9 /3 FSTP m32fp ST(0) をm32fp にコピーし、レジスタスタックをポップする。 > DD /3 FSTP m64fp ST(0) をm64fp にコピーし、レジスタスタックをポップする。 > DB /7 FSTP m80fp ST(0) をm80fp にコピーし、レジスタスタックをポップする。 > DD D8+i FSTP ST(i) ST(0) をST(i) にコピーし、レジスタスタックをポップする。 つまり君のstatic版 > 0000001f DD 1D 00 30 CC 00 fstp qword ptr ds:[00CC3000h] では FSTP /3 m64fp [disp32] であり、そこで64bit(倍精度)に丸められてる。 だからレジスタ(80bit=拡張倍精度)で演算される非static版と結果が異なる。 static版のsftpが DB /7 m80fp なら誤差は出ないはずなんだよ。(Cでどう書くのかは知らん) だから>>252の場合の誤差なら、仕様通りなんだよ。(片方が倍精度、もう片方は拡張倍精度) ただし、>>191は逆アセンブル(>>235)を見る限りそれに該当しないし、(両方とも倍精度) 今回の俺の上記逆アセンブル(>>253、中身は君の指摘通りunmanagedにしただけ)も該当しない。(両方とも倍精度) そして253は何故か直ってしまった。 http://mevius.5ch.net/test/read.cgi/tech/1413180800/254
255: デフォルトの名無しさん [sage] 2018/09/16(日) 22:34:16.44 ID:zL1WUjLu >>252 > .netの場合、デバッガ配下では(デバッグのため)違うコードを実行しているような気がする。 > デバッガの逆アセンブル表示とかasm出力はあまり当てにならないような気もする。 これは俺も相当疑っているのだが、今のところ尻尾を掴めない。 ILspyだっけ?外部の逆アセンブルツール使えばチェック出来るのかな? いずれにしても、>>251の指摘 ・unmanagedにすれば直る のも事実だし、逆アセンブルを見る限り、これを説明出来る理由もないのも事実。 http://mevius.5ch.net/test/read.cgi/tech/1413180800/255
メモ帳
(0/65535文字)
上
下
前
次
1-
新
書
関
写
板
覧
索
設
栞
歴
あと 59 レスあります
スレ情報
赤レス抽出
画像レス抽出
歴の未読スレ
AAサムネイル
Google検索
Wikipedia
ぬこの手
ぬこTOP
0.016s