2017-04-20 1 views
2

그래서 나는 this exact problem을 가졌습니다.DIV 명령이 임의의 위치로 점프하고 있습니까?

주어진 해결책은 DX인데 제 경우는 이미 있습니다!
내 프로그램은 단순히 16 비트 숫자를 8 비트 숫자로 나눕니다.

내 코드는 다음과 같습니다

data segment 
num1 dw 0204h 
num2 db 02h 
quotient db ? 
remainder db ? 
data ends 
code segment 
assume cs:code,ds:data 
start: mov ax,data 
mov ds,ax 
mov ax,num1 
div num2 
mov quotient,al 
mov remainder,ah 
mov ah,4ch 
int 21h 
code ends 
end start 

모든 솔루션?

+4

사용중인 [DIV] (http://www.felixcloutier.com/x86/DIV.html) 명령의 형식은 다음과 같습니다. 'AX는 r/m8로 나눕니다. 결과는 AL에 저장됩니다. ← Quotient, AH ← 나머지 .' 이것은 MASM/TASM이 'num2 db 02h'정의 때문에 8 비트 메모리 피연산자 였기 때문에 조용히 num1로 간주했기 때문입니다. 이 경우 _DX_는 사용되지 않습니다 (따라서 값은 중요하지 않습니다). 틀린 것은 0x204를 2로 나눈 값이 0x102입니다. 0x102는 바이트 (바이트는 0x00에서 0xff)에 맞지 않으므로 몫이 8 바이트 레지스터 (_AL_)에 맞지 않으므로 나누기 예외 (오버플로)가 발생합니다. –

+1

이것을 작동 시키려면 16 비트 레지스터를 0으로하고, 그 레지스터의 하위 8 비트에 mov num2를 넣고, _DX_를 0으로 설정하고, 16 비트 나눗셈을합니다 (8이 아닌). 첫 번째 코멘트의 링크에서 지시 형식은'Unsigned Divide DX : AX를 r/m16으로 나눠서 결과를 AX ← Quotient, DX ← Remainder '에 저장합니다. 분할이 완료되면 0x102는 _AX_ –

답변

3

공백을 사용하여 어셈블리 코드를 분리해야 할 필요가 있습니다. 이 코드는 무언가를하고 있습니다 매우 (하나씩 다른 숫자로 나눕니다), 아직 그것은 매우 읽기가 어렵습니다. 그것은 분명히 사실이 아닙니다 : 간단한 코드는 읽기 쉽습니다! 왜 읽는 것이 어렵습니까? 당신은 당신의 상용구 코드가 실제로 나누기 연산을 수행하는 코드와 얽혀 있기 때문에, 제 눈은 그냥 유약이 나옵니다. 나는 상용구에서 중요한 비트를 찾아 낼 수 없다. 공백은 무료입니다. 두려워하지 마라. 당신의 어셈블러는 상관 없습니다. 이 같은

쓰기를 : 이제

data segment 

num1  dw 0204h 
num2  db 02h 
quotient db ? 
remainder db ? 

data ends 


code segment 
assume cs:code, ds:data 

start: 
    ; Initialize Data Segment (DS) 
    mov ax, data 
    mov ds, ax 

    ; Do the division and save the results 
    mov ax, num1 
    div num2 
    mov quotient, al 
    mov remainder, ah 

    ; Terminate process 
    ; (Note that you should also be setting AL to a result code here!) 
    mov ah, 4ch 
    int 21h 
end start 

code ends 

, 무슨 무슨 더 명확 실질적 아닌가요? 또한, MASM/TASM을 사용하면 실수로 벗어날 수 있지만 나쁜 습관에 빠지지 마십시오. 그것은 코드를 읽을 수 없게 만들고 잘못된 결과를 얻는 또 다른 방법입니다./ 그 심볼의 오프셋 한 가지 방법은 주소를 사용하는 것입니다, 다른 방법은 내용/심볼의 값을 사용하는 것입니다 :이 코드에서 기호를 사용할 수있는 두 가지 방법이 있습니다. MASM/TASM에서 주소/오프셋을 원하면 OFFSET 키워드를 사용해야합니다. 내용/값을 사용할 때 기술적으로는 필요하지 않지만 실제로는 이어야합니다.은 역 참조가되고 있음을 나타 내기 위해 기호를 괄호로 묶습니다. 대신 즉, :

mov ax, num1 

쓰기를 : 내 가슴 떨어져 그 호언 장담으로

mov ax, [num1] 

은의 당신의 코드에 문제가 있는지 살펴 보자. Michael Petch는 이미 MASM/TASM이 "내가 쓰는 것이 아니라 내 뜻대로"스타일이 당신에게 어떤 호의를 베풀지 않는 또 다른 사례라고 지적했습니다. DIV 명령어와 함께 8 비트 피연산자 (num2)를 사용했기 때문에 8 비트 나누기를 수행하고 있습니다.

AX/[num2] 

AL의 몫과 AH의 나머지 : 즉, 실제로 일을 의미합니다. 몫이 8 비트보다 크면 AL에 적합하지 않으며 부분이 오버플로됩니다.

해결 방법은 16 비트 나눗셈을 수행하는 것입니다.이 경우 몫은 AX에 있고 나머지는 DX에 배치됩니다.

는 것을 얻을 thusly 히 코드를 작성하려면

mov ax, [num1]  ; AX = [num1] 
xor dx, dx   ; DX = 0 

xor bx, bx   ; BX = 0 
mov bl, [num2]  ; BL = [num2], BH = 0 

div bx    ; DX:AX/BX 

mov [quotient], ax 
mov [remainder], dx 

(이 또한 BX을 건드리지이기 때문에, 당신은 상단에 push bx과 끝에 pop bx을 수행하여 원래 값을 저장 할 수 있습니다.)


documentation for the DIV instruction는 8 비트, 16 비트 및 32 비트 사업부가 작동하는 방법을 요약하는 편리한 테이블을 포함

Operand Size  | Dividend | Divisor | Quotient | Remainder | Maximum Quotient 
-------------------------------------------------------------------------------------- 
Word/byte   | AX  | r/m8  | AL  | AH  | 2^8 - 1 
Doubleword/word  | DX:AX  | r/m16  | AX  | DX  | 2^16 - 1 
Quadword/doubleword | EDX:EAX | r/m32  | EAX  | EDX  | 2^32 - 1 

"제수"는 DIV 명령어의 유일한 피연산자입니다. "배당금"은 함축적입니다. "r/m"은 레지스터 또는 메모리 피연산자를 의미합니다.

+0

에 있어야합니다. * quotient * 및 * remainder *에 대한 정의가'db?'에서'dw? '로 변경되어야 함을 나타내는 것이 좋습니다. 제안 된 솔루션은 단어를 작성합니다! –

관련 문제