📄 div.asm
字号:
********************************************************************* Copyright (C) 1991, GMD. All rights reserved. ** ** ** NOTICE ** ** Acquisition, use, and distribution of this module ** and related materials are subject to restrictions ** mentioned in each volume of the documentation. ** ********************************************************************** Datei : div.s* Datum : 6.6.1988* Inhalt: Dividieren zweier langer Zahlen** a0 : Adresse des Dividenten(Dt) und Adresse des divident-Felds (dtF)* a1 : Adresse des Divisors (Dr)* a2 : Adresse des divident-Felds* a3 : Adresse des quotient-Felds (qF)* a4 : Adresse des Testfelds (tF)* a5 : Adresse des Quotienten (Quot)* a6 : Adresse des Rests (R)* d0 : Returncode (Standard) und Laenge Divident und Schleifenzaehler* fuer die Hauptschleife (Anzahl Divisionsschritte)* d1 : Laenge des Divisors (OP1)* d2 : Hilfsregister* d3 : Naeherungswert fuer q (q^)* d4 : Hilfsregister* d5 : Hilfsregister* d6 : niederwertiger Teil des Dividenten, Quotient des Ergebnisses* d7 : hoeherwertiger Teil des Dividenten, Rest des Ergebnisses** 4(sp) : Divident* 8(sp) : Divisor* 12(sp) : Quotient* 16(sp) : Rest** .lcomm quotient,4*20 * Quotientfeld-Laenge: 4*Feldlaenge* .lcomm divident,2*(4*20)+4* .lcomm testfeld,2*(4*20)* .text MODULE _div cpu 68020 entry.p _div DATAdada equ *_div lea dada,a0 jmp.l div$proc extern.p printfa$printf ac printf extern.f _shifta$shift ac _shiftquotient: ds.l 4*20divident: ds.l 2*(4*20)+4testfeld: ds.l 2*(4*20) PROCdiv$proc: movem.l a0/a1/a2/a3/a4/a5/a6/d1/d2/d3/d4/d5/d6/d7,-(sp) move.l a0,db movem.l null,a0/a1/a2/a3/a4/d0/d1/d2/d3/d4/d5/d6/d7** Adressen in Register laden* move.l 64(sp),a1 * a1->Adresse Divisor move.l 0(a1),d1 * d1 = L(Divisor),a1->1.Zi Div.or cmp.l #0,d1 * Divisor = 0 ? bne noerror * nein => weiter bei noerror** Sonderfall : Division durch Null* move.l #-1,d0 * RC = -1 bra return * Ruecksprung** Sonderfall: Divident < Divisor*noerror: move.l 60(sp),a0 * a0->Adresse Divident move.l 0(a0),d0 * d0 = L(Divident) cmp.l d0,d1 * Divident laenger Divisor ? bls nottrivial * ja => "echte" Division move.l 68(sp),a3 * a5->Laengenfeld Quotient move.l #0,0(a3) * Quotient = 0 move.l 72(sp),a4 * a6->Laengenfeld Rest cmp.l #0,d0 * Divident = 0 ? bne nodiv * nein -> Divident=Rest,Quot=0 move.l #0,0(a4) * Rest = 0 bra returnnodiv: move.l d0,(a4)+ * Laenge eintr., a6->1.Zi Quot addq.l #4,a0 * a0->1.Zi Divident subq.l #1,d0 * d0 Schleifenzaehler, Schlei-* * fenende bei -1looprestonly: move.l (a0)+,(a4)+ * uebertragen dbra d0,looprestonly eor.l d0,d0 * RC = 0 bra return ** Sonderfall : Divisor hat nur eine Ziffer*nottrivial: cmp.l #1,d1 * L(Divisor) = 1 ? bne notshort * nein => echte Division move.l 4(a1),d5 * d5=die einzige Ziffer von Dr move.l 68(sp),a3 * a5->Laengenfeld Quotient move.l 72(sp),a4 * a6->Laengenfeld Rest move.l d0,(a3)+ * Laenge vor.laeufig eintragen,* * a5->1.Zi Quotient move.l #4,d4 mulu.l d0,d4 * d4=vor.laeufig L(Quotient) add.l d4,a3 * a5->vor fuehrende Zi Quotient add.l d4,a0 addq.l #4,a0 * a0->vor fuehrende Zi Divident subq.l #1,d0 * d0 Schleifenzaehler, Schlei-* * fenende bei -1 eor.l d7,d7 * loeschenloop_sdiv:move.l -(a0),d6 * d6 = hoechste Zi Divident divu.l d5,d7:d6 * d6d7,d5,d6=Quotient,d7=Rest move.l d6,-(a3) * Quotient eintragen dbra d0,loop_sdiv * Divident fertig?nein=>Schleife move.l -(a3),d4 * d4=vor.laeufige Laenge Quotient cmp.l #0,0(a3,d4.l*4) * fuehrende Zi Quotient = 0 ? bne nocorr1 * nein => Laenge Quotient okay subq.l #1,0(a3) * ja=>Laenge Quotient 1 kuerzernocorr1: cmp.l #0,d7 * Gibt es einen Rest ? bne notzero * ja => eintragen move.l #0,0(a4) * nein => Rest = 0 eintragen eor.l d0,d0 * RC = 0 bra returnnotzero: move.l #1,(a4)+ * Laenge Rest = 1 move.l d7,0(a4) * Rest eintragen eor.l d0,d0 * RC = 0 bra return** Echte Division; Zunaechst uebertragen des Dividenten in das* Arbeitsfeld*notshort: lea divident,a2 * a2->L-Feld div-Feld move.l d0,d2 * d2 Schleifenzaehlerloop_trfield: move.l (a0)+,(a2)+ * uebertragen dbra d2,loop_trfield * fertig ? nein => Schleife** Erweitern von divident-Feld und Divisor* zuerst : v1 > b/2 ?* move.l 0(a1,d1.l*4),d5 * d5 = fuehrende Zi Divisor=v1 cmp.l #0,d5 * v1>b/2 ?(hoechstwertiges Bit* * muss 1 sein!) bpl shift1 * nein => shiften** kein Shift = Erweitern noetig, daher Shiftfaktor = 0 und die beiden* ersten Ziffern vom Divisor merken* move.l #0,-(sp) * Shiftfaktor auf Stack merken move.l d5,-(sp) * v1 auf Stack merken move.l -4(a1,d1.l*4),-(sp) * v2 auf Stack merken bra startdiv * jetzt dividierenshift1: eor.l d4,d4 * d4 loeschenloopshift:addq.l #1,d4 * d4 Shiftfaktor lsl.l #1,d5 * um 1 nach links shiften cmp.l #0,d5 * v1 jetzt okay ? bpl loopshift * nein => weiter shiften move.l d4,-(sp) * ja => Shiftfaktor auf Stack* * merken pea divident * Adresse div-Feld und Shiftfak- move.l d4,-(sp) * tor fuer den Aufruf des Shift- pea divident * programms uebergeben move.l a$shift,a0 jsr (a0) * Programm aufrufen move.l a1,0(sp) * Dasselbe fuer den Divisor move.l a1,8(sp) move.l a$shift,a0 jsr (a0) * Programm aufrufen add.l #$0c,a7 * SP zuruecksetzen: sp=sp+12
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -