📄 div.s
字号:
|********************************************************************|* 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|| sp@(4) : Divident| sp@(8) : Divisor| sp@(12) : Quotient| sp@(16) : Rest| .text .globl __div .extern _printf .extern __shift__div: moveml a0,a1,a2,a3,a4,a5,a6,d1,d2,d3,d4,d5,d6,d7,sp@- moveml null,a0,a1,a2,a3,a4,a5,a6,d0,d1,d2,d3,d4,d5,d6,d7|| Adressen in Register laden| movl sp@(64),a1 | a1->Adresse Divisor movl a1@(0),d1 | d1 = L(Divisor),a1->1.Zi Div.or cmpl #0,d1 | Divisor = 0 ? bne noerror | nein => weiter bei noerror|| Sonderfall : Division durch Null | movl #fehler,sp@- | Fehlermeldung jsr _printf addql #4,sp | Stack zuruecksetzen movl #-1,d0 | RC = -1 bra return | Ruecksprung|| Sonderfall: Divident < Divisor|noerror: movl sp@(60),a0 | a0->Adresse Divident movl a0@(0),d0 | d0 = L(Divident) cmpl d0,d1 | Divident laenger Divisor ? bls nottrivial | ja => "echte" Division movl sp@(68),a5 | a5->Laengenfeld Quotient movl #0,a5@(0) | Quotient = 0 movl sp@(72),a6 | a6->Laengenfeld Rest cmpl #0,d0 | Divident = 0 ? bne nodiv | nein -> Divident=Rest,Quot=0 movl #0,a6@(0) | Rest = 0 bra returnnodiv: movl d0,a6@+ | Laenge eintr., a6->1.Zi Quot addql #4,a0 | a0->1.Zi Divident subql #1,d0 | d0 Schleifenzaehler, Schlei- | fenende bei -1looprestonly: movl a0@+,a6@+ | uebertragen dbra d0,looprestonly eorl d0,d0 | RC = 0 bra return || Sonderfall : Divisor hat nur eine Ziffer|nottrivial: cmpl #1,d1 | L(Divisor) = 1 ? bne notshort | nein => echte Division movl a1@(4),d5 | d5=die einzige Ziffer von Dr movl sp@(68),a5 | a5->Laengenfeld Quotient movl sp@(72),a6 | a6->Laengenfeld Rest movl d0,a5@+ | Laenge vorlaeufig eintragen, | a5->1.Zi Quotient movl #4,d4 mulul d0,d4 | d4=vorlaeufig L(Quotient) addl d4,a5 | a5->vor fuehrende Zi Quotient addl d4,a0 addql #4,a0 | a0->vor fuehrende Zi Divident subql #1,d0 | d0 Schleifenzaehler, Schlei- | fenende bei -1 eorl d7,d7 | loeschenloop_sdiv:movl a0@-,d6 | d6 = hoechste Zi Divident divuq d5,d7:d6 | d6d7:d5,d6=Quotient,d7=Rest movl d6,a5@- | Quotient eintragen dbra d0,loop_sdiv | Divident fertig?nein=>Schleife movl a5@-,d4 | d4=vorlaeufige Laenge Quotient cmpl #0,a5@(0,d4:l*4) | fuehrende Zi Quotient = 0 ? bne nocorr1 | nein => Laenge Quotient okay subql #1,a5@(0) | ja=>Laenge Quotient 1 kuerzernocorr1: cmpl #0,d7 | Gibt es einen Rest ? bne notzero | ja => eintragen movl #0,a6@(0) | nein => Rest = 0 eintragen eorl d0,d0 | RC = 0 bra returnnotzero: movl #1,a6@+ | Laenge Rest = 1 movl d7,a6@(0) | Rest eintragen eorl d0,d0 | RC = 0 bra return|| Echte Division; Zunaechst uebertragen des Dividenten in das| Arbeitsfeld|notshort: movl #divident,a2 | a2->L-Feld div-Feld movl d0,d2 | d2 Schleifenzaehlerloop_trfield: movl a0@+,a2@+ | uebertragen dbra d2,loop_trfield | fertig ? nein => Schleife|| Erweitern von divident-Feld und Divisor| zuerst : v1 > b,2 ?| movl a1@(0,d1:l*4),d5 | d5 = fuehrende Zi Divisor=v1 cmpl #0,d5 | v1>b,2 ?(hoechstwertiges Bit | muss 1 sein!) bpl shift | nein => shiften|| kein Shift = Erweitern noetig, daher Shiftfaktor = 0 und die beiden| ersten Ziffern vom Divisor merken| movl #0,sp@- | Shiftfaktor auf Stack merken movl d5,sp@- | v1 auf Stack merken movl a1@(-4,d1:l*4),sp@- | v2 auf Stack merken bra startdiv | jetzt dividierenshift: eorl d4,d4 | d4 loeschenloopshift:addql #1,d4 | d4 Shiftfaktor lsll #1,d5 | um 1 nach links shiften cmpl #0,d5 | v1 jetzt okay ? bpl loopshift | nein => weiter shiften movl d4,sp@- | ja => Shiftfaktor auf Stack | merken pea divident | Adresse div-Feld und Shiftfak- movl d4,sp@- | tor fuer den Aufruf des Shift- pea divident | programms uebergeben jsr __shift | Programm aufrufen movl a1,sp@(0) | Dasselbe fuer den Divisor movl a1,sp@(8) jsr __shift addl #0xc,a7 | SP zuruecksetzen: sp=sp+12 movl a1@(0),d1 | d1 = neue Laenge Divisor, a1-> | 1. Zi Divisor movl a1@(0,d1:l*4),sp@- | fuehrende und naechste Zi Di- movl a1@(-4,d1:l*4),sp@- | visor auf Stack merken movl a1@(0,d1:l*4),d5 | d5 = neue fuehrende Zi Divisor|||startdiv: lea divident,a0 | a0->Laengenfeld div-Feld addql #4,a1 | a1->fuehrende Zi Divisor movl a0@+,d0 | d0=neue Laenge div-Feld subl d1,a0@(-4) | Anzahl der Divisionsschritte addql #1,a0@(-4) | = L(Dt)-L(dr), evtl. +1
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -