■公式
ttp://www.microsoft.com/japan/msdn/vstudio/default.aspx
■前スレ
Visual Studio 2008 Part 21
http://peace.2ch.net/test/read.cgi/tech/1290969016/
■リンク
Visual Studio 2008に搭載された17の新機能
ttp://www.atmarkit.co.jp/fdotnet/special/visualstudio2008_01/visualstudio2008_01_01.html
5000個のバグと戦った、MSが「Visual Studio 2008」RTM出荷
ttp://www.atmarkit.co.jp/news/200711/20/vs.html
■関連
Visual Studio 2013 part4
http://peace.2ch.net/test/read.cgi/tech/1404333757/
Visual Studio 2012 Part8
http://peace.2ch.net/test/read.cgi/tech/1392639689/
Visual Studio 2010 Part21
http://peace.2ch.net/test/read.cgi/tech/1412136476/
Visual Studio 2005 Part 27
http://peace.2ch.net/test/read.cgi/tech/1291513609/
その他テンプレ>>2-5
探検
Visual Studio 2008 Part 22
■ このスレッドは過去ログ倉庫に格納されています
2014/10/13(月) 15:13:20.18ID:yFRqmPNp
128デフォルトの名無しさん
2017/05/18(木) 08:51:36.17ID:thYMhZbz129デフォルトの名無しさん
2017/05/18(木) 08:52:36.67ID:thYMhZbz >>60
eメールのアカウントが必要
eメールのアカウントが必要
130デフォルトの名無しさん
2017/05/18(木) 09:02:35.23ID:thYMhZbz dll
131デフォルトの名無しさん
2017/05/18(木) 09:03:37.43ID:thYMhZbz132デフォルトの名無しさん
2017/05/18(木) 09:04:21.32ID:thYMhZbz 今の時代、パソコンでテレビが見れないとだめなのか。
133デフォルトの名無しさん
2017/05/18(木) 09:12:17.83ID:thYMhZbz .iso
134デフォルトの名無しさん
2017/06/03(土) 19:22:27.66ID:cZuYHM9v 古い奴だとお思いでしょうが、古い奴こそ新しいものを欲しがるもんでございます。
どこに新しいものがございましょう…
「傷だらけの人生」
藤田まさと作詞・吉田正作曲
どこに新しいものがございましょう…
「傷だらけの人生」
藤田まさと作詞・吉田正作曲
135デフォルトの名無しさん
2017/06/15(木) 00:13:00.81ID:0Bo/JfNC KB957507って現在は入手不可能?
136デフォルトの名無しさん
2017/07/06(木) 07:11:13.84ID:6wMkdZx/ 温故知新(おんこちしん)
137デフォルトの名無しさん
2017/10/03(火) 08:49:19.60ID:dPWSl44k >>135
https://support.microsoft.com/ja-jp/hotfix/kbhotfix?kbnum=957507&kbln=ja-jp
出典は
http://lsair.html.xdomain.jp/a/e/list-of-vs2008-hotfix.html
いつものHotFixの画面だったから大丈夫かと・・・
試してはいないけどw
https://support.microsoft.com/ja-jp/hotfix/kbhotfix?kbnum=957507&kbln=ja-jp
出典は
http://lsair.html.xdomain.jp/a/e/list-of-vs2008-hotfix.html
いつものHotFixの画面だったから大丈夫かと・・・
試してはいないけどw
138デフォルトの名無しさん
2018/01/20(土) 12:54:23.17ID:bSTKludV VC++2008にユーザプリプロセッサを噛ませる方法ってある?
関連質問は以下。
http://mevius.2ch.net/test/read.cgi/tech/1514025223/395
VC++2017相当のラムダをVC++2008で使いたい。
MSVCのプリプロセッサだけでは多分無理っぽい。
自前のプリプロセッサをまず通し、結果をVSでコンパイルすれば確実にいけるのだが、
これをやる方法ってある?
(自前のプリプロセッサはスクリプト言語で書く)
関連質問は以下。
http://mevius.2ch.net/test/read.cgi/tech/1514025223/395
VC++2017相当のラムダをVC++2008で使いたい。
MSVCのプリプロセッサだけでは多分無理っぽい。
自前のプリプロセッサをまず通し、結果をVSでコンパイルすれば確実にいけるのだが、
これをやる方法ってある?
(自前のプリプロセッサはスクリプト言語で書く)
139デフォルトの名無しさん
2018/01/20(土) 13:28:02.32ID:5zEZap2N .cppじゃなくて.cupみたいなソース書いて
.cup->.cppにするならいける
.cup->.cppにするならいける
140デフォルトの名無しさん
2018/01/20(土) 13:37:19.70ID:bSTKludV >>139
多分カスタムビルドツールだよね?今それを見ていたところ。
https://msdn.microsoft.com/ja-jp/library/hefydhhy.aspx
とりあえずこれから試してみる。ありがとう。
多分カスタムビルドツールだよね?今それを見ていたところ。
https://msdn.microsoft.com/ja-jp/library/hefydhhy.aspx
とりあえずこれから試してみる。ありがとう。
141デフォルトの名無しさん
2018/01/20(土) 13:44:14.42ID:5zEZap2N 最近の人はmake書いたこと無いんか
142デフォルトの名無しさん
2018/01/20(土) 14:14:17.24ID:bSTKludV >>141
手動makeか。まあその手もあるか。
手動makeか。まあその手もあるか。
143デフォルトの名無しさん
2018/01/20(土) 14:25:54.52ID:Hc/lJP5p Makefile家や
144デフォルトの名無しさん
2018/01/20(土) 14:27:12.33ID:4AOaXNlF make書いたら負け
145デフォルトの名無しさん
2018/01/20(土) 14:40:08.73ID:bSTKludV まあどっちでもいいと思うが。
Cマクロで出来れば一番簡単だが、どうやらこれは無理。
ならば次善策は自前でのスクリプティングであり、
主な手間はmakefile/カスタムビルドツール設定ではなく、
スクリプトを作成することなんだから、この際起動はどっちでもいいだろ。
Cマクロで出来れば一番簡単だが、どうやらこれは無理。
ならば次善策は自前でのスクリプティングであり、
主な手間はmakefile/カスタムビルドツール設定ではなく、
スクリプトを作成することなんだから、この際起動はどっちでもいいだろ。
146デフォルトの名無しさん
2018/01/20(土) 15:02:15.30ID:4AOaXNlF Dで書いてobjリンクする
147デフォルトの名無しさん
2018/01/20(土) 15:57:47.74ID:bSTKludV ちなみに、以下確かに動くのだが、これってどうなん?
https://stackoverflow.com/questions/472667/lambda-expressions-support-in-vs2008-sp1
(超絶簡単なソースしか試してないが)
・コンパイルは c:\windows\microsoft.net\framework\v2.0.50727\system.dll : warning C4945: が出つつも通る。
・F5でのデバッグ実行が出来ない。「デバッガのプロトコルがデバッグされる対象と互換性がありません」
・IntellisenseはVC++/CLIでも機能している。
>>146
なおラムダはGUIからの機能選択部で使うので、
結構な頻度で追加/書き換えしており、ソースは分離したくない。
普通に考えればVC++2017に上げればいいだけではあるが、
環境を変更すると色々他の問題が発生するかもしれないのでちょっと無理しようとしている。
https://stackoverflow.com/questions/472667/lambda-expressions-support-in-vs2008-sp1
(超絶簡単なソースしか試してないが)
・コンパイルは c:\windows\microsoft.net\framework\v2.0.50727\system.dll : warning C4945: が出つつも通る。
・F5でのデバッグ実行が出来ない。「デバッガのプロトコルがデバッグされる対象と互換性がありません」
・IntellisenseはVC++/CLIでも機能している。
>>146
なおラムダはGUIからの機能選択部で使うので、
結構な頻度で追加/書き換えしており、ソースは分離したくない。
普通に考えればVC++2017に上げればいいだけではあるが、
環境を変更すると色々他の問題が発生するかもしれないのでちょっと無理しようとしている。
148デフォルトの名無しさん
2018/01/20(土) 16:02:31.52ID:5zEZap2N 本質と関係ない話題の方が盛り上がるのが2ch
149デフォルトの名無しさん
2018/01/20(土) 16:09:16.48ID:5zEZap2N150デフォルトの名無しさん
2018/01/20(土) 23:47:48.29ID:bSTKludV まだカスタムビルドには組み込んでいないが、スクリプトを作成し、動作することを確認した。
知恵を絞ってくれた人はありがとう。現在の解決策は以下。
・#define LAMBDA でインラインの展開を行う。
・クラス宣言部はスクリプトで作成し、これをincludeする。
VS2017に上げてもLAMBDAマクロ宣言部だけの変更(1行)で済む予定なので、まあまあかと。
とりあえずこれで様子見します。
知恵を絞ってくれた人はありがとう。現在の解決策は以下。
・#define LAMBDA でインラインの展開を行う。
・クラス宣言部はスクリプトで作成し、これをincludeする。
VS2017に上げてもLAMBDAマクロ宣言部だけの変更(1行)で済む予定なので、まあまあかと。
とりあえずこれで様子見します。
151デフォルトの名無しさん
2018/04/10(火) 07:51:46.77ID:25Me0atb 最終列車に乗り遅れるな
VC++2008Expressサポート切れまであと1日。
2018年4月11日(水)でサポート終了。
修正パッチの入手の終わってない人は忘れないように。
VC++2008Expressサポート切れまであと1日。
2018年4月11日(水)でサポート終了。
修正パッチの入手の終わってない人は忘れないように。
152デフォルトの名無しさん
2018/04/10(火) 14:36:15.41ID:JIHFaEMv GJ
153デフォルトの名無しさん
2018/04/11(水) 01:33:09.61ID:PizNPnSY 必死だなぁw
154デフォルトの名無しさん
2018/04/11(水) 13:05:30.31ID:Gexxa1fK https://forest.watch.impress.co.jp/docs/news/1116235.html
「Microsoft Visual Studio 2008」のサポートが終了 〜無償版「Express Edition」も
「Microsoft SQL Server Compact 3.5」なども対象
「Microsoft Visual Studio 2008」のサポートが終了 〜無償版「Express Edition」も
「Microsoft SQL Server Compact 3.5」なども対象
155デフォルトの名無しさん
2018/04/11(水) 13:06:06.48ID:bG1z7LTF ああ終わったか
乙でした
乙でした
156デフォルトの名無しさん
2018/04/11(水) 13:26:11.45ID:bG1z7LTF てst
157デフォルトの名無しさん
2018/04/12(木) 14:51:25.15ID:nqXIWDjI 《 後継開発環境のご案内 》
LinuxMintのダウンロードはこちらから。
Main Page - Linux Mint
https://linuxmint.com/
https://linuxmint.com/download.php
---------
AGK無料試用版の配布開始(リンク先にWindows、Mac、Linux版のファイルが直接置いてある)
AppGameKit - Free Trial Version
https://www.appgamekit.com/trial
無料試用版
AppGameKit無料トライアル版は、AppGameKitの主要な領域すべてにアクセスできるため、
完全に評価することができます。完全版の有料版には、次の主要機能が含まれています。
・ Android、iOS、HTML5にプロジェクトをエクスポートする
・ アプリをデバイスに直接ブロードキャストする
・ コンパイルされたプロジェクトからウォーターマークを削除する
LinuxMintのダウンロードはこちらから。
Main Page - Linux Mint
https://linuxmint.com/
https://linuxmint.com/download.php
---------
AGK無料試用版の配布開始(リンク先にWindows、Mac、Linux版のファイルが直接置いてある)
AppGameKit - Free Trial Version
https://www.appgamekit.com/trial
無料試用版
AppGameKit無料トライアル版は、AppGameKitの主要な領域すべてにアクセスできるため、
完全に評価することができます。完全版の有料版には、次の主要機能が含まれています。
・ Android、iOS、HTML5にプロジェクトをエクスポートする
・ アプリをデバイスに直接ブロードキャストする
・ コンパイルされたプロジェクトからウォーターマークを削除する
158デフォルトの名無しさん
2018/04/16(月) 00:56:57.36ID:CadfvnK3 WineでPassmarkとHDbenchを試したところ、シングルスレッド性能はWindowsより若干高く、マルチコア性能は半分程度に留まった。
おそらくWine内部処理の都合と言うことにw
また、DirectXテストは通らなかった。GDIクラスのみ。
おそらくWine内部処理の都合と言うことにw
また、DirectXテストは通らなかった。GDIクラスのみ。
159デフォルトの名無しさん
2018/04/22(日) 03:49:49.80ID:CAx4oxnE …って言う訳で、早速Linuxのパフォーマンステスト。
64x64ピクセルの2Dスプライトの表示枚数をカウントして、パフォーマンスを計測してみよう。
ダウンロードは以下のリンクからどうぞ。
http://upload.saloon.jp/src/up27011.zip
Firefoxブラウザの右上にダウンロードマーク(↓)の付いたアイコンをクリックして、ファイル
アイコンをクリックすると、zipファイルの入ったフォルダが表示されるので、右クリックして
「 Extract Here 」 を選ぶ。
次に、「 agk_sample 」 と言うフォルダが作成されるので、ダブルクリックする。
フォルダの中に 「 abc 」 と言う拡張子のないファイル、「 media 」 と言うランタイムの入った
フォルダが作成されている。
「 abc 」 と言う拡張子のないファイルが、実行ファイルで、これを迷わずダブルクリックすれ
ばよいw
だいたい2分ぐらいで最大表示枚数が安定する。
プログラムの終了は [ ESC ] キー。
Celeron G1820 + Intel HD無印 で1500枚程度。
64x64ピクセルの2Dスプライトの表示枚数をカウントして、パフォーマンスを計測してみよう。
ダウンロードは以下のリンクからどうぞ。
http://upload.saloon.jp/src/up27011.zip
Firefoxブラウザの右上にダウンロードマーク(↓)の付いたアイコンをクリックして、ファイル
アイコンをクリックすると、zipファイルの入ったフォルダが表示されるので、右クリックして
「 Extract Here 」 を選ぶ。
次に、「 agk_sample 」 と言うフォルダが作成されるので、ダブルクリックする。
フォルダの中に 「 abc 」 と言う拡張子のないファイル、「 media 」 と言うランタイムの入った
フォルダが作成されている。
「 abc 」 と言う拡張子のないファイルが、実行ファイルで、これを迷わずダブルクリックすれ
ばよいw
だいたい2分ぐらいで最大表示枚数が安定する。
プログラムの終了は [ ESC ] キー。
Celeron G1820 + Intel HD無印 で1500枚程度。
160デフォルトの名無しさん
2018/05/23(水) 19:42:34.90ID:Au5e7VGg 僕の知り合いの知り合いができたパソコン一台でお金持ちになれるやり方
役に立つかもしれません
グーグルで検索するといいかも『ネットで稼ぐ方法 モニアレフヌノ』
CRP7I
役に立つかもしれません
グーグルで検索するといいかも『ネットで稼ぐ方法 モニアレフヌノ』
CRP7I
161デフォルトの名無しさん
2018/05/24(木) 10:53:48.52ID:cPlRxlDn CRP7I
162デフォルトの名無しさん
2018/05/25(金) 19:20:37.97ID:TsdeULHr163デフォルトの名無しさん
2018/07/04(水) 22:48:21.01ID:gFgZc5FG TJH
164デフォルトの名無しさん
2018/07/06(金) 12:24:57.09ID:uTPDH9XV TJH
165デフォルトの名無しさん
2018/08/23(木) 09:04:57.51ID:by5uxKdK VC9 SP1 Hotfix For The vector<function<FT>> Crash
がダウンロードできないのですが、
どなたかアップロードしていただけないでしょうか?
https://blogs.msdn.microsoft.com/vcblog/2008/12/17/vc9-sp1-hotfix-for-the-vectorfunctionft-crash/#9234449
がダウンロードできないのですが、
どなたかアップロードしていただけないでしょうか?
https://blogs.msdn.microsoft.com/vcblog/2008/12/17/vc9-sp1-hotfix-for-the-vectorfunctionft-crash/#9234449
166デフォルトの名無しさん
2018/09/13(木) 23:46:46.29ID:MPXnmy/B 起動の仕方で浮動小数点演算に誤差が発生するのだけど、理由が分かる人居ますか?
今のところ、
A. Debugビルドのバイナリをダブルクリックして起動
B. Releaseビルドのバイナリをダブルクリックで起動
C. DebugビルドまたはReleaseビルドでF5で起動
の3種類出来てる。それぞれ微妙な誤差だ。(doubleの下位ビット)
AとBの違いについては諦めていたのだが、(なお両方とも/fp:precise)
実はCもあると気づいてしまった。
なお、バイナリをダブルクリックして起動、それにIDEをアタッチしても結果は変わらない。
それぞれAまたはCが出る。
何かIDEの設定を間違っているのだと思うのだけど…
今のところ、
A. Debugビルドのバイナリをダブルクリックして起動
B. Releaseビルドのバイナリをダブルクリックで起動
C. DebugビルドまたはReleaseビルドでF5で起動
の3種類出来てる。それぞれ微妙な誤差だ。(doubleの下位ビット)
AとBの違いについては諦めていたのだが、(なお両方とも/fp:precise)
実はCもあると気づいてしまった。
なお、バイナリをダブルクリックして起動、それにIDEをアタッチしても結果は変わらない。
それぞれAまたはCが出る。
何かIDEの設定を間違っているのだと思うのだけど…
167デフォルトの名無しさん
2018/09/14(金) 12:43:29.26ID:5xDSXwp0 0fillしてないんだろ
168デフォルトの名無しさん
2018/09/14(金) 13:05:12.93ID:XcO59d50 再現性は100%なので、初期化のミスではない。(と思っている)
演算途中の結果を double なら16進16桁でテキストにダンプしている。
数値だけではないが500MB程度のファイルが出力され、
diff を取ることによりレグレッションテストをしている。
今のところ、A/B/Cの3種類しか出ない。
初期化忘れならこうはならない。(はず)
演算途中の結果を double なら16進16桁でテキストにダンプしている。
数値だけではないが500MB程度のファイルが出力され、
diff を取ることによりレグレッションテストをしている。
今のところ、A/B/Cの3種類しか出ない。
初期化忘れならこうはならない。(はず)
169デフォルトの名無しさん
2018/09/14(金) 13:09:49.07ID:Qw2nkUqU MSのエンジニアを信じるか、再現可能なソースも示さず問題だ問題だ言ってるとこの馬の骨とも知れない奴を
信じるかって言われたら迷うことなく前者を信じるw
信じるかって言われたら迷うことなく前者を信じるw
170デフォルトの名無しさん
2018/09/14(金) 14:43:10.29ID:XcO59d50 俺はIDEのバグだとは思っていない。
何かIDEの設定があって、俺がそれを適切にやってないのだと思っている。
色々見た限り、俺は /fp:precise しか発見出来なかった。
ただしこれは一応適切に設定されている。
他にないかな?ということ。
何かIDEの設定があって、俺がそれを適切にやってないのだと思っている。
色々見た限り、俺は /fp:precise しか発見出来なかった。
ただしこれは一応適切に設定されている。
他にないかな?ということ。
171デフォルトの名無しさん
2018/09/14(金) 15:49:43.21ID:cyu8WCuc IDEじゃなくてコマンドラインからコンパイラで直接コンパイルしても一緒?
172デフォルトの名無しさん
2018/09/14(金) 16:14:47.18ID:XcO59d50 どういう意味?
(どれとどれの違いにフォーカスしろと?)
俺はバイナリに問題があるとは思っていない。
何らかの理由で浮動小数点のモードが切り替えられたりしてないかを疑ってる。
だからIDEの設定とか、そっちを見てる。
Release/Debugのバイナリは当たり前だが違ってる。
/O2と/Od等だ。
ただそれでも /fp:precise の場合は
浮動小数点の演算順序を入れ替えない範囲で最適化される事になっている。
逆アセンブラは見たけどちょっとグチャグチャすぎてよく分からなかった。
(見た範囲では演算順序の入れ替えはないように思えた)
(どれとどれの違いにフォーカスしろと?)
俺はバイナリに問題があるとは思っていない。
何らかの理由で浮動小数点のモードが切り替えられたりしてないかを疑ってる。
だからIDEの設定とか、そっちを見てる。
Release/Debugのバイナリは当たり前だが違ってる。
/O2と/Od等だ。
ただそれでも /fp:precise の場合は
浮動小数点の演算順序を入れ替えない範囲で最適化される事になっている。
逆アセンブラは見たけどちょっとグチャグチャすぎてよく分からなかった。
(見た範囲では演算順序の入れ替えはないように思えた)
173デフォルトの名無しさん
2018/09/14(金) 16:25:44.73ID:2giHKuhd >>166
double型を使っていても、SSEのXMMレジスタなどを使う場合、昔のfld, fst, fmulなどを使う場合より基本的には精度が落ちる。
丸めの方向も四捨五入、正負どちらかの方向への丸めや切り捨てなどの他、確か、精度を気にしない、なんてオプションもあった気がする。ゲームで使うことを想定しているらしい。
SSE用に最適化を掛けると、速度は上がるが精度は落ちるかも知れない。
double型を使っていても、SSEのXMMレジスタなどを使う場合、昔のfld, fst, fmulなどを使う場合より基本的には精度が落ちる。
丸めの方向も四捨五入、正負どちらかの方向への丸めや切り捨てなどの他、確か、精度を気にしない、なんてオプションもあった気がする。ゲームで使うことを想定しているらしい。
SSE用に最適化を掛けると、速度は上がるが精度は落ちるかも知れない。
174デフォルトの名無しさん
2018/09/14(金) 17:45:18.51ID:XcO59d50 >>173
今の範囲ではSSEは使っていない(はず)
「拡張命令セットを有効にする」は「設定無し」になっている。(多分デフォのまま)
見た目全部x87が出てたし。
やっぱRelease/Debugの違いから攻めろって感じか?
俺もF5起動で結果が異なるってのは全く予想してなかったし。(ただしこちらの問題だろうけど)
演算部分は場合によってはSSEのアセンブラに差し替えるので、
問題になる場合には、Release/Debugの違いはこれで吸収するつもりだった。
(これは1ヶ月後にやるかも)
今の範囲ではSSEは使っていない(はず)
「拡張命令セットを有効にする」は「設定無し」になっている。(多分デフォのまま)
見た目全部x87が出てたし。
やっぱRelease/Debugの違いから攻めろって感じか?
俺もF5起動で結果が異なるってのは全く予想してなかったし。(ただしこちらの問題だろうけど)
演算部分は場合によってはSSEのアセンブラに差し替えるので、
問題になる場合には、Release/Debugの違いはこれで吸収するつもりだった。
(これは1ヶ月後にやるかも)
175デフォルトの名無しさん
2018/09/14(金) 17:48:23.40ID:HVgt1gkj 浮動小数点の誤差を考慮に入れてないというイージーな仕様バグですね。
176デフォルトの名無しさん
2018/09/14(金) 21:39:03.40ID:fXySkelb 再現するコードをみないとなにもわかるわけがない
低学歴知恵遅れが書くコードなんかなにをやってるか分からないからな
ごちゃごちゃいってないで再現するコードをあげなさい
低学歴知恵遅れが書くコードなんかなにをやってるか分からないからな
ごちゃごちゃいってないで再現するコードをあげなさい
177デフォルトの名無しさん
2018/09/15(土) 06:26:55.94ID:/OsufeBT 月並みな意見だけど、
「症状を再現できる最小のソースと初期データ、それとコンパイル環境」
まで切り詰めてみるのが早道じゃないかな。
ちょくちょく発生する事例なら、解決策を知ってる誰かが教えてくれてるかと。
週末、より多くの人が質問を見ることを期待して待つ手もあるけど。
「症状を再現できる最小のソースと初期データ、それとコンパイル環境」
まで切り詰めてみるのが早道じゃないかな。
ちょくちょく発生する事例なら、解決策を知ってる誰かが教えてくれてるかと。
週末、より多くの人が質問を見ることを期待して待つ手もあるけど。
178デフォルトの名無しさん
2018/09/15(土) 08:56:57.28ID:9ZmI9OgI より基本に立ち返ろう
そもそも誤差はあるのか?
計算結果を何を使ってどう出力しているかだけでもソースを見せてくれ
そもそも誤差はあるのか?
計算結果を何を使ってどう出力しているかだけでもソースを見せてくれ
179デフォルトの名無しさん
2018/09/15(土) 13:36:34.65ID:heijdb7v180デフォルトの名無しさん
2018/09/15(土) 13:42:47.95ID:heijdb7v fpu control word で、丸め方法と、精度の二つを独立に設定できる。
この精度の設定で、メモリ上の表現がdouble型でも、計算時のfpuの内部精度が変わってくる。
普通は64bit doubleに対して、fpu内部では80bitの精度で計算する。仮数部のbit数は、確か、それぞれ、53BIT、64BITだったかな。
この精度の設定で、メモリ上の表現がdouble型でも、計算時のfpuの内部精度が変わってくる。
普通は64bit doubleに対して、fpu内部では80bitの精度で計算する。仮数部のbit数は、確か、それぞれ、53BIT、64BITだったかな。
181デフォルトの名無しさん
2018/09/15(土) 14:05:09.61ID:heijdb7v Intel® 64 and IA-32 Architectures Software Developer’s Manual
[Vol 1]
11.6.8 Compatibility of SIMD and x87 FPU Floating-Point Data Types
SSE and SSE2 extensions operate on the same single-precision and double-precision floating-point data types that
the x87 FPU operates on. However, when operating on these data types, the SSE and SSE2 extensions operate on
them in their native format (single-precision or double-precision), in contrast to the x87 FPU which extends them
to double extended-precision floating-point format to perform computations and then rounds the result back to a
single-precision or double-precision format before writing results to memory. Because the x87 FPU operates on a
higher precision format and then rounds the result to a lower precision format, it may return a slightly different
result when performing the same operation on the same single-precision or double-precision floating-point values
than is returned by the SSE and SSE2 extensions. The difference occurs only in the least-significant bits of the
significand.
[Vol 1]
11.6.8 Compatibility of SIMD and x87 FPU Floating-Point Data Types
SSE and SSE2 extensions operate on the same single-precision and double-precision floating-point data types that
the x87 FPU operates on. However, when operating on these data types, the SSE and SSE2 extensions operate on
them in their native format (single-precision or double-precision), in contrast to the x87 FPU which extends them
to double extended-precision floating-point format to perform computations and then rounds the result back to a
single-precision or double-precision format before writing results to memory. Because the x87 FPU operates on a
higher precision format and then rounds the result to a lower precision format, it may return a slightly different
result when performing the same operation on the same single-precision or double-precision floating-point values
than is returned by the SSE and SSE2 extensions. The difference occurs only in the least-significant bits of the
significand.
182デフォルトの名無しさん
2018/09/15(土) 14:14:58.92ID:heijdb7v >>181
書いてある意味は、
「SSEやSSE2だと、float(32BIT)やdouble(64BIT)のまま計算するが、x87 fpuだと、もっと高い精度であるところの
『double extended-precision floating-point format(拡張倍精度浮動小数点フォーマット:80BIT)』
で計算を実行して、丸めてから、floatやdoubleに戻す。
そのため、SSE/SSE2 と x87 fpuでは結果が変わることがある。
しかし、その場合でも結果の違いは、仮数部の LSB (最も価値の小さいBIT)の1BITにだけ現れる。」
というような事。
書いてある意味は、
「SSEやSSE2だと、float(32BIT)やdouble(64BIT)のまま計算するが、x87 fpuだと、もっと高い精度であるところの
『double extended-precision floating-point format(拡張倍精度浮動小数点フォーマット:80BIT)』
で計算を実行して、丸めてから、floatやdoubleに戻す。
そのため、SSE/SSE2 と x87 fpuでは結果が変わることがある。
しかし、その場合でも結果の違いは、仮数部の LSB (最も価値の小さいBIT)の1BITにだけ現れる。」
というような事。
183デフォルトの名無しさん
2018/09/15(土) 16:09:28.75ID:aC3C7hdp 揚げ足取りだけどLSBを「最も価値が小さい」って直訳はいかがなものかなw
普通に最下位ビットじゃないの?
ところで
> the least-significant bits
これ何で複数形なのかね
普通に最下位ビットじゃないの?
ところで
> the least-significant bits
これ何で複数形なのかね
184デフォルトの名無しさん
2018/09/15(土) 16:14:15.89ID:AVfR6YnT 2の0乗だから実際価値が低い
上はMVBで
上はMVBで
185デフォルトの名無しさん
2018/09/15(土) 17:07:56.98ID:UR1d6CKz186デフォルトの名無しさん
2018/09/15(土) 17:12:32.47ID:heijdb7v >>183
「The difference occurs only in the least-significant bits of the significand.」
これは、SSE の場合の LSB と、x87 FPU の場合の FPU の2種類を頭の中に想定していると思われる。
SSE: a1 = 1.xxxxxxxxz * 10^b
x87 : a2 = 1.yyyyyyyyw * 10^c
つまり、LSB は、↑のように、z と w で、2つあるので、LSBs という英語になる。
「The difference occurs only in the least-significant bits of the significand.」
これは、SSE の場合の LSB と、x87 FPU の場合の FPU の2種類を頭の中に想定していると思われる。
SSE: a1 = 1.xxxxxxxxz * 10^b
x87 : a2 = 1.yyyyyyyyw * 10^c
つまり、LSB は、↑のように、z と w で、2つあるので、LSBs という英語になる。
187デフォルトの名無しさん
2018/09/15(土) 17:15:04.14ID:heijdb7v 誤:これは、SSE の場合の LSB と、x87 FPU の場合の FPU の2種類を
正:これは、SSE の場合の LSB と、x87 FPU の場合の 2種類を
正:これは、SSE の場合の LSB と、x87 FPU の場合の 2種類を
188デフォルトの名無しさん
2018/09/15(土) 17:18:55.19ID:heijdb7v >>183
>揚げ足取りだけどLSBを「最も価値が小さい」って直訳はいかがなものかなw
>普通に最下位ビットじゃないの?
整数の場合は、「最下位ビット」というと、本当にBITの位置が一番右にあるようなイメージもある。
一方、浮動小数点数の場合は、右にあるとかより、仮数部において、一番価値の小さいビット、というニュアンスを使えたかった。
IEEEでは、それは確かに一番右にあるビットであって、マシン語レベルの表現では、BIT0ではあるのだが。
ニュアンス的に。
>揚げ足取りだけどLSBを「最も価値が小さい」って直訳はいかがなものかなw
>普通に最下位ビットじゃないの?
整数の場合は、「最下位ビット」というと、本当にBITの位置が一番右にあるようなイメージもある。
一方、浮動小数点数の場合は、右にあるとかより、仮数部において、一番価値の小さいビット、というニュアンスを使えたかった。
IEEEでは、それは確かに一番右にあるビットであって、マシン語レベルの表現では、BIT0ではあるのだが。
ニュアンス的に。
189デフォルトの名無しさん
2018/09/15(土) 17:29:56.92ID:aC3C7hdp >>186
それは俺も思ったけど、それならsignificandの方も複数じゃないとおかしいような...
それは俺も思ったけど、それならsignificandの方も複数じゃないとおかしいような...
190デフォルトの名無しさん
2018/09/15(土) 20:35:40.44ID:UR1d6CKz 同様の症状を再現出来るようになったので上げる。
完全再現は出来てないが、使い物にはなるはず。興味がある人はよろしく。
症状:
単独で起動した場合と、IDEから起動した場合で、結果が異なる。
環境:
VS++2008ExpressEdition
再現方法:
1. 新規プロジェクトを作成。(CLRコンソールアプリケーション。オプション等は全てデフォのまま)
2. mainを以下ソースと差し替える。
3. Releaseビルドで実行する。(Debugビルドでは再現しなかったので注意)
結果:
0.000000, 0x1ff68ddfb62221dd (IDEからの起動(F5))
0.000000, 0x1ff68ddfb62221de (コマンドプロンプトからの起動)
最後の2bitが異なる。(誤差は1bit)
備考:
俺が遭遇しているのとはやや異なる。(俺の場合、Debugビルドでもこれが発生する)
この再現状況だと、単に
「DebugとReleaseでバイナリが異なり、
IDEから起動した場合は常にDebugバイナリを掴んでいるだけでは?」
とも取れるが、こちらで確認した限りはちゃんとReleaseバイナリを掴んでいる。
理由は、
1. Debug/Releaseの両方のバイナリがない状態で実行した場合、
自動的に作成されるのはReleaseバイナリ。(当然だが)
結果は****ddとなる。(ブレークポイント等で止めて確認する)
2. そのReleaseバイナリをコマンドプロンプトから起動すると、****deの結果が得られる。
完全再現は出来てないが、使い物にはなるはず。興味がある人はよろしく。
症状:
単独で起動した場合と、IDEから起動した場合で、結果が異なる。
環境:
VS++2008ExpressEdition
再現方法:
1. 新規プロジェクトを作成。(CLRコンソールアプリケーション。オプション等は全てデフォのまま)
2. mainを以下ソースと差し替える。
3. Releaseビルドで実行する。(Debugビルドでは再現しなかったので注意)
結果:
0.000000, 0x1ff68ddfb62221dd (IDEからの起動(F5))
0.000000, 0x1ff68ddfb62221de (コマンドプロンプトからの起動)
最後の2bitが異なる。(誤差は1bit)
備考:
俺が遭遇しているのとはやや異なる。(俺の場合、Debugビルドでもこれが発生する)
この再現状況だと、単に
「DebugとReleaseでバイナリが異なり、
IDEから起動した場合は常にDebugバイナリを掴んでいるだけでは?」
とも取れるが、こちらで確認した限りはちゃんとReleaseバイナリを掴んでいる。
理由は、
1. Debug/Releaseの両方のバイナリがない状態で実行した場合、
自動的に作成されるのはReleaseバイナリ。(当然だが)
結果は****ddとなる。(ブレークポイント等で止めて確認する)
2. そのReleaseバイナリをコマンドプロンプトから起動すると、****deの結果が得られる。
191デフォルトの名無しさん
2018/09/15(土) 20:37:06.43ID:UR1d6CKz ソース:
#include "stdafx.h"
#include <math.h>
using namespace System;
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;
}
int main(array<System::String ^> ^args)
{
int count = 16;
__int64 inputs_hex[16] = {
0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x1fedb1530240aa54,
0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x1ff0af0d95025bc3,
0x1fc9353df6af376b, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000,
0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000};
double* inputs = (double*)inputs_hex;
double norm = calc_norm_and_regulate(count, inputs, false);
Console::Write(String::Format("{0:F6}, 0x{1:x16}\r\n",norm, *(__int64*)&norm));
// Release build
// 0.000000, 0x1ff68ddfb62221dd from IDE
// 0.000000, 0x1ff68ddfb62221de from command prompt
return 0;
}
#include "stdafx.h"
#include <math.h>
using namespace System;
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;
}
int main(array<System::String ^> ^args)
{
int count = 16;
__int64 inputs_hex[16] = {
0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x1fedb1530240aa54,
0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x1ff0af0d95025bc3,
0x1fc9353df6af376b, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000,
0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000};
double* inputs = (double*)inputs_hex;
double norm = calc_norm_and_regulate(count, inputs, false);
Console::Write(String::Format("{0:F6}, 0x{1:x16}\r\n",norm, *(__int64*)&norm));
// Release build
// 0.000000, 0x1ff68ddfb62221dd from IDE
// 0.000000, 0x1ff68ddfb62221de from command prompt
return 0;
}
192デフォルトの名無しさん
2018/09/15(土) 20:42:48.06ID:UR1d6CKz オプション等(コマンドライン):(全てデフォのままのはずだが一応)
C/C++:
/GL /D "WIN32" /D "NDEBUG" /D "_UNICODE" /D "UNICODE" /FD /EHa /MD /Yu"stdafx.h"
/Fp"Release\test_floating_error4.pch" /Fo"Release\\" /Fd"Release\vc90.pdb"
/W3 /nologo /c /Zi /clr /TP /errorReport:prompt /FU "c:\Windows\Microsoft.NET\Framework\v2.0.50727\System.dll"
/FU "c:\Windows\Microsoft.NET\Framework\v2.0.50727\System.Data.dll"
/FU "c:\Windows\Microsoft.NET\Framework\v2.0.50727\System.XML.dll"
リンカ:
/OUT:"MYPATH\test_floating_error4\Release\test_floating_error4.exe"
/INCREMENTAL:NO /NOLOGO /MANIFEST
/MANIFESTFILE:"Release\test_floating_error4.exe.intermediate.manifest"
/MANIFESTUAC:"level='asInvoker' uiAccess='false'" /DEBUG
/PDB:"MYPATH\test_floating_error4\Release\test_floating_error4.pdb"
/LTCG /DYNAMICBASE /FIXED:No /NXCOMPAT /MACHINE:X86 /ERRORREPORT:PROMPT
パスは$MYPATHと書き換えた。また、投稿の為に適宜改行を入れた。
このプロジェクト名は見れば分かるとおりtest_floating_error4。
C/C++:
/GL /D "WIN32" /D "NDEBUG" /D "_UNICODE" /D "UNICODE" /FD /EHa /MD /Yu"stdafx.h"
/Fp"Release\test_floating_error4.pch" /Fo"Release\\" /Fd"Release\vc90.pdb"
/W3 /nologo /c /Zi /clr /TP /errorReport:prompt /FU "c:\Windows\Microsoft.NET\Framework\v2.0.50727\System.dll"
/FU "c:\Windows\Microsoft.NET\Framework\v2.0.50727\System.Data.dll"
/FU "c:\Windows\Microsoft.NET\Framework\v2.0.50727\System.XML.dll"
リンカ:
/OUT:"MYPATH\test_floating_error4\Release\test_floating_error4.exe"
/INCREMENTAL:NO /NOLOGO /MANIFEST
/MANIFESTFILE:"Release\test_floating_error4.exe.intermediate.manifest"
/MANIFESTUAC:"level='asInvoker' uiAccess='false'" /DEBUG
/PDB:"MYPATH\test_floating_error4\Release\test_floating_error4.pdb"
/LTCG /DYNAMICBASE /FIXED:No /NXCOMPAT /MACHINE:X86 /ERRORREPORT:PROMPT
パスは$MYPATHと書き換えた。また、投稿の為に適宜改行を入れた。
このプロジェクト名は見れば分かるとおりtest_floating_error4。
193デフォルトの名無しさん
2018/09/15(土) 20:43:03.84ID:UR1d6CKz 備考2:
なおこの方法で見える calc_norm_and_regulate 関数の『逆アセンブル』結果は
俺の環境での物とコールアドレス以外は一致していることを確認している。
一応、diff結果は以下。
8c8
< 0000000c cmp dword ptr ds:[00752E14h],0
---
> 0000000c cmp dword ptr ds:[007D2E14h],0
10c10
< 00000015 call 676F58B9
---
> 00000015 call 683C58B9
44c44
< 0000006a call FF0455E8
---
> 0000006a call FFD955E8
なおこの方法で見える calc_norm_and_regulate 関数の『逆アセンブル』結果は
俺の環境での物とコールアドレス以外は一致していることを確認している。
一応、diff結果は以下。
8c8
< 0000000c cmp dword ptr ds:[00752E14h],0
---
> 0000000c cmp dword ptr ds:[007D2E14h],0
10c10
< 00000015 call 676F58B9
---
> 00000015 call 683C58B9
44c44
< 0000006a call FF0455E8
---
> 0000006a call FFD955E8
194デフォルトの名無しさん
2018/09/16(日) 02:47:43.28ID:wIV2HUNW >>190
C++/CLR では、.Net を使っているから、起動方法が違うだけでも、
fpu control word の値や、使うCPU命令がx87 FPUなのか、SSE
なのかが違ってくる可能性があるかもしれない。
fpu control word は、main()関数に入る前の start up codeの中で
初期化される。
C++/CLR では、.Net を使っているから、起動方法が違うだけでも、
fpu control word の値や、使うCPU命令がx87 FPUなのか、SSE
なのかが違ってくる可能性があるかもしれない。
fpu control word は、main()関数に入る前の start up codeの中で
初期化される。
195デフォルトの名無しさん
2018/09/16(日) 03:19:36.22ID:wIV2HUNW >>191
// Release build
// 0.000000, 0x1ff68ddfb62221dd from IDE
// 0.000000, 0x1ff68ddfb62221de from command prompt
それにしても、随分小さな値だね。ちなみに、浮動小数点表示
の場合の有効数字の桁数を上げたら、どのようになる?
1.xxxe-yy
表示にして。
// Release build
// 0.000000, 0x1ff68ddfb62221dd from IDE
// 0.000000, 0x1ff68ddfb62221de from command prompt
それにしても、随分小さな値だね。ちなみに、浮動小数点表示
の場合の有効数字の桁数を上げたら、どのようになる?
1.xxxe-yy
表示にして。
196デフォルトの名無しさん
2018/09/16(日) 03:40:33.66ID:wIV2HUNW >>191
試しに、ソースの冒頭に
#include <stdio.h>
を追加してから、
Console::Write(String::Format("{0:F6}, 0x{1:x16}\r\n",norm, *(__int64*)&norm));
の部分を、
printf( "%30.30e, 0x%016X\n", norm, *(__int64*)&norm) );
としてみるとどうなる?
試しに、ソースの冒頭に
#include <stdio.h>
を追加してから、
Console::Write(String::Format("{0:F6}, 0x{1:x16}\r\n",norm, *(__int64*)&norm));
の部分を、
printf( "%30.30e, 0x%016X\n", norm, *(__int64*)&norm) );
としてみるとどうなる?
197デフォルトの名無しさん
2018/09/16(日) 03:42:01.82ID:wIV2HUNW >>196
誤: printf( "%30.30e, 0x%016X\n", norm, *(__int64*)&norm) );
正: printf( "%30.30e, 0x%016X\n", norm, *(__int64*)&norm );
誤: printf( "%30.30e, 0x%016X\n", norm, *(__int64*)&norm) );
正: printf( "%30.30e, 0x%016X\n", norm, *(__int64*)&norm );
198デフォルトの名無しさん
2018/09/16(日) 07:27:22.50ID:SOVIz+sV > 0x1ff68ddfb62221dd(Debug)
> 0x1ff68ddfb62221de(Release)
VS 2010 VC++ Express でも再現した
> 0x1ff68ddfb62221de(Release)
VS 2010 VC++ Express でも再現した
199デフォルトの名無しさん
2018/09/16(日) 07:38:10.70ID:SOVIz+sV ↓このループを抜けたあと、すでにReleaseビルドとDebugビルドでは
normの値に差異が発生してることが確認できた
for (int i=0;i<num;i++) norm += (double)r[i] * (double)r[i];
↓この下に(ループ内に)fprintf文を入れるだけで
ReleaseビルドとDebugビルドが同じ実行結果になることが確認できた
norm += (double)r[i] * (double)r[i];
とりあえずまずこれだけは分かったから
低学歴知恵遅れが書いたウンココードの問題箇所を限定する
normの値に差異が発生してることが確認できた
for (int i=0;i<num;i++) norm += (double)r[i] * (double)r[i];
↓この下に(ループ内に)fprintf文を入れるだけで
ReleaseビルドとDebugビルドが同じ実行結果になることが確認できた
norm += (double)r[i] * (double)r[i];
とりあえずまずこれだけは分かったから
低学歴知恵遅れが書いたウンココードの問題箇所を限定する
200デフォルトの名無しさん
2018/09/16(日) 07:51:03.41ID:SOVIz+sV @-1 デフォルト設定(Release)
【コード】
#include "stdafx.h"
#include <stdio.h>
#include <stdint.h>
#include <math.h>
int main(array<System::String ^> ^args)
{
__int64 inputs_hex[16] = {
0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x1fedb1530240aa54,
0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x1ff0af0d95025bc3,
0x1fc9353df6af376b, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000,
0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000
};
double* r = (double*)inputs_hex;
double norm = 0;
for (int i = 0; i < 16; i++) {
norm += (double)r[i] * (double)r[i];
// fprintf(stdout, "[1]0x%016llX:%.19lg\n", *(uint64_t*)&norm, norm);
}
fprintf(stdout, "0x%016llX:%.19lg\n", *(uint64_t*)&norm, norm);
return 0;
}
【コード】
#include "stdafx.h"
#include <stdio.h>
#include <stdint.h>
#include <math.h>
int main(array<System::String ^> ^args)
{
__int64 inputs_hex[16] = {
0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x1fedb1530240aa54,
0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x1ff0af0d95025bc3,
0x1fc9353df6af376b, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000,
0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000
};
double* r = (double*)inputs_hex;
double norm = 0;
for (int i = 0; i < 16; i++) {
norm += (double)r[i] * (double)r[i];
// fprintf(stdout, "[1]0x%016llX:%.19lg\n", *(uint64_t*)&norm, norm);
}
fprintf(stdout, "0x%016llX:%.19lg\n", *(uint64_t*)&norm, norm);
return 0;
}
201デフォルトの名無しさん
2018/09/16(日) 07:51:56.62ID:SOVIz+sV @-1 デフォルト設定(Release)
↓このコードの逆アセンブルコード
https://ideone.com/Ryyxkl
【実行結果】
0x0007F2C44DFFF8F2:1.1053482540585106e-308
↓このコードの逆アセンブルコード
https://ideone.com/Ryyxkl
【実行結果】
0x0007F2C44DFFF8F2:1.1053482540585106e-308
202デフォルトの名無しさん
2018/09/16(日) 07:53:20.79ID:SOVIz+sV @-2 デフォルト設定(Release)
#include "stdafx.h"
#include <stdio.h>
#include <stdint.h>
#include <math.h>
int main(array<System::String ^> ^args)
{
__int64 inputs_hex[16] = {
0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x1fedb1530240aa54,
0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x1ff0af0d95025bc3,
0x1fc9353df6af376b, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000,
0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000
};
double* r = (double*)inputs_hex;
double norm = 0;
for (int i = 0; i < 16; i++) {
norm += (double)r[i] * (double)r[i];
fprintf(stdout, "[1]0x%016llX:%.19lg\n", *(uint64_t*)&norm, norm);
}
fprintf(stdout, "0x%016llX:%.19lg\n", *(uint64_t*)&norm, norm);
return 0;
}
#include "stdafx.h"
#include <stdio.h>
#include <stdint.h>
#include <math.h>
int main(array<System::String ^> ^args)
{
__int64 inputs_hex[16] = {
0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x1fedb1530240aa54,
0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x1ff0af0d95025bc3,
0x1fc9353df6af376b, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000,
0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000
};
double* r = (double*)inputs_hex;
double norm = 0;
for (int i = 0; i < 16; i++) {
norm += (double)r[i] * (double)r[i];
fprintf(stdout, "[1]0x%016llX:%.19lg\n", *(uint64_t*)&norm, norm);
}
fprintf(stdout, "0x%016llX:%.19lg\n", *(uint64_t*)&norm, norm);
return 0;
}
203デフォルトの名無しさん
2018/09/16(日) 08:02:12.99ID:SOVIz+sV @-2 デフォルト設定(Release)
↓このコードの逆アセンブルコード
https://ideone.com/4j12ib
【実行結果】
↓実行結果を書き込めないからこっちに書き込んどいた
https://ideone.com/gOqtki
0x0007F2C44DFFF8F1:1.1053482540585101e-308
↓このコードの逆アセンブルコード
https://ideone.com/4j12ib
【実行結果】
↓実行結果を書き込めないからこっちに書き込んどいた
https://ideone.com/gOqtki
0x0007F2C44DFFF8F1:1.1053482540585101e-308
204デフォルトの名無しさん
2018/09/16(日) 08:05:50.92ID:SOVIz+sV A-1 最適化無効 (/Od)(Release)
※ コードは@-1(>>200)と同じ
↓このコードの逆アセンブルコード
https://ideone.com/cONCAx
【実行結果】
0x0007F2C44DFFF8F1:1.1053482540585101e-308
※ コードは@-1(>>200)と同じ
↓このコードの逆アセンブルコード
https://ideone.com/cONCAx
【実行結果】
0x0007F2C44DFFF8F1:1.1053482540585101e-308
205デフォルトの名無しさん
2018/09/16(日) 08:09:59.78ID:SOVIz+sV A-2 最適化無効 (/Od)(Release)
※ コードはA-2(>>202)と同じ
↓このコードの逆アセンブルコード
https://ideone.com/kuRt3w
【実行結果】
※ @-2(>>203)と同じ
0x0007F2C44DFFF8F1:1.1053482540585101e-308
※ コードはA-2(>>202)と同じ
↓このコードの逆アセンブルコード
https://ideone.com/kuRt3w
【実行結果】
※ @-2(>>203)と同じ
0x0007F2C44DFFF8F1:1.1053482540585101e-308
206デフォルトの名無しさん
2018/09/16(日) 08:20:27.67ID:SOVIz+sV @-1、@-2の逆アセンブルの出力結果を比較すると原型をとどめてないぐらいグチョグチョに違う(最適化のせいと考えられる)
A-1、A-2の逆アセンブルの出力結果を比較すると差異はほとんどない(Aは両方ともまったく最適化されてないから当然)
@-1とA-1の逆アセンブルの出力結果を比較すると原型をとどめてないぐらいグチョグチョに違う(@-1のコード(>>200)ははげしくウンコ最適化されてると考えられる)
@-2とA-2の逆アセンブルの出力結果を比較すると差異はほとんどない(@-2のコード(>>202)はあまり最適化されてないと考えられる)
はっきりいって、これ以上見る気もしないしテキトーだが
ウンコみたいな最適化で演算の順序が入れ替わったせいで、誤差が発生しているものと考えられる
A-1、A-2の逆アセンブルの出力結果を比較すると差異はほとんどない(Aは両方ともまったく最適化されてないから当然)
@-1とA-1の逆アセンブルの出力結果を比較すると原型をとどめてないぐらいグチョグチョに違う(@-1のコード(>>200)ははげしくウンコ最適化されてると考えられる)
@-2とA-2の逆アセンブルの出力結果を比較すると差異はほとんどない(@-2のコード(>>202)はあまり最適化されてないと考えられる)
はっきりいって、これ以上見る気もしないしテキトーだが
ウンコみたいな最適化で演算の順序が入れ替わったせいで、誤差が発生しているものと考えられる
207デフォルトの名無しさん
2018/09/16(日) 08:28:37.25ID:zL1WUjLu >>198以降、
すまん、入れ替わりになるかもしれんが後で確認する。
まず>>194その他について回答する。
>>194
SSEは /arch:SSE または /arch:SSE2 でないと出ないことになっており、勿論設定はしていない。
また、逆アセンブル結果では x87 命令のみであるのも確認している。
ただ今回の問題は、本当にReleaseビルドのバイナリを逆アセンブルしているか怪しい事だが。
>>195
小さい値なのは偶々だ。
辿って行ってそれが1回目にヒットする入力データだっただけのこと。
>>196
.NETの書式指定はググり難いが以下。
https://docs.microsoft.com/en-us/dotnet/standard/base-types/standard-numeric-format-strings
概ねprintfと同じで、自動的にやってくれるのが増えている。
30桁欲しければ以下。
Console::Write(String::Format("{0:E6}, {0:E30}\r\n",norm));
// 出力は 1.051355E-154, 1.051355436595307800000000000000E-154
なおdoubleは16桁な。(15.9=53*log(10)2)
ただ当たり前だが、書式を変えたところで計算結果は変わらないし、
精度の問題には関係ない。
すまん、入れ替わりになるかもしれんが後で確認する。
まず>>194その他について回答する。
>>194
SSEは /arch:SSE または /arch:SSE2 でないと出ないことになっており、勿論設定はしていない。
また、逆アセンブル結果では x87 命令のみであるのも確認している。
ただ今回の問題は、本当にReleaseビルドのバイナリを逆アセンブルしているか怪しい事だが。
>>195
小さい値なのは偶々だ。
辿って行ってそれが1回目にヒットする入力データだっただけのこと。
>>196
.NETの書式指定はググり難いが以下。
https://docs.microsoft.com/en-us/dotnet/standard/base-types/standard-numeric-format-strings
概ねprintfと同じで、自動的にやってくれるのが増えている。
30桁欲しければ以下。
Console::Write(String::Format("{0:E6}, {0:E30}\r\n",norm));
// 出力は 1.051355E-154, 1.051355436595307800000000000000E-154
なおdoubleは16桁な。(15.9=53*log(10)2)
ただ当たり前だが、書式を変えたところで計算結果は変わらないし、
精度の問題には関係ない。
208デフォルトの名無しさん
2018/09/16(日) 08:29:03.14ID:zL1WUjLu >>194
FPU control registor については何故か安定した結果を得られていない。
インラインアセンブラは以下の通りで、
#pragma unmanaged
inline void fpu_getcw(unsigned short* cw) {
__asm{
fnstcw [cw];
}
}
#pragma managed
これを norm = calc_norm_and_regulate( ... ) の直前/直後に配置して読み出し、
同様にコンソール出力すると、以下となる。
また、IDEで起動した場合は、「レジスタ」で見れる。
なお定義は以下の通り。
[9:8]に対し、
0x00 : 単精度(24bit)
0x01 : reserved
0x10 : 倍精度(53bit)
0x11 : 拡張倍精度(64bit)
[11:10]に対し
0x00 : 最近値
0x01 : 切り捨て
0x10 : 切り上げ
0x11 : 0方向への切り捨て
FPU control registor については何故か安定した結果を得られていない。
インラインアセンブラは以下の通りで、
#pragma unmanaged
inline void fpu_getcw(unsigned short* cw) {
__asm{
fnstcw [cw];
}
}
#pragma managed
これを norm = calc_norm_and_regulate( ... ) の直前/直後に配置して読み出し、
同様にコンソール出力すると、以下となる。
また、IDEで起動した場合は、「レジスタ」で見れる。
なお定義は以下の通り。
[9:8]に対し、
0x00 : 単精度(24bit)
0x01 : reserved
0x10 : 倍精度(53bit)
0x11 : 拡張倍精度(64bit)
[11:10]に対し
0x00 : 最近値
0x01 : 切り捨て
0x10 : 切り上げ
0x11 : 0方向への切り捨て
209デフォルトの名無しさん
2018/09/16(日) 08:29:57.53ID:zL1WUjLu >>194
直後のみに配置:
0x027F (倍精度) = Debug(IDE起動)のIDE内表示、Release(IDE起動)のIDE内表示、
0x03a5 (拡張倍精度) = Debug(IDE起動)、Release(IDE起動)、
0x3fdc (拡張倍精度) = Debug(コマンドプロンプト)、
0xf280, 0xf290, 0xf160, 0xf010等、不安定 = Release(コマンドプロンプト)
直前のみに配置:
直後のみと同じ結果。(つまり『何故か』安定している)
Release(コマンドプロンプト)は不安定なのも同じ。
直前と直後に配置:
直前側は当然不安定になる。
直後側は「直後のみ」の結果と同じ。(Release(コマンドプロンプト)は不安定なのも同じ)
雰囲気からすると、IDE内表示は当てにならず、
命令自体は rdtsc と同じで非同期に実行されている雰囲気だが、
rdtsc命令の注意書きにある「シリアル化命令ではない」という但し書きが無く、状況は不明。
正直、正しく読み出せているか怪しい。(あてにならない)
これらから推測すると、暫定的には以下。
拡張倍精度 = Debug(IDE起動)、Release(IDE起動)、Debug(コマンドプロンプト)、
不明 = Release(コマンドプロンプト)
以上が>>194その他に対する回答。
これから>>198その他について確認する。
直後のみに配置:
0x027F (倍精度) = Debug(IDE起動)のIDE内表示、Release(IDE起動)のIDE内表示、
0x03a5 (拡張倍精度) = Debug(IDE起動)、Release(IDE起動)、
0x3fdc (拡張倍精度) = Debug(コマンドプロンプト)、
0xf280, 0xf290, 0xf160, 0xf010等、不安定 = Release(コマンドプロンプト)
直前のみに配置:
直後のみと同じ結果。(つまり『何故か』安定している)
Release(コマンドプロンプト)は不安定なのも同じ。
直前と直後に配置:
直前側は当然不安定になる。
直後側は「直後のみ」の結果と同じ。(Release(コマンドプロンプト)は不安定なのも同じ)
雰囲気からすると、IDE内表示は当てにならず、
命令自体は rdtsc と同じで非同期に実行されている雰囲気だが、
rdtsc命令の注意書きにある「シリアル化命令ではない」という但し書きが無く、状況は不明。
正直、正しく読み出せているか怪しい。(あてにならない)
これらから推測すると、暫定的には以下。
拡張倍精度 = Debug(IDE起動)、Release(IDE起動)、Debug(コマンドプロンプト)、
不明 = Release(コマンドプロンプト)
以上が>>194その他に対する回答。
これから>>198その他について確認する。
210デフォルトの名無しさん
2018/09/16(日) 12:52:37.56ID:haV9TZ8e >>209
興味深い結果だ。
興味深い結果だ。
211デフォルトの名無しさん
2018/09/16(日) 13:21:26.16ID:haV9TZ8e >>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 );
を使ってみたらどうなる?
>命令自体は 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デフォルトの名無しさん
2018/09/16(日) 13:31:15.50ID:Q5j4SiHR win32コンソールなら結果が同じ。 もう理由は分かったのに何が問題なんだ?こんなの何の影響もないだろう。
213デフォルトの名無しさん
2018/09/16(日) 13:33:14.92ID:zL1WUjLu >>198
再現実験ありがとう。
しかし色々問題がある。
1. 俺は起動方法による違いについてフォーカスしているが、
君はRelease/Debugの違いにフォーカスしている。
2. VC++2008では再現しない。(VC++2010では再現する)
3. ソース改変しすぎ。それでは意味がない。
4. >>206の結論は間違い。
まず問題なのはソースの改変だ。
ループ回数を16回と決め打ちしたことで 8*2 に展開されている。
その結果、元のソース(俺が遭遇した状況)では発生しえないことが発生している。
これでは意味がない。
そして、君の結論は間違いだ。
× > ウンコみたいな最適化で演算の順序が入れ替わったせいで、誤差が発生しているものと考えられる
逆アセンブルを追えば分かるが、演算順序は入れ替わっていない。
原因は、Debugでは fld/fmul/fadd/fstp と毎回64bitに整形されるのに対し、
Releaseでは (fld/fmul/fadd)*8 + fstp と整形が8回に1回と減り、
8回は80bit(拡張倍精度)で演算されるからだ。
(こうなったのは君が16回ループ決め打ちコードに改変したから)
ただしIDE上の fpu control registor の値は 相変わらず0x027F(倍精度)となっており、
IDEのこの表示が当てにならない事は分かる。
なおVC++2008では再現しなかった。
俺の環境では、16回決め打ちコードでも 8*2 に展開されず、Debugと同じコードだからだ。
勿論結果も同じだった。
再現実験ありがとう。
しかし色々問題がある。
1. 俺は起動方法による違いについてフォーカスしているが、
君はRelease/Debugの違いにフォーカスしている。
2. VC++2008では再現しない。(VC++2010では再現する)
3. ソース改変しすぎ。それでは意味がない。
4. >>206の結論は間違い。
まず問題なのはソースの改変だ。
ループ回数を16回と決め打ちしたことで 8*2 に展開されている。
その結果、元のソース(俺が遭遇した状況)では発生しえないことが発生している。
これでは意味がない。
そして、君の結論は間違いだ。
× > ウンコみたいな最適化で演算の順序が入れ替わったせいで、誤差が発生しているものと考えられる
逆アセンブルを追えば分かるが、演算順序は入れ替わっていない。
原因は、Debugでは fld/fmul/fadd/fstp と毎回64bitに整形されるのに対し、
Releaseでは (fld/fmul/fadd)*8 + fstp と整形が8回に1回と減り、
8回は80bit(拡張倍精度)で演算されるからだ。
(こうなったのは君が16回ループ決め打ちコードに改変したから)
ただしIDE上の fpu control registor の値は 相変わらず0x027F(倍精度)となっており、
IDEのこの表示が当てにならない事は分かる。
なおVC++2008では再現しなかった。
俺の環境では、16回決め打ちコードでも 8*2 に展開されず、Debugと同じコードだからだ。
勿論結果も同じだった。
214デフォルトの名無しさん
2018/09/16(日) 13:33:48.22ID:zL1WUjLu >>198
問題は、俺の環境で俺が提供したコード>>191だと、
同様に展開されないにも関わらず、『起動方法によって』結果が異なってしまう点だ。
俺の環境でのRelease/Debugの逆アセンブル結果のdiffは以下。
17c17
< 0000000c cmp dword ptr ds:[001C2E14h],0
---
> 0000000c cmp dword ptr ds:[00702E14h],0
19c19
< 00000015 call 68302BA9
---
> 00000015 call 683A5AB1
93c93
< 0000015a call FF6C3098
---
> 0000015a call FFCA57E8
98c98
< 0000016f push 0B5311Ch
---
> 0000016f push 0D03188h
104,105c104,105
< 00000183 push 4F9D68h
< 00000188 call FF6C30A4
---
> 00000183 push 2B71C0h
> 00000188 call FFCA57F4
アドレスの変更だけであり、君の結果
「ループ回数を決め打ちしたことによりアンローリングされ、一部の演算がx87精度で計算される」には該当しない。
そして、この状況でも結果が異なってしまうことが問題なのだ。
君は君が勝手に新しく作り込んだ問題に対し、間違った結論でお茶を濁したにすぎない。
君が知っているFPU関連のことはこちらも知っている上で、質問している。
問題は、俺の環境で俺が提供したコード>>191だと、
同様に展開されないにも関わらず、『起動方法によって』結果が異なってしまう点だ。
俺の環境でのRelease/Debugの逆アセンブル結果のdiffは以下。
17c17
< 0000000c cmp dword ptr ds:[001C2E14h],0
---
> 0000000c cmp dword ptr ds:[00702E14h],0
19c19
< 00000015 call 68302BA9
---
> 00000015 call 683A5AB1
93c93
< 0000015a call FF6C3098
---
> 0000015a call FFCA57E8
98c98
< 0000016f push 0B5311Ch
---
> 0000016f push 0D03188h
104,105c104,105
< 00000183 push 4F9D68h
< 00000188 call FF6C30A4
---
> 00000183 push 2B71C0h
> 00000188 call FFCA57F4
アドレスの変更だけであり、君の結果
「ループ回数を決め打ちしたことによりアンローリングされ、一部の演算がx87精度で計算される」には該当しない。
そして、この状況でも結果が異なってしまうことが問題なのだ。
君は君が勝手に新しく作り込んだ問題に対し、間違った結論でお茶を濁したにすぎない。
君が知っているFPU関連のことはこちらも知っている上で、質問している。
215デフォルトの名無しさん
2018/09/16(日) 13:53:17.67ID:haV9TZ8e >>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)に入っていても、計算が
80BITか、64BIT、32BITのどれで計算されるか異なったり、丸め方が四捨五入
か、正負二種類の方向の切り捨てなどが変わっている。
そして、IDEから起動した場合と、コマンドラインから起動した場合で結果が違う
のは、「2.」の理由によるものではないかと。そして、実際に、インラインアセンブラ
で fpu control word を読み取ってみると、不安定な値が読み出されたと。
なるほど、全く別の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)に入っていても、計算が
80BITか、64BIT、32BITのどれで計算されるか異なったり、丸め方が四捨五入
か、正負二種類の方向の切り捨てなどが変わっている。
そして、IDEから起動した場合と、コマンドラインから起動した場合で結果が違う
のは、「2.」の理由によるものではないかと。そして、実際に、インラインアセンブラ
で fpu control word を読み取ってみると、不安定な値が読み出されたと。
216デフォルトの名無しさん
2018/09/16(日) 13:58:15.86ID:haV9TZ8e まず、
__asm{
fnstcw [cw];
}
ではなく、_control87() を使ってみて欲しい。
インラインアセンブラは、独立した *.asm で書くより危険な場合が
あるかも知れないので。特にC関数の引数、今の場合は、「cw」を
インライン・アセンブラで用いた場合、正しいコードが出ているかどうか
は注意が必要。
__asm{
fnstcw [cw];
}
ではなく、_control87() を使ってみて欲しい。
インラインアセンブラは、独立した *.asm で書くより危険な場合が
あるかも知れないので。特にC関数の引数、今の場合は、「cw」を
インライン・アセンブラで用いた場合、正しいコードが出ているかどうか
は注意が必要。
217デフォルトの名無しさん
2018/09/16(日) 14:05:28.41ID:haV9TZ8e >>208
よく見ると、それは、かなり複雑な事情が絡みそうなコード。
以下のようにした方が安心。なお、「cw」という短すぎる引数名
も長年のプログラミング経験からすると、インラインアセンブラでは
怖い。また、
TTTT reg,引数名
や
TTTT 引数名
は大丈夫でも、
TTTT reg,[引数名]
や
TTTT [引数名]
は1命令では不可能な事をコンパイラに指示している事になるので
ちょっと怖い。間接の間接、つまり、[[ebp+8]]みたいな事を要求
しているが、そんなオペランドが使えるアセンブリ命令はx86/x64
では存在しないので。
#pragma unmanaged
inline void fpu_getcw(unsigned short *pCW) {
__asm{
mov edx,pCW
fnstcw [edx];
}
}
#pragma managed
よく見ると、それは、かなり複雑な事情が絡みそうなコード。
以下のようにした方が安心。なお、「cw」という短すぎる引数名
も長年のプログラミング経験からすると、インラインアセンブラでは
怖い。また、
TTTT reg,引数名
や
TTTT 引数名
は大丈夫でも、
TTTT reg,[引数名]
や
TTTT [引数名]
は1命令では不可能な事をコンパイラに指示している事になるので
ちょっと怖い。間接の間接、つまり、[[ebp+8]]みたいな事を要求
しているが、そんなオペランドが使えるアセンブリ命令はx86/x64
では存在しないので。
#pragma unmanaged
inline void fpu_getcw(unsigned short *pCW) {
__asm{
mov edx,pCW
fnstcw [edx];
}
}
#pragma managed
218デフォルトの名無しさん
2018/09/16(日) 14:17:40.34ID:haV9TZ8e あ、後、インライン・アセンブラで実験する場合は、関数名の inline は
「取った」方がいい。つまり、以下の方が安心:
#pragma unmanaged
void fpu_getcw(unsigned short *pCW) {
__asm{
mov edx,pCW
fnstcw [edx];
}
}
#pragma managed
「取った」方がいい。つまり、以下の方が安心:
#pragma unmanaged
void fpu_getcw(unsigned short *pCW) {
__asm{
mov edx,pCW
fnstcw [edx];
}
}
#pragma managed
219デフォルトの名無しさん
2018/09/16(日) 15:23:18.78ID:h8nMbN0G また基本に戻るが、>>192で/MDになってるので
/MTや/MTdでも発生するかしてみた方がいい
/MTや/MTdでも発生するかしてみた方がいい
220デフォルトの名無しさん
2018/09/16(日) 15:37:02.44ID:Q5j4SiHR .netはx87コンテキストをすべて保持しませんって分かったんだからもう十分。
win32かx64にすれば解決。そもそも問題になる仕様バグじゃない。
win32かx64にすれば解決。そもそも問題になる仕様バグじゃない。
221デフォルトの名無しさん
2018/09/16(日) 15:40:56.17ID:haV9TZ8e222デフォルトの名無しさん
2018/09/16(日) 15:42:36.82ID:haV9TZ8e223デフォルトの名無しさん
2018/09/16(日) 15:48:45.63ID:zL1WUjLu >>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.
> https://msdn.microsoft.com/en-us/library/e9b52ceh.aspx
とはいえ無理矢理やってみた。警告は出るがコンパイルは通る。
結果は、どこに置いても、Debug/Releaseでも、常に 0x9001f が読み出される。
ただし、これは上記の仕様からして、当てにならない。
それはどうやら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.
> https://msdn.microsoft.com/en-us/library/e9b52ceh.aspx
とはいえ無理矢理やってみた。警告は出るがコンパイルは通る。
結果は、どこに置いても、Debug/Releaseでも、常に 0x9001f が読み出される。
ただし、これは上記の仕様からして、当てにならない。
224デフォルトの名無しさん
2018/09/16(日) 15:49:44.99ID:zL1WUjLu >>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);
fpu_getcw(&fpu_cw_after);
Console::Write(String::Format("{0:D}, 0x{0:x4}\r\n",fpu_cw));
Console::Write(String::Format("{0:D}, 0x{0:x4}\r\n",fpu_cw_after));
読み出しと書き出し(Console::Write)を両方ともコメントアウトするのが面倒なので、
色々試す際、読み出しだけコメントアウトし、不定を表示させて脳内で省略していたのだが、
IDEから起動した場合はReleaseビルドであっても必ず0x0000が表示される事に気づいた。
上記『初期化していない』 fpu_cw を
Releaseビルドをコマンドプロンプトから実行: 不定
ReleaseビルドをIDEから実行: 常に0x0000
となる。
実行前にあらかじめスタック領域を0fillでもしているのか?
まあこれに当たっているのなら確実に俺のバグだし、これなら辻褄は合ってしまうのだが。
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);
fpu_getcw(&fpu_cw_after);
Console::Write(String::Format("{0:D}, 0x{0:x4}\r\n",fpu_cw));
Console::Write(String::Format("{0:D}, 0x{0:x4}\r\n",fpu_cw_after));
読み出しと書き出し(Console::Write)を両方ともコメントアウトするのが面倒なので、
色々試す際、読み出しだけコメントアウトし、不定を表示させて脳内で省略していたのだが、
IDEから起動した場合はReleaseビルドであっても必ず0x0000が表示される事に気づいた。
上記『初期化していない』 fpu_cw を
Releaseビルドをコマンドプロンプトから実行: 不定
ReleaseビルドをIDEから実行: 常に0x0000
となる。
実行前にあらかじめスタック領域を0fillでもしているのか?
まあこれに当たっているのなら確実に俺のバグだし、これなら辻褄は合ってしまうのだが。
225デフォルトの名無しさん
2018/09/16(日) 15:51:01.50ID:zL1WUjLu >>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]
}
}
00DA1546 5D pop ebp
00DA1547 C3 ret
fnstcwは D9 /7 で 7D なら [EBP+disp8] となり、 7D 08 は [EBP+08] となる。
つまりスタックポインタ+8の領域に書き戻せ、となる。
[ebp+0]は元のebpが入っているから、(pushしているので)
[ebp+4]にcallの戻り値アドレス
[ebp+8]にcw(第一引数)が入っていることになる。
これは正しいコードだ。
しかし再度試したが、確かに不安定だ。何故かは分からん。
inline取ってみても不安定のまま。
> そんなオペランドが使えるアセンブリ命令はx86/x64
> では存在しないので。
正直、/7の意味が分からないのだが、説明は
> /digit − 0 から7 までの数字で、命令のModR/M バイトがr/m(レジスタまたはメモリ)オペランドだけを使用することを示す。
> reg フィールドには、命令のオペコードを拡張する数字が入っている。(Intelのマニュアルより)
となっているのだが、これはどういう意味だ?
ModR/Mバイトが全部使えるとすると [ebp+disp8]出来ることになる。そしてそのコードは出ている。
ただし、動作は怪しいのも事実。
ModR/Mの一部しか使えない、ということか?
なお、逆アセンブルでコードバイトを表示させて確かめることは出来る。
正しいコードは出ている。(ただし不安定)
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]
}
}
00DA1546 5D pop ebp
00DA1547 C3 ret
fnstcwは D9 /7 で 7D なら [EBP+disp8] となり、 7D 08 は [EBP+08] となる。
つまりスタックポインタ+8の領域に書き戻せ、となる。
[ebp+0]は元のebpが入っているから、(pushしているので)
[ebp+4]にcallの戻り値アドレス
[ebp+8]にcw(第一引数)が入っていることになる。
これは正しいコードだ。
しかし再度試したが、確かに不安定だ。何故かは分からん。
inline取ってみても不安定のまま。
> そんなオペランドが使えるアセンブリ命令はx86/x64
> では存在しないので。
正直、/7の意味が分からないのだが、説明は
> /digit − 0 から7 までの数字で、命令のModR/M バイトがr/m(レジスタまたはメモリ)オペランドだけを使用することを示す。
> reg フィールドには、命令のオペコードを拡張する数字が入っている。(Intelのマニュアルより)
となっているのだが、これはどういう意味だ?
ModR/Mバイトが全部使えるとすると [ebp+disp8]出来ることになる。そしてそのコードは出ている。
ただし、動作は怪しいのも事実。
ModR/Mの一部しか使えない、ということか?
226デフォルトの名無しさん
2018/09/16(日) 15:51:25.16ID: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] だ。
理由は分からんがこちらだと安定しているので、結果としてはこのやり方が正しい。
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] だ。
理由は分からんがこちらだと安定しているので、結果としてはこのやり方が正しい。
227デフォルトの名無しさん
2018/09/16(日) 16:02:47.64ID:haV9TZ8e >>225
をを。やはり、ある意味ではVCが間違ったアセンブリコードを出していたよ。
それだと、
fnstcw [EBP+08]
という意味になってしまって、
fnstcw pCW
の意味になっている。つまり:
pCW = control_word;
あなたが、やりたいのは、
*pCW = control_word;
だったのだから、アセンブリ・コードが間違ってる。
あなたが指示したのは、
fnstcw [pCW]
だった。実際に生成されたコードは、
fnstcw pCW
だった。
VC のインラインアセンブラは、エラーも出さずに間違ったコードを
出すことが証明された。
これと、精度が不安定な問題とは全く別ではあるけれど。
をを。やはり、ある意味ではVCが間違ったアセンブリコードを出していたよ。
それだと、
fnstcw [EBP+08]
という意味になってしまって、
fnstcw pCW
の意味になっている。つまり:
pCW = control_word;
あなたが、やりたいのは、
*pCW = control_word;
だったのだから、アセンブリ・コードが間違ってる。
あなたが指示したのは、
fnstcw [pCW]
だった。実際に生成されたコードは、
fnstcw pCW
だった。
VC のインラインアセンブラは、エラーも出さずに間違ったコードを
出すことが証明された。
これと、精度が不安定な問題とは全く別ではあるけれど。
228デフォルトの名無しさん
2018/09/16(日) 16:06:05.39ID:zL1WUjLu すまん、間違いの修正
>>224
× > どうやらこれが原因の可能性が出てきた。(はっきり言って俺のバグだが)
× > まあこれに当たっているのなら確実に俺のバグだし、これなら辻褄は合ってしまうのだが。
今回は俺はあくまで俺の本番コードのデバッグを念頭に置いていて、この発言だった。
ただし>>191の再現コードで『不定スタック領域』を掴んでいるわけもなく、
一応IDE起動とコマンドプロンプト起動での挙動の違いを再現出来ているわけだから、
これだけが問題ではないのも事実だ。
俺にとっては一つ新しい知見として、
・IDEから起動した場合、スタックが初期化されるっぽい
ということが分かった。とはいえOSは0fillしてから各プロセスにメモリを与えるので、実際は、
・コマンドプロンプト起動ならmain前に設定した続きでそのまま実行、
・IDE起動ならmain前に色々やって0fillして実行、
或いはmain前に色々やることが多く、スタックが進み、(例えばデバッガをアタッチする為)
結果的にOSが初期化済みの領域から始動
となって違いが発生するというところか。
>>224
× > どうやらこれが原因の可能性が出てきた。(はっきり言って俺のバグだが)
× > まあこれに当たっているのなら確実に俺のバグだし、これなら辻褄は合ってしまうのだが。
今回は俺はあくまで俺の本番コードのデバッグを念頭に置いていて、この発言だった。
ただし>>191の再現コードで『不定スタック領域』を掴んでいるわけもなく、
一応IDE起動とコマンドプロンプト起動での挙動の違いを再現出来ているわけだから、
これだけが問題ではないのも事実だ。
俺にとっては一つ新しい知見として、
・IDEから起動した場合、スタックが初期化されるっぽい
ということが分かった。とはいえOSは0fillしてから各プロセスにメモリを与えるので、実際は、
・コマンドプロンプト起動ならmain前に設定した続きでそのまま実行、
・IDE起動ならmain前に色々やって0fillして実行、
或いはmain前に色々やることが多く、スタックが進み、(例えばデバッガをアタッチする為)
結果的にOSが初期化済みの領域から始動
となって違いが発生するというところか。
■ このスレッドは過去ログ倉庫に格納されています
ニュース
- バリ島で男子生徒ら集団万引きか、防犯カメラ映像が拡散 京都の大谷中学・高校が「窃盗行為」謝罪★4 [七波羅探題★]
- 中国軍機レーダー照射、トランプ氏沈黙突く 試される日本外交 [蚤の市★]
- 【地震】青森県で震度6強 長周期地震動も 津波注意報すべて解除 ★7 [ぐれ★] [ぐれ★]
- 【広島】「万引きした人を追跡」コンビニ店員の男性(46)を果物ナイフで刺したか 中国籍の少年(17)を殺人未遂容疑で現行犯逮捕 [ぐれ★]
- トランプ大統領 エヌビディア製AI半導体の中国輸出許可 安全保障重視の方針転換 [蚤の市★]
- 【サッカー】58歳カズ「オファーが来ている」 J3福島と近日中にも交渉 早ければ年内にも決断 [征夷大将軍★]
- 【悲報】高市早苗の擬人化がXで大バズりwwwwwwwwwwww [455031798]
- 高市が早くあの発言を撤回しないと、中国からもっと大きな制裁が飛んでくるぞ [805596214]
- 【動画】ファッションモデルまんこ、裸でランウェイを歩く。これがファッションだと言われて [749674962]
- 【画像】髙市さん「無職のシンママ支援を手厚くするため、世帯年収900万円以上の控除をカットします🙂」 [881878332]
- 早大名誉教授「高市内閣の高支持率はデータ操作か、支持している日本人がアホなのか」👈核心を突いてしまう [868050967]
- こんぺこ!こんぺこ!こんぺこ!🐰🏡
