2017-04-23 13 views
5

は、私は私の友人は彼のプログラムをデバッグを支援し、私たちもここで発生する問題にそれを絞り込む:TASM 4.1でそれを組み立てた後DOSBox上の8086アセンブリ:idiv命令のバグ?

.MODEL small 
.STACK 16 
.CODE 
start: 
    mov ax, 044c0h 
    mov bl, 85 
    idiv bl 
exit: 
    mov ax, 4c00h 
    int 21h 

end start 

、およびDOSBoxを0.74上でそれを実行している、それがに入ります無限ループターボデバッガでそれを調べると、何らかの理由でcsipレジスタが変更され、2つの一見無作為な命令がそれらを復帰してidiv行を指すように復帰させた後、再び無限に実行することがわかります。

誰でもこれについて説明しますか?

+3

あなたの部門の署名商が8ビット・レジスタ(_AL_)に収まらない可能性があるので:すべてこれにより

は心の中であなたの部門コードは、16ビットの除数を取るように調整することができ算術オーバーフローが発生しています。 r16/r8 [IDIV](http://www.felixcloutier.com/x86/IDIV.html)の商の範囲は-128から+127です。あなたの部門は207の商を得ます。 –

+1

@MichaelPetch:そうです。私はちょうど答えとして提出しようとしていたが、あなたは私を打つ! – wallyk

+1

これはINT 00h割り込みハンドラになります。ちょっと私には驚くべきことですが、壊れたコードにジャンプして、無限ループを引き起こします。私はそれがアプリケーションを終了する、エラーメッセージを印刷する、またはもう少し明白な何かを期待していただろう。あなたはこれによって混乱するのは何日もの間に二人目です。 –

答えて

7

この質問は、他の部門関連の障害のバリエーションです。


あなたのデバッガがにジャンプするようだどうやらランダムコードは、算術演算例外ハンドラ(ゼロ除算なども同じもの)です。あなたのコードにDivision Overflowが発生しています。あなたは16ビット/ 8ビットIDIVをやっています。ドキュメントから:

AXはr/m8で符号分割し、結果はAL:←Quotient、AH←Remainに格納されます。

enter image description here

ます(あなたのケースBLに)8ビットの除数と分割するための商の範囲は-128~ + 127であることがわかります。 044c0h IDIV 85は207(10進数)です。 207は符号付き8ビットレジスタに収まらないため、除算のオーバーフローと予期しない問題の原因が発生します。

これを解決するには、最大16ビットの除数に移動できます。だから、除算をBX(16ビットレジスタ)に置くことができます。それはmov bx, 85です。残念ながら、それほど単純ではありません。 16ビットの除数を使用する場合、プロセッサは被除数がDXの上位16ビットで32ビットであり、下位16ビットがAXであるとみなします。

符号付き除算DX:AXはr/m16で、結果はAX←Quotient、DX←残りに格納されます。

この問題を解決するには、AXの16ビット値を符号拡張する必要があります。これは、命令をAXに配置した後に使用する必要があるため、単純です。命令セットリファレンスから

DX:AX←AXの符号拡張。効果的

AXの最上位ビット(MSB)が0 DXある場合、MSBは、次に1 DXが0FFFFH(いずれかに設定されたすべてのビット)になる場合は0となるであろう。数字の符号ビットはMSBです。そう

mov ax, 044c0h 
cwd    ; Sign extend AX into DX (DX:AX = 32-bit dividend) 
mov bx, 85   ; Divisor is 85 
idiv bx   ; Signed divide of DX:AX by BX 
関連する問題