Parrot Assembly, oder kurz PASM, ist die Assemblersprache der ParrotVM. PASM ist sehr nah an der ParrotVM. Jeder Befehl in PASM entspricht einen Operationscode im Bytecode. Dies bringt die üblichen Nachteile von Assembler-Sprachen mit sich.
In der Dokumentation wird von der Verwendung von PASM abgeraten, da PASM schwer leserlich und fehleranfällig ist. Die Verwendung der Parrot Intermediate Representation sollte bevorzugt werden.
In einer Einführung darf ein "Hallo Welt"-Beispiel nicht fehlen:
$ cat hallo_wedel.pasm
print "Hallo Wedel\n"
end
$ parrot hallo_wedel.pasm
Hallo Wedel
Mit dem Operationscode "set" können Registerinhalte verändert werden. "print" gibt den Inhalt eines Registers aus.
$ cat register.pasm
set I1, 42
set N1, 4.2
set S1, "Hallo Ohlsdorf"
print I1
print ", "
print N1
print ", "
print S1
print "\n"
end
$ parrot register.pasm
42, 4.200000, Hallo Ohlsdorf
Für mathematischen Operationen sind natürlich auch die entsprechenden Befehle in Parrot vorhanden.
$ cat arithmetik.pasm
set I1, 2
set I2, 4
add I3, I1, I2 # I3 ist nun 6 (2+4)
sub I3, I1, I2 # I3 ist nun -2 (2-4)
mul I3, I1, I2 # I3 ist nun 8 (2*4)
div I3, I2, I1 # I3 ist nun 2 (4/2)
add I1, I1, 5 # I1 ist nun 7 (2+5)
set N1, 1
set N2, 3
div N3, N1, N2 # N3 ist nun 0.333333
print I1
print ", "
print N3
print "\n"
end
$ parrot arithmetik.pasm
7, 0.333333
Zeichenketten gehören in Parrot zu den grundlegenden Datentypen. Dementsprechend gibt es in Parrot Operationscodes mit denen Zeichenketten direkt verarbeitet werden können.
$ cat strings.pasm
set S1, "Hallo"
set S2, " Jena"
length I1, S2 # I1 ist nun 5
print I1
print ", "
concat S1, S2 # S1 ist nun "Hallo Jena"
concat S3, S1, S2 # S3 ist nun "Hallo Jena Jena"
substr S2, S1, 6, 5 # S2 ist nun "Jena"
chopn S1, I1 # S1 ist nun "Hallo"
print S1
print ", "
print S2
print ", "
print S3
print "\n"
end
$ parrot strings.pasm
5, Hallo, Jena, Hallo Jena Jena
Parrot Magic Cookies sind zusammengesetzte Datentypen und können dynamischen Speicher benötigen. Somit müssen PMCs mit einem Befehl erzeugt werden. Dieser Befehl ist "new".
Desweiteren können Operationscodes wie "set" oder "add" ein PMC als Operand aufnehmen. Parrot greift dann mit bestimmten Methoden auf das PMC zu. Beispielsweise wird set_number() aufgerufen, um einem PMC eine Zahl zuzuweisen.
$ cat pmc.pasm
new P0, .Integer # Klasse 'Integer' instanziieren
set P0, 123 # Den Wert 123 zuweisen
new P1, .Integer
set P1, 321
add P1, P1, P0 # Addieren geht auch
print P1
print "\n"
end
$ parrot pmc.pasm
444
Bedingte Sprünge sind weitgehend selbsterklärend.
$ cat spruenge.pasm
set I1, 1
NOCHMAL:
gt I1, 10, END # Wenn 'I1' größer '10', springe zu END
print I1
print " "
inc I1
branch NOCHMAL # goto
END:
print "\n"
end
$ parrot spruenge.pasm
1 2 3 4 5 6 7 8 9 10
Ein Funktionsaufruf ist ein unbedingter Sprung (branch) mit dem Unterschied, dass die aktuelle Position auf einem Call-Stack gespeichert wird
Die Parameterübergabe erfolgt über spezielle Befehle. Dies macht es möglich, mehrere Parameter auf einmal zurückzugeben.
$ cat unterprogramm.pasm
bsr HELLO
end
HELLO:
print "Hello there!\n"
ret
$ parrot unterprogramm.pasm
Hello there!
Erstellt von Johannes Barop