THASM

Hier ist die Dokumentations-, Hilfe-, Readme- und Referenzdatei zum Thunder Assembler. Gleich zu Anfang möchte ich erwähnen, dass es sich um keinen echten Assembler handelt, sondern um einen Interpreter, dessen Syntax stark der einer Assemblersprache ähnelt. Ich habe ihn für den BCC entwickelt und mit dem Anfang der BCC-Abstimmung wird THASM unter GPL lizenziert!

 

 

 

Dokumentation

Die Versionsnummer wird ausgegeben wenn thasm ohne Parameter oder nur mit dem Parameter „-v“ aufgerufen wird. Diese kann dann mit den hier genannten verglichen werden. Übrigens werden nicht alle Versionen online gestellt. Versionen die nie online gestellt waren, werden grau gekennzeichnet.

 

Version -KEINE ANGABE- :

Wenn thasm.exe keine Angaben zur Versionsnummer macht ist das die Version 0.67 unstable. Es sind schon ziemlich viele Befehle implementiert, aber call, ret, mul, div, push und pop funktionieren noch nicht einwandfrei.

 

Version 0.7 nearly stable:

Die bekannten Fehler der letzten Version sind nun behoben. Es werden noch einige, sogar relativ wichtige, Funktionen eingebaut werden, daher nur „nearly stable“.

 

Version 0.72 nearly stable:

2 Fehler in push und pop behoben!

 

Version 0.73 nearly stable:

Programmkonstanten eingebaut. Neuen Bug entdeckt.

 

Version 0.74 nearly stable:

Laufzeitkonstanten und Compiletimerkonstante eingebaut, d.h. man kann jetzt abfragen wie lange das parsen/lexen dauert.

Schwere Fehler gefunden!

 

Version 0.75 nearly stable:

Schwere Fehler der letzten Version beseitigt.

 

Version 0.76 nearly stable:

Bedingte Funktionsaufrufe mit (ce=cz, cne=cnz, cg, cge, cl und cle) sind nun möglich. Diese funktionieren genauso wie (je=jz, jne=jnz, …), außer, dass sie eine Rücksprungadresse erstellen, die es erlaubt mit ret zurückzuspringen.

 

Version 0.765 nearly stable:

Timer eingebaut.

 

Version 0.78 Beta:

Alle mir bekannten Bugs wurden behoben. Außerdem wurden einige Funktionen eingebaut: sin(Sinuswert), cos(Cosinuswert), rnd(Zufallswert).

 

Version 0.8 stable:

-

 

Befehlsreferenz

Die Befehle werden hier in einer Tabelle aufgezählt und erklärt. Folgendes ist zu beachten:

-          Wenn ein Parameter unter Verwendung in eckigen Klammern steht, kann er weggelassen werden.

-          Wenn ein Befehl blau gefärbt ist, kann er nur im .text Sektor verwendet werden.

-          Wenn ein Befehl rot gefärbt ist, kann er nur im .data Sektor verwendet werden.

-          Wenn ein Befehl schwarz gefärbt ist, kann er in jedem Sektor verwendet werden.

-          Wenn in der Beschreibung ein [STR] steht, dann kann diese Funktion auch für Stringvariablen verwendet werden.

 

 

Befehl

Verwendung

Beschreibung

app

app name

Name muss ein String sein! Der Fenstertitel des Programms wird auf name gesetzt.

mov

mov op1,op2

Kopiert den Wert aus op2 nach op1 [STR]

add

add op1,op2

Addiert Wert aus op2 nach op1 [STR]

sub

sub op1,op2

Subtrahiert Wert aus op2 von op1

mul

mul op1,op2

Multipliziert op1 mit op2 und speichert das Ergebnis in op1

div

div op1,op2

Dividiert op1 durch op2 und speichert das Ergebnis in op1

inc

inc op

Erhöht Wert aus op um 1

dec

dec op

Verringert Wert aus op um 1

neg

neg op

Dreht das Vorzeichen des Wertes aus op um

not

not

Ändert alle Bits im Wert von op

push

push op

Kopiert den Wert aus op auf den Stack [STR]

pop

pop [op]

Verschiebt Wert von Stack nach op. Wenn op nicht gegeben ist, wird nach dx verschoben. (Siehe Standardvariablen DX) [STR]

jmp

jmp label

Springt zum Label label. (Siehe Hilfeabschnitt Deklaration eines Labels)

int

int name

name muss in dem Fall ein String sein! (Siehe Hilfeabschnitt Interrupts)

cmp

cmp op1,op2

Vergleicht op1 mit op2 und speichert das Ergebnis Programmintern

je = jz

je label

Springt zu label, wenn beim letzten cmp op1 und op2 gleich waren

jne = jnz

jne label

Springt zu label, wenn beim letzten cmp op1 und op2 ungleich waren

jl

jl label

Springt zu label, wenn beim letzten cmp op2 kleiner war als op1

jle

jle label

Springt zu label, wenn beim letzten cmp op2 kleiner oder gleich wie op1 war

jg

jg label

Springt zu label, wenn beim letzten cmp op2 größer war als op1

jge

jge label

Springt zu label, wenn beim letzten cmp op2 größer oder gleich war wie op1

jcxz

jcxz label

Springt zu label, wenn cx 0 ist (Siehe Standardvariablen CX)

call

call function

Ruft eine Funktion auf, die wie ein Label deklariert wurde

ret

ret

Nur in Funktionen! Kehrt zu der Zeile zurück von der aus die Funktion aufgerufen wurde

gfx

gfx op1,op2

Erzeugt ein Grafikfenster mit op1 Mal op2 Pixel

org

org op1,op2

Setzt die beiden Originvariablen auf op1 und op2. Diese werden bei diversen Grafikbefehlen benötigt

cls

cls

Löscht Bildschirminhalt

flip

flip

Kopiert gezeichnetes vom Backbuffer auf den Frontbuffer

rect

rect op1,op2

Zeichnet ein Rechteck mit einer Breite von op1 und einer Höhe von op2 an den Koordinaten, die mit org gesetzt worden sind.

text

text op

Schreibt Text op an die org-Koordinaten

oval

oval op1,op2

Zeichnet ein Oval mit einer Breite von op1 und einer Höhe von op2 an die org-Koordinaten

dot

dot op1,op2

Zeichnet einen Punkt an (op1|op2)

and

and op1,op2

Führt die logische And-Operation mit op1 und op2 aus und speichert das Ergebnis in op1

or

or op1,op2

Führt die logische Or-Operation mit op1 und op2 aus und speichert das Ergebnis in op1

xor

xor op1,op2

Führt die logische Xor-Operation mit op1 und op2 aus und speichert das Ergebnis in op1

cos

cos op

Errechnet den Cosinuswert für op und speichert ihn in op

sin

sin op

Errechnet den Sinuswert für op und speichert ihn in op

rnd

rnd min,max

Speichert eine Zufallszahl, die im durch min und max angegebenen Wertebereich liegt im AX.

int

op1 int op2

Erstellt eine Variable des Typs Int mit dem Namen op1 und dem Wert op2(muss konstant sein!)

single

op1 single op2

Erstellt eine Variable des Typs Single mit dem Namen op1 und dem Wert op2(muss konstant sein!)

string

op1 string op2

Erstellt eine Variable des Typs String mit dem Namen op1 und dem Wert op2(muss konstant sein!)

 

 

 

 

 

Hilfe

Datentypen

Es sind (bis jetzt) nur 3 verschiedene Datentypen verfügbar.

 

Datentyp

Name

Minimum

Maximum

Int

Ganzzahl

-2147483648

2147483647

Single

Gleitkommazahl

1.17549e-38

3.40282e+38

String

Zeichenkette

-

-

 

 

Standardvariablen

Thasm definiert nicht nur die Variablen des Programmierers, sondern auch eigene. Hier ist die Tabelle:

 

Name

Datentyp

Verwendet von Funktion(en)

ax

Single

rnd

bx

Single

-

cx

Int

jcxz

dx

String

pop

cmd

String

int print ; int input

kbd

Int

int downkey ; int waitkey

 

Interrupts

 

Ein Interrupt ist eine sogenannte Unterbrechungsroutine, das heißt es wird das laufende Programm unterbrochen und, zumindest bei Thasm, ein vordefiniertes „Miniprogramm“ ausgeführt. Folgende Interrupts existieren und funktionieren:

 

 

 

 

 

Interrupt

Beschreibung

int print

Gibt den Wert aus der Standardvariablen cmd auf dem Bildschirm aus, sofern sich das Programm im Kommandozeilenmodus befindet.

int input[,text]

Gibt den Text text aus und wartet auf eine Eingabe. Diese wird dann in die Variable cmd verschoben.

int waitkey

Wartet auf einen Tastendruck. Verschiebt dann den Ascii-Wert der Taste in die Standardvariable kbd. ACHTUNG: Funktioniert nur im Grafikmodus!

int downkey,k

k ist eine KeyKonstante(siehe Hilfeabschnitt KeyKonstanten). Je nachdem ob die Taste gedrückt wird oder nicht, wird kbd auf 1 oder 0 gesetzt.

int delay,zeit

Wartet eine Zeit von zeit ab. Diese muss in Millisekunden gegeben werden.

 

 

KeyKonstanten

KeyKonstanten sind Konstanten, die von Thasm selbst erstellt werden und, mit dem Interrupt downkey, der Abfrage von Tastendrücken dienen.

Ein Beispiel wäre:

 

.text

main:

int downkey,ESC

jmp main

 

Hier wird die Standardvariable kbd auf 1 gesetzt wenn die Taste Escape gedrückt wird und 0 wenn sie nicht gedrückt wird. Es werden bis jetzt aber nur folgende Tasten unterstützt: A, S, D, W, LEFT, RIGHT, DOWN, UP, ESCAPE. Die Konstanten LEFT, RIGHT, DOWN und UP gehören zu den Pfeiltasten.

 

Sektoren

In Thasm müssen Variablendeklarationen von Befehlen getrennt werden. Bei diversen Hochsprachen macht dies der Compiler, hier muss der Programmierer anpacken. Dadurch werden alle Variablen global, also im gesamten Programm verwendbar, was Nachteile, aber auch gewisse Vorteile bringt. Ich habe beim Pong Programmieren ein völlig neues Programmiergefühl bekommen (war ein komisches Gefühl). Die Sektoren werden wie folgt eröffnet:

 

.data    'eröffnet den Datensektor

           

            username string "Thunder"

 

.text     'eröffnet den Codesektor

 

main:   'Main-Funktion - hier setzt der Interpretiervorgang

            'ein. Ist nicht notwendig wenn das Programm direkt

            'nach der Codesektoreröffnung beginnt.

 

            mov cmd,username   'Natürlich könnte man statt

                                               'username auch "Thunder"

                                               'schreiben

            int print

            end

 

 

Dieses Programm erstellt eine Variable namens username und gibt sie dann im Codesektor aus.

 

Kommentare

Kommentare können den Code übersichtlicher gestalten. Dies ist besonders wichtig, wenn man größere Programme schreibt, was in thasm schnell mal passieren kann.

Einzeilige Kommentare werden durch Apostroph eröffnet. Obiges Beispiel erklärt einzeilige Kommentare auch.

Mehrzeilige Kommentare beginnen mit / ' = Slash mit anschließendem Apostroph

und endet mit '/ = Apostroph mit anschließendem Slash.

Beispiel:

 

.text

            int input,"Ihr Name: "

            /'

                        KOMMENTARTEST

            '/

            int print

            int delay,2000

            end

 

 

Labels

Ein Label stellt eine Sprungmarke oder den Anfang einer Funktion dar. Es wird an einen Beliebigen Namen ein Doppelpunkt angeschlossen und fertig ist das Label. Wenn man eine Funktion erstellen will, muss man sie auch noch mit dem Schlüsselwort „ret“ beenden.

Ein Beispiel für eine Sprungmarke:

.text

main:

int downkey,ESC

jmp main

 

Ein Beispiel für eine Funktion:

 

.text

main:

            mov cx,0

            mov dx,"Etwas"

            inc cx

            push cx

            push dx

            call out

            int delay,1500

            end

 

out:

            pop dx

            pop cx

            mov cmd,cx

            add cmd,": "

            add cmd,dx

            int print

ret

 

 

Programmkonstanten (v0.74+)

 

Programmkonstanten sind da um einen Zustand oder eine „Besonderheit“ eines Programms zu ermitteln. Sie beginnen mit zwei Underlines( _ ) und enden auch mit zwei Underlines. Dazwischen steht der Name in Großbuchstaben. Ein Beispiel ist die Programmkonstante __LINE__ . Sie gibt die Zeilenzahl zurück.

 

Es gibt im Grunde 2 Arten von Programmkonstanten:

-          Die, die während des Parsens durch einen Wert ersetzt werden(einfache Programmkonstante)

-          Die, die während der Laufzeit durch einen Wert ersetzt werden(Laufzeitkonstante)

 

Hier eine Tabelle der bis jetzt vorhandenen Programmkonstanten:

 

 

 

 

Name

Typ

Wird ersetzt durch…

__LINE__

Einfache Programmkonstante

…die Nummer der Zeile in der sie steht

__FUNC__

Einfache Programmkonstante

…den Namen der Funktion in der sie steht

__TIMER__

Laufzeitkonstante

…durch die Zeit in Millisekunden die seit dem Prozessorstart vergangen ist.

___WINDOWS__

Einfache Programmkonstante

… 1 wenn das Programm unter Windows ausgeführt wird und sonst 0.

__MACOS__

Einfache Programmkonstante

… 1 wenn das Programm unter Mac OS ausgeführt wird und sonst 0.

__LINUX__

Einfache Programmkonstante

… 1 wenn das Programm unter Linux ausgeführt wird und sonst 0.

__CTIMER__

Einfache Programmkonstante

… die Zeit in Millisekunden die vom Prozessorstart bis zum Anfang des Parsens vergangen ist.

 

 

Durch die Programmkonstanten __TIMER__ und __CTIMER__ lässt sich leicht die Zeit ermitteln, die thasm zum Parsen gebraucht hat:

 

.text

main:

            mov cx,__TIMER__

            sub cx,__CTIMER__

            mov cmd,cx

            int print

            int delay,1500

            end

 

Also bei mir ist das eine Millisekunde. Ob das für eine Scriptsprache wenig oder viel ist weiß ich nicht genau, aber sehr schlecht kann es ja nicht sein.

 

Arrays (v0.77+)

 

Endlich habe ich es geschafft Arrays zu implementieren. Sie werden auf eine ganz einfache Art und Weise definiert und modifiziert. Dieses Beispiel soll das verdeutlichen:

 

 

 

.data

            ar[50] int 0 'setzt alle Elemente auf 0

.text

main:

            mov cx,0

mainloop:

            mov ar[cx],cx

            add cmd,ar[cx]

            add cmd," ,"

            inc cx

            cmp 49,cx

            jl mainloop

            int print

            int delay,1500

            end

 

Die Arrays sollten sich mit diesem Beispiel selbst erklären.

 

 

Arithmetische und logische Operationen

 

Achtung: logische Operationen werden erst ab Version 0.75 vollständig unterstützt!

 

Arithmetik:

           

Höhere Programmiersprache

Thasm

x = x + y

add x,y

x = x - y

sub x,y

x = x * y

mul x,y

x = x / y

div x,y

 

Logik:

 

Höhere Programmiersprache

Thasm

x = x and y        oder        x = x & y

and x,y

x = x or y           oder       x = x | y

or x,y

x = x xor y         oder        x = (x | y) - (x & y)

xor x,y

x = -x

neg x

x = not x            oder        x = !x

not x