もう少し考察してみました。
fname = dpath + dname_l1;
00401F32 lea edx,[esp+10h]
00401F36 push edx
00401F37 lea eax,[esp+0Ch]
00401F3B push eax
00401F3C lea ecx,[esp+1Ch]
00401F40 push ecx
00401F41 call ATL::operator+ (401D30h)
00401F46 add esp,0Ch
00401F49 push eax
00401F4A lea ecx,[esp+8]
00401F4E mov byte ptr [esp+34h],5
00401F53 call ATL::CSimpleStringT<char,0>::operator= (401B80h)
00401F58 mov eax,dword ptr [esp+14h]
00401F5C add eax,0FFFFFFF0h
00401F5F mov byte ptr [esp+30h],4
00401F64 lea edx,[eax+0Ch]
00401F67 or ecx,0FFFFFFFFh
00401F6A lock xadd dword ptr [edx],ecx
00401F6E dec ecx
00401F6F test ecx,ecx
00401F71 jg CTestDlg3Dlg::OnBnClickedButton1+0EBh (401F7Bh)
00401F73 mov ecx,dword ptr [eax]
00401F75 mov edx,dword ptr [ecx]
00401F77 push eax
00401F78 call dword ptr [edx+4]
00401F7B push esi
fsize = _byteswap_ulong(0xFFFFFFF0);
00401F7C mov esi,0FFFFFFF0h // (1) esi = 0x0fffffff0
file.Write(&fsize, sizeof(fsize));
00401F81 push 4
00401F83 lea eax,[esp+8]
00401F87 bswap esi // (2) ここでesi=0xf0ffffffになる。
00401F89 push eax
00401F8A lea ecx,[esp+24h]
00401F8E mov dword ptr [esp+0Ch],esi
00401F92 call CFile::Write (41D918h)
fname = dpath + dname_l2;
00401F97 lea ecx,[esp+10h]
00401F9B push ecx
00401F9C lea edx,[esp+10h]
00401FA0 push edx
00401FA1 lea eax,[esp+20h]
00401FA5 push eax
00401FA6 call ATL::operator+ (401D30h)
00401FAB add esp,0Ch
00401FAE push eax
00401FAF lea ecx,[esp+0Ch]
00401FB3 mov byte ptr [esp+38h],6
00401FB8 call ATL::CSimpleStringT<char,0>::operator= (401B80h)
00401FBD mov eax,dword ptr [esp+18h]
00401FC1 add eax,esi // (3) 本来は add eax,0FFFFFFF0h とすべきだが、
// esiが0x0fffffff0のままだと思ってesiを使い回して
しまった?
00401FC3 mov byte ptr [esp+34h],4
00401FC8 lea ecx,[eax+0Ch]
00401FCB or edx,0FFFFFFFFh
00401FCE lock xadd dword ptr [ecx],edx
00401FD2 dec edx
00401FD3 test edx,edx
00401FD5 jg CTestDlg3Dlg::OnBnClickedButton1+14Fh (401FDFh)
00401FD7 mov ecx,dword ptr [eax]
00401FD9 mov edx,dword ptr [ecx]
00401FDB push eax
00401FDC call dword ptr [edx+4]
今回はたまたま、_byteswap_ulong(0xFFFFFFF0); で 0xfffffff0 という値が
使用され、それとは無関係な CString::operator= でも 0xfffffff0 という
値を使用するため、それらを最適化しようとして間違った最適化がされて
しまったと考えられます。
試しに _byteswap_ulong() に0xfffffff0以外の値を与えると違ったアセンブリコード
が生成され、落ちずに正常に動きました。
誤記訂正
(誤)それとは無関係な CString::operator= でも 0xfffffff0 という
値を使用するため、
(正)それとは無関係な fname = dpath + dname_l2; でも 0xfffffff0 という
値を使用するため、
isshiさん解説ありがとうございます。
やはりコンパイラのバグでしたか・・・
今回の対応としては固定値の_byteswap_ulong(0xFFFFFFF0)を行わず
0xF0FFFFFFの代入に変更する事で現象を回避をする事が出来ました。
上記テストプログラムを変更して0xFFFFFFF0の値を変数に入れて
data = 0xFFFFFFF0;
fsize = _byteswap_ulong(data);
として呼び出しても現象が発生してしまう為
byteswap_ulongに0xFFFFFFF0の値が入るかもしれない処理の時は
下記の様に条件式で固定値の代入して回避しないと危ない様です。
if(data==0xFFFFFFF0) fsize = 0xF0FFFFFF;
else fsize = _byteswap_ulong(data);
開発環境が.net2003の方は_byteswap_ulongの扱いに注意が必要のようです。
同現象は.net2005/2008では発生しない様ですので修正済みの不具合のようです。
以上で問題解決とします。
皆さんありがとうございました。