JASm Coding – Beispielprogramme 2 (Logik, ggT, Division und bitweises Schieben)

Division

Die Division erfordert mehrerer Fallunterscheidungen. Die offensichtlichste ist die Überprüfung, ob der Divisor (b) 0 ist, denn dies ist keine gültige Operation. Aus diesem Grund liefert diese Berechnung in einer separaten Speicherzelle (hier: error) einen von Null abweichenden Wert, wenn die Berechnung fehlgeschlagen ist.

Ohne diese Fallüberprüfung, würde die JASm Maschine bei der Berechnung des Quotienten in eine Endlosschleife laufen.

Die nächste Überprüfung ist dahingehend, ob der Dividend (a) gleich null ist. In diesem Fall können die weiteren Rechenschritte ausbleiben und das Ergebnis (0) sogleich festgeschrieben werden.

Nach diesen beiden Fällen, wird eine Überprüfung der Vorzeichen von a und b erforderlich. Der Fall, dass a oder b gleich null ist, kann an dieser Stelle schon ausgeschlossen werden. Sind die Vorzeichen gleich, ist das Ergebnis positiv, andernfalls Negativ.

Für einen möglichen Rest bei der Division, ist das Vorzeichen des Dividenden (a) relevant, insbesondere aus dem Grund, weil von a und b nun die Vorzeichen entfernt werden (a = |a| und b = |b|).

                @Start 
                -3 

REM Parameter und Variablen

a:              10                         # Dividend, später Rest
b:              3                          # Divisor
c:              0                          # Quotient
error:          0                          # Fehlermarker
tmp:            0                          # Puffer zur Vorzeichenkonvertierung
minusc:         0                          # Puffer für Ergebnisvorzeichen
minusa:         0                          # Puffer für Restvorzeichen
mina:           0                          # a negiert
minb:           0                          # b negiert
one:            -1                         # Konstante -1
minone:         1                          # Konstante +1

REM Programmbeginn

Start:                                     # c = a / b, Rest bleibt in a
                SUB @mina @a               # mina = -a
                SUB @minb @b               # minb = -b

REM Prüfung, ob b = 0

                JA  @b @vorzTest 
                JA  @minb @vorzTest 
                SUB @error @one            # Fehler (Division durch 0)
                SUB 0 0                    # Programmausstieg error = 1

REM Fallunterscheidung bzgl. Gleichheit der Vorzeichen von a und b

vorzTest:       JA  @a @aistpos            # a > 0
                JA  @mina @aistneg         # a < 0
                SUB 0 0                    # a ist 0, daher kann hier bereits die
                                           # Berechnung mit c = 0 enden
aistneg:        SUB @minusa @one           # merken, dass das Vorzeichen des Rests
                                           # gedreht werden muss
                SUB @a @a                  # Vorzeichen von a entfernen
                SUB @a @mina 
                JA  @b @vorzUngleich       # a < 0 && b > 0
                SUB @b @b                  # Vorzeichen von b entfernen
                SUB @b @minb 
                JA  0 @vorzGleich 
aistpos:        JA  @b @vorzGleich 
                SUB @b @b                  # Vorzeichen von b entfernen
                SUB @b @minb 
vorzUngleich:   SUB @minusc @one           # merken, dass das Vorzeichen gedreht
                                           # werden muss

REM Beginn der tatsächliche Division
REM Ab hier gilt:
REM   a > 0 && b > 0
REM   minus = 1, wenn das Vorzeichen gedreht werden muss
REM   c = 0

vorzGleich:
loop:           JA  @a @subb               # while a>0 do @subb
                SUB @mina @mina 
                SUB @mina @a 
                JA  @mina @korrektur 
                JA  0 @vorzKorr 
korrektur:      SUB @minb @minb 
                SUB @minb @b 
                SUB @a @minb               # um den Rest zu ermitteln, muss auch der
                                           # Wert von a um ein b korrigiert werden
                SUB @c @minone             # c = c - 1, Zähler korrigieren, da von a
                                           # ein b zu viel abgezogen wurde
vorzKorr:       JA  @minusc @vorzCDreh     # Vorzeichenkorrektur erforderlich?
                JA  0 @End 

vorzCDreh:      SUB @tmp @tmp              # Vorzeichen von c (= Quotient) tauschen
                SUB @tmp @c 
                SUB @c @c 
                SUB @c @tmp 
                JA  @a @rest               # existiert ein Rest?
                JA  0 @End 
rest:           JA  @minusa @vorzADreh     # Vorzeichenkorrektur des Rests
                                           # erforderlich?
                JA  0 @End 
vorzADreh:      SUB @tmp @tmp              # Vorzeichen von a (= Rest) tauschen
                SUB @tmp @a 
                SUB @a @a 
                SUB @a @tmp 
End:            SUB 0 0                    # Programmausstieg, c beinhaltet den
                                           # Quotienten und a den Rest der Division
                                           # (Modulus)

subb:           SUB @a @b                  # a = a - b
                SUB @c @one                # c = c + 1
                JA  0 @loop 

Nach diesen Vorbereitungen wird b so oft von a abgezogen, bis a nicht mehr größer als null ist. Sollte der Rest von a nun kleiner als null sein, muss ein Schritt rückgängig gemacht werden. Abschließend gilt es noch die Vorzeichen des Rests und des Quotienten basierend auf den eingangs festgehaltenen Erkenntnissen anzupassen.

Bei dem hier dargestellten Code wird der Quotient von 10 und 3 (10 : 3) ermittelt. Das Ergebnis befindet sich abschließend in Zelle @c, der Rest der Division in @a. Zudem ist in der Zelle @error eine 1 hinterlegt, wenn eine Division durch null versucht wurde.

Dieser Code funktioniert auch mit Gleitkommazahlen für a und b, ist also nicht beschränkt auf ganze Zahlen. Allerdings wird als Ergebnis für die Division nur eine natürliche Zahl geliefert. Der Rest hingegen (Modulus) kann durchaus eine reelle Zahl beinhalten.

Ähnlich wie bei der bereits vorgestellten Multiplikation wären auch hier Optimierungen möglich, die vor allem zum Tragen kommen, wenn Divisor und Dividend sich in ihrer Größenordnung massiv unterscheiden. Ein Ansatz hierzu wäre eine Implementierung analog zur schriftlichen Division zweier Zahlen. Dies erhöht die Komplexität des Codes deutlich, allerdings sollte es die Laufzeit erheblich verkürzen. Für den theoretischen Nachweis, dass eine Division mit JASm realisierbar ist, soll dieser Code allerdings zunächst genügen.

Beitrag vorlesen lassen

Kommentar hinterlassen

Nutze dieses Kommentarfeld um deine Meinung oder Ergänzung zu diesem Beitrag kundzutun. Verhalte dich bitte respektvoll und höflich! Kommentare werden vor der Veröffentlichung in der Regel moderiert und bei Verstößen gegen geltendes Recht, die guten Sitten, fehlendem Bezug oder missbräuchlicher Verwendung nicht freigegeben oder gelöscht.
Über die Angabe deines Namens, deiner E-Mail Adresse und deiner Webseite freuen wir uns, doch diese Felder sind optional. Deine E-Mail Adresse wird dabei zu keinem Zeitpunkt veröffentlicht.

Um mit dem Betreiber dieser Seite nicht-öffentlich in Kontakt zu treten, nutze die Möglichkeiten im Impressum.