| FAQ der Newsgroup de.comp.lang.assembler (d.c.l.a.) | |||
|
Wie dividiere ich mit großen Zahlen (zwei Register)?
1. Fall: Der Dividend passt nicht in ein Register. Der Divisor und die Ergebnisse der Division (Quotient, Rest) passen jedoch vollständig in je ein Register. Da der Dividend bei DIV immer aus EDX:EAX gebildet wird, ergibt sich kein Problem:
Aufgabe: 353821814888 : 1000 = 353821814 Rest 888
= 0x52616C7068 / 0x03E8 = 0x1516E476 Rest 0x378
Assembler:
mov edx, 52h ; Dividend: EDX:EAX
mov eax, 616C7068h
mov ebx, 1000 ; Divisor
div ebx
Danach befinden sich in EAX der Quotient und in EDX der Rest
2. Fall: Der Quotient wird nicht in ein 32-Bit-Register passen:
Aufgabe: 353821814888 : 10 = 35382181488 Rest 8
= 0x52616C7068 / 0x0A = 0x083CF13E70 Rest 0x08
Assembler:
mov edx, 52h ; Hi-Dividend:Lo-Dividend: EDX:EAX
mov eax, 616C7068h
mov ebx, 10 ; Divisor
mov ecx, eax ; Lo-Dividend sichern
mov eax, edx ; Hi-Dividend wird einziger Dividend
xor edx, edx
div ebx ; Hi-Dividend / 100
xchg eax, ecx ; EAX wird Hi-Quotient, altes EAX zurück, EDX bleibt
div ebx ; Quotient wird Lo-Quotient, EDX: Rest
Danach befindet sich der Quotient in ECX:EAX und der Rest in EDX.
3. Fall: Divisor und/oder Rest passen nicht in ein Register
Aufgabe: 353821814888 : 10000000000 = 35 Rest 3821814888
= 0x52616C0000 / 0x02540BE400 = 0x23 Rest 0xE3CC4468
Assembler:
push ebp ; vorsichtshalber
mov edx, 52h ; Dividend: EDX:EAX
mov eax, 616C7068h
mov ebp, 02h ; Divisor: EBP:EBX
mov ebx, 540BE400h
push 0 ; Quotient: [esp]
push 0
xor esi, esi ; Zahl: EDI:ESI
xor edi, edi
mov ecx, 64 ; 64 Schleifendurchgänge: for (cx=64; cx>0; cx--)
Schleife:
shl eax, 1 ; linkes Bit von Dividend nach Zahl
rcl edx, 1
rcl esi, 1
rcl edi, 1
cmp ebp, edi ; Divisor (EBP:EBX) und Zahl (EDI:ESI) vergleichen
je S1 ; ebp = edi
jc S2 ; ebp < edi
jmp Sprungmarke ; ebp > edi
S1:
cmp ebx, esi
ja Sprungmarke ; ebx > esi (CY=0 & ZF=0)
S2:
sub esi, ebx ; Zahl = Zahl-Divisor, Carry setzen
sbb edi, ebp
stc
Sprungmarke:
rcl dword ptr [esp], 1 ; Carry (0 oder 1) an Quotienten kleben.
rcl dword ptr [esp+4], 1
loop Schleife
pop eax
pop edx
pop ebp
Danach steht der Quotient in EDX:EAX und der Rest in EDI:ESI.
Die Vorgehensweise beim 3. Fall entspricht der "Division ohne DIV". Näheres beim entsprechenden FAQ-Artikel. Ralph 'rkhb' Bauer Aug 2008 | ||