You are currently viewing JASm Coding – Beispielprogramme 2 (Logik, ggT, Division und bitweises Schieben)

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

Für die minimalistische Programmiersprache JASm, die mit nur zwei Befehlen auskommt, wurden schon eine Reihe an Algorithmen vorgestellt. Unter anderem auch zur Addition und Multiplikation von Zahlen.

In diesem Beitrag werden die vorgestellten Codebeispiele länger, obwohl die eigentlich damit realisierten Funktionen nach wie vor eher “einfacher” Natur sind. So gehört die Division eigentlich zum Kernelement einer Programmiersprache, bei JASm, welches nur die Subtraktion (und einen Sprung) kennt, liegt dies anders.

Neben der Division werden auch ein paar logische Operationen vorgestellt.

Null? Und? Oder?

Wie bereits dargestellt, besitzt JASm einen Operator für einen bedingten Sprung: JA. Dieser versetzt den Programmzeiger auf eine andere Adresse, wenn der zu überprüfende Wert größer als Null ist. Im anderen Fall, wird mit der nächsten Codezeile fortgefahren.

Um zu prüfen, ob ein Wert exakt gleich Null ist, ist es also erforderlich die beiden anderen Kriterien (größer als Null und kleiner als Null) auszuschließen. Im konventionellen Pseudo-Code sieht dies wie folgt aus:

if (a > 0) goto ungleichNull
if (a < 0) goto ungleichNull
/* a ist gleich null */
...

Oder im JASm Code:

a:          0                      # zu überprüfender Wert
tmp:        0                      # Pufferspeicher
            JA  @a @ungleichNull
            SUB @tmp @a            # a negieren (tmp = -a)
            JA  @tmp @ungleichNull
gleichNull: ...                    # Code für den Fall, dass a = 0

ungleichNull: ...                  # Code für den Fall, dass a!= 0

Diese Implementierung entspricht auch zugleich einer Oder-Bedingung:

if (a>0 || a<0) goto ungleichNull

Bekanntlich lässt sich diese Logik auch negieren zu einer äquivalenten Und-Bedingung

if (!a>0 && !a<0) goto ungleichNull

Größter gemeinsamer Teiler (ggT), der Euklidische Algorithmus

Bei der Berechnung des größten gemeinsamen Teilers (ggT) von zwei Zahlen, handelt es sich um wohl einen der ältesten Algorithmen. Zum Einsatz kommt der Euklidische Algorithmus in seiner Reinform, also ohne Modulus Berechnung.

Die folgende Implementierung implementiert den Algorithmus als Makro.

EUCLID:                                                    
                                                           
REM b = abs(b)
                                                           
                     SUB @EUCLID_tmp @EUCLID_tmp           # init tmp
                     JA  @EUCLID_b @EUCLID_bispos          
                     SUB @EUCLID_neg @EUCLID_neg           # init neg
                     SUB @EUCLID_neg @EUCLID_b             # neg = -b
                     SUB @EUCLID_tmp @EUCLID_neg           # tmp = b
                     SUB @EUCLID_b @EUCLID_b               # b = 0
                     SUB @EUCLID_b @EUCLID_tmp             # b = -b
                                                           
EUCLID_bispos:                                             
                                                           
REM if a!=0 => goto loop
                                                           
                     JA  @EUCLID_a @EUCLID_loop            # a>0 goto loop
                     SUB @EUCLID_neg @EUCLID_neg           # init neg
                     SUB @EUCLID_neg @EUCLID_a             # neg = -a
                     SUB @EUCLID_tmp @EUCLID_neg           # tmp = a
                     SUB @EUCLID_a @EUCLID_a               # a = 0
                     SUB @EUCLID_a @EUCLID_tmp             # a = -a
                     JA  @EUCLID_a @EUCLID_loop            # "a"<0 goto loop
                                                           
REM a==0 => return b
                                                           
                     SUB @EUCLID_tmp @EUCLID_tmp           # init tmp
                     SUB @EUCLID_tmp @EUCLID_b             # tmp = -b
                                                           
EUCLID_finish:                                             # return tmp
                                                           
                     SUB @EUCLID_result @EUCLID_result     # init result
                     SUB @EUCLID_result @EUCLID_tmp        # result = -tmp
                     SUB @EUCLID_a @EUCLID_a               # init a for later use
                     SUB @EUCLID_b @EUCLID_b               # init b for later use
EUCLID_return:       JA  0 0                               # return to caller
                                                           
EUCLID_loop:                                               
                                                           
REM if b!=0 goto innerloop
                                                           
                     JA  @EUCLID_b @EUCLID_innerloop       # b>0 goto innerloop
                     SUB @EUCLID_tmp @EUCLID_tmp           # init tmp
                     SUB @EUCLID_tmp @EUCLID_b             # tmp = -b
                     JA  @EUCLID_tmp @EUCLID_innerloop     # b<0 goto innerloop
                                                           
REM b==0 return a
                                                           
                     SUB @EUCLID_tmp @EUCLID_tmp           # init tmp
                     SUB @EUCLID_tmp @EUCLID_a             # tmp = -a
                     JA  0 @EUCLID_finish                  # goto finish
                                                           
EUCLID_innerloop:                                          # if a>b then a-=b else b-=a
                                                           
                     SUB @EUCLID_tmp @EUCLID_tmp           # init tmp
                     SUB @EUCLID_tmp @EUCLID_b             # tmp = -b
                     SUB @EUCLID_neg @EUCLID_neg           # init neg
                     SUB @EUCLID_neg @EUCLID_a             # neg = -a
                     SUB @EUCLID_tmp @EUCLID_neg           # tmp = -b + a
                     JA  @EUCLID_tmp @EUCLID_agreaterb     # a>b goto agreaterb
                     SUB @EUCLID_b @EUCLID_a               # b -= a
                     JA  0 @EUCLID_loop                    
                                                           
EUCLID_agreaterb:                                          # a>b
                                                           
                     SUB @EUCLID_a @EUCLID_b               # a -= b
                     JA  0 @EUCLID_loop                    
                                                           
EUCLID_a:            0                                     # input variable a
EUCLID_b:            0                                     # input variable b
EUCLID_tmp:          0                                     # internal buffer
EUCLID_neg:          0                                     # internal buffer for -a oder -b

Schreibe einen Kommentar

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.