2017-04-23 1 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 

, 그리고 도스 박스 0.74에 실행, 그것은에 간다 무한 루프. 터보 디버거로 검사 할 때 어떤 이유로 csip 레지스터를 수정 한 idiv 명령어 다음에 발생하는 것을 볼 수 있으며 두 개의 겉보기 임의 명령어는 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

이 질문은 다른 부서 관련 오류에 대한 변형입니다. x86 tag wiki 몇 가지 추가 링크가 있습니다 :


디버거가 점프듯한 분명히 임의의 코드는 산술 예외 핸들러 (0으로 나누기로 같은 하나)입니다. 현재 코드에 Division Overflow이 발생하고 있습니다. 당신은 16 비트/8 비트 IDIV하고 있습니다. 문서에서 :

부호있는 나눗셈 AX : r/m8에 의한 결과 : AL ← 지수, AH ← 나머지.

enter image description here

당신은 지수의 범위는 127 -128입니다 (귀하의 경우 BL에서) 8 비트 제수와 부문에 대한 것을 알 수

. 044c0h IDIV 85는 207 (십진수)입니다. 207은 부호가있는 8 비트 레지스터에 맞지 않으므로 나눗셈 오버 플로우와 예기치 않은 문제의 원인을 얻을 수 있습니다.

이 문제를 해결하기 위해 최대 16 비트 제수로 이동할 수 있습니다. 그래서 당신은 약자를 BX (16 비트 레지스터)에 배치 할 수 있습니다. 그것은 mov bx, 85입니다. 불행히도 그렇게 간단하지 않습니다. 16 비트 제수를 사용하는 경우 프로세서는 배당량이 DX이고 16 비트가 16 비트 인 32 비트가 AX이라고 가정합니다.

부호 분할 DX : AX는 r/m16에 따라 결과가 AX ← Quotient, DX ← 나머지에 저장됩니다.

이 문제를 해결하려면 AX의 16 비트 값을 확장해야합니다. 이 값을 AX에 배치 한 후에 명령어를 사용해야하기 때문에 간단합니다.명령어 세트 참조에서

DX : AX ← AX의 부호 확장.

AX의 최상위 비트 (MSB)가 MSB 다음 1 DX는 (하나에 설정된 모든 비트) 0ffffh가 될 경우 0이 될 것이다 0 DX가 효과적으로 경우. 숫자의 부호 비트는 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 
관련 문제