制作日記

こういうの作った方が、逃げにくいじゃない

累乗フリーズ

http://oki6761.blog23.fc2.com/blog-entry-1753.html

これは無限ループしてるね
累乗計算中のループ判定でミスってるのが原因

mugenでの累乗の計算方法は下記記事参照
整数での**の計算
とりあえず、累乗は上位桁から順番に一桁ずつ計算していってるっていう想定
(実際にはバグってて下位桁から計算してるけど、今回の話は計算結果は関係ないので気にしないでおk)

で、問題個所(ループ)のアセンブラ

00407CF3 8BC8 MOV ECX,EAX
00407CF5 BD 01000000 MOV EBP,1
00407CFA 0FAFC1 IMUL EAX,ECX
00407CFD 8D4A FF LEA ECX,DWORD PTR DS:[EDX-1]
00407D00 D3E5 SHL EBP,CL
00407D02 85EF TEST EDI,EBP
00407D04 74 03 JE SHORT winmugen.00407D09
00407D06 0FAFC3 IMUL EAX,EBX
00407D09 42 INC EDX
00407D0A BD 01000000 MOV EBP,1
00407D0F 8BCA MOV ECX,EDX
00407D11 D3E5 SHL EBP,CL
00407D13 3BFD CMP EDI,EBP
00407D15 ^7D DC JGE SHORT winmugen.00407CF3


重要なのは最後の2命令
00407D13 3BFD CMP EDI,EBP
 EDI:累乗する値(**の右オペランド)と
 EBP:次に計算する桁だけ立っている値の比較
 ここまでで3(11)乗してたら次は3桁目なので100
 4(100)~7(111)乗してたら次は4桁目なので1000になる

00407D15 ^7D DC JGE SHORT winmugen.00407CF3
 上の比較結果について、EDIの方が大きいか同じであれば計算途中なので、ループの最初に戻る
 小さければ計算終了なので、次の命令へ進む

問題なのは、この比較が正負を考慮してる点
上の比較において、EBPの最大値は2進数で上から2桁目だけ立ってる値
0x40000000=1073741824になる
次に比較する値は2進数の最上位桁だけ立ってる値
0x80000000=-2147483648だから、最小値になる
さらに次に比較する値は、最下位桁だけ立ってる値になる
そんでまた2桁目、3桁目と増えて行っての繰り返し

つまり、上から2桁目が立っていて、且つ最上位桁が立っていない値はこの判定を抜けられない
よって、無限ループに陥る

これはよくあるオバフロでの判定ミスだねー
どうせ**は両オペランドが整数且つ、右オペランドが正数のときにしか使わない処理なんだから、unsignedにしとけと
割とよくあるミスだし、あんまりバカに出来ないんだけどね

コメントの投稿

非公開コメント

No title

無限ループなのは警告ウィンドウ出なかったから
永久処理として判別できたけど原因さっぱりだったからなぁ

まさか内部処理のミスとは…

No title

これはさすがに内部処理知ってないと、わからないですね

MUGENの謎仕様とかも、案外こういう些細なミスが原因かも?
プロフィール

Author:drab
霊夢改変キャラ
「12 3 ! {V} [_]」
公開中
L霊夢でもl_reimuでも好きなように読んでください

最新記事
最新コメント
月別アーカイブ
カテゴリ
検索フォーム
RSSリンクの表示
リンク