비부호수 나눗셈 32비트 모드에서 DIV 명령어는 8비트, 16비트, 32비트 비부호수를 처리하며 결과는 몫과 나머지 형태로 나타납니다. 구문은 다음과 같습니다:
DIV 8비트 레지스터 또는 메모리 DIV 16비트 레지스터 또는 메모리 DIV 32비트 레지스터 또는 메모리
| 피나눗셈수 | 나눗셈수 | 몫 | 나머지 |
|---|---|---|---|
| AX | reg/mem8 | AL | AH |
| DX:AX | reg/mem16 | AX | DX |
| EDX:EAX | reg/mem32 | EAX | EDX |
표에 따르면, 8비트 연산 시 피나눗셈수는 16비트, 16비트 연산 시 32비트(두 레지스터 조합)여야 합니다. 이는 피나눗셈수가 항상 나눗셈수보다 크다는 것을 의미합니다.
다음 코드는 8비트 비부호수 나눗셈(83h/2)을 수행하며, 결과는 41h 몫과 1 나머지입니다:
mov bx, 0083h ; 피나눗셈수
mov cl, 2 ; 나눗셈수
div cl ; AL = 41h, AH = 01h
16비트 비부호수 나눗셈(8003h/100h) 예시입니다. 나눗셈 수행 전 DX를 0으로 초기화해야 합니다:
mov dx, 0 ; 피나눗셈수 상위 16비트 초기화
mov ax, 8003h ; 피나눗셈수 하위 16비트
mov si, 100h ; 나눗셈수
div si ; AX = 0080h, DX = 0003h
32비트 비부호수 나눗셈 예제입니다:
.data
dividend QWORD 0000000800300020h
divisor DWORD 00000100h
.code
mov edx, DWORD PTR dividend + 4 ; 상위 4바이트
mov eax, DWORD PTR dividend ; 하위 4바이트
div divisor ; EAX = 08003000h, EDX = 00000020h
64비트 나눗셈 예제에서는 RAX에 결과(0108000000003330h)가 저장됩니다:
.data
dividend_hi QWORD 0000000000000108h
dividend_lo QWORD 0000000033300020h
divisor QWORD 0000000000000001h
.code
mov rdx, dividend_hi
mov rax, dividend_lo
div divisor ; RAX = 0108000000003330
; RDX = 0000000000000020
부호수 나눗셈 부호수 나눗셈은 비부호수와 유사하지만, 피나눗셈수를 부호 확장해야 합니다. 부호 확장 명령어는 다음과 같습니다:
| 명령어 | 전체명 | 설명 |
|---|---|---|
| cbw | Convert Byte to Word | AL의 부호비트를 AH로 확장 |
| cwd | Convert Word to Doubleword | AX의 부호비트를 DX로 확장 |
| cdq | Convert Doubleword to Quadword | EAX의 부호비트를 EDX로 확장 |
.DATA
byte_val SBYTE -101
.CODE
mov al, byte_val ; AL = 9Bh
cbw ; AX = FF9Bh
cbw 명령어는 AL의 최상위 비트를 AH로 채우며, AH 기존 내용은 덮어쓰게 됩니다.
부호수 나눗셈 전 부호 확장이 필수적입니다. 다음 예제에서 DX:AX가 0000:FF9B로 표시되지만, 이는 65435로 해석되어 -101이 아닌 값을 반환합니다:
.386
.model flat,stdcall
.stack 4096
ExitProcess proto,dwExitCode:dword
INCLUDE Irvine32.inc
.data
wordval sword -101
.code
main PROC
nop
mov dx, 0
mov ax, wordval
mov bx, 2
idiv bx ; 65435/2=32717, 나머지 1
invoke ExitProcess,0
main ENDP
end main
cbw 사용 시:
.data
wordval sword -101
.code
main PROC
nop
mov dx, 0
mov ax, wordval
cwd ; DX:AX=FFFF:FF9B로 확장
mov bx, 2
idiv bx
invoke ExitProcess,0
main ENDP
나눗셈 오버플로우 나눗셈 결과가 저장 공간에 들어가지 않으면 오버플로우가 발생합니다. 이는 프로세서 예외를 발생시키고 프로그램 실행을 중단합니다. AL에 100h을 저장하려는 시도는 오버플로우를 유발합니다.
0으로 나누는 경우도 동일한 오류가 발생합니다. 이를 방지하기 위해 CPU 조건 분기 명령을 사용해 나눗셈수를 0인지 확인할 수 있습니다:
.code
main PROC
nop
mov bx, 20
mov cl, 0
cmp cl, 0
je NoDivideZero
div cl
NoDivideZero:
invoke ExitProcess,0
main ENDP