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 