Kurs: Kleines Assembler ABC. Das hier soll keine komplette Anleitung sein, um Assembler zu erlernen. Aber es sollte einem Profan-User gestatten, erste Assemblerprogämmchen zu erstellen.
Zunächst einmal: Für Assembler benötigt man keine grosse Anzahl von Befehlen, mit 10 Befehlen (insgesamt gibt es über 90) ist man schon gut bedient, alles andere ist unnütz, weil der MASM32 Assembler High-Level-Syntax (.while / .endw / .if / .endif usw.) unterstützt. Und davon ist einem Profan-User schon das meiste bekannt.
In Assembler gibt es Register, das sind Speicherbereiche, die 4 Byte (Long-Int) groß sind. Einige Register dürfen wahlweise auch nur 1 oder 2 Bytes groß sein. Diese Register heißen eax, ebx, ecx, edx, edi und esi. Dann gibt es noch ebp, das sie aber erstmal ausser acht lassen sollten. Und es gibt noch esp, das ist auch erstmal tabu für sie. Zudem benutzt Assembler esp als Stackpointer.
Diese Register können auch als Integer oder Byte vorkommen. Als Integer heißen sie dann ax, bx, cx, dx, di und si.
Als Byte, da gibt es einmal das HiByte und das LoByte, in diesem Format heißen sie dann ah und al, bh und bl, ch und cl und noch dh und dl. Edi und esi können nur als Long-Int oder Integer benutzt werden.
Es dürfen immer nur zwei Register mit der selben Byte-Größe zusammen benutzt werden !!!
Die Aufgabe eines Registers: Ein Register kann eine Zahl zwischenspeichern und der Assembler rechnet bei einigen Befehlen mit den Werten einiger Register aktualisiert diese selbstständig. Die Register sind also zum speichern und zum rechnen da. Variablen gibt es natürlich auch.
Hier ein paar Beipspiele: KompilierenMarkierenSeparierenWerte dd 0,0,4,6,874,414425 ;6 Long-Ints
Zahlen dw 45,263,4663 ;6 Integer
dw 364,67,3
Nochmehr db 4,5,1,90,34 ;5 Bytes
Text db Hallo,0 ;Und ein 6 bytes langer String (immer mit Nullbyte !!!)
Kommen wir zum ersten und wichtigsten Befehl: mov. Mov steht für Move und heißt verschiebe. Man kann damit Zahlen in ein Register verschieben oder einen Registerwert in ein anderes Register kopieren. Der linke Wert ist das Ziel, der rechte Wert ist die Quelle. KompilierenMarkierenSeparieren Add addiert zwei Werte miteinander und schreibt den neuen Wert in das linke Register: KompilierenMarkierenSeparieren Sub subtrahiert zwei Werte und schreibt den neuen Wert in das linke Register: KompilierenMarkierenSeparieren Mul multipliziert zwei Werte und schreibt den neuen Wert nach eax. Bei einer Multiplikation dürfen nur eax und edx verwendet werden. Will man vorzeichenbehaftete Zahlen multiplizieren, dann muß anstatt dem mul das imul verwendet werden. mul ist in der Ausführung aber schneller.. KompilierenMarkierenSeparieren Div dividiert zwei Zahlen. An der Division sind drei Register daran beteiligt, eax, edx und ein Register ihrer Wahl. edx muß Null sein ! KompilierenMarkierenSeparieren So jetzt können wir schonmal rechnen.
Manchmal wünschen wir uns aber noch mehr Register. Die gibts aber nicht. Aber wir können den Stack als Registerablage mißbrauchen.
Mit push legen wir eine Variable oder ein Register auf dem Stack ab. KompilierenMarkierenSeparieren Mit pop können wir den Wert wieder von Stack runternehmen. Das muß aber in umgekehrter Reihenfolge passieren. KompilierenMarkierenSeparieren Stellt euch den Stack als ein Stapel mit Briefen vor. Wenn ich drei Briefe daraufpacke, dann muß ich die beiden obersten wieder wegräumen, um an den ersten der drei Briefe zu gelangen.
Jmp gleicht Profans Goto und wird für Schleifen und Sprünge benutzt. KompilierenMarkierenSeparieren Lea ist ähnlich wie mov. Nur übergibt lea nicht den Wert einer Variablen oder eines Registers, sondern den Zeiger auf die Variable/Register. KompilierenMarkierenSeparierenjmp weiter ;Datenbereich überspringen
data dd 333,444,555,666 ;Hier 4 Longints
weiter:
mov eax,data ;In eax steht jetzt 333. Der erste Wert aus data wird übergeben
lea edx,data ;In edx steht jetzt der Zeiger auf data
mov eax,[edx+0] ;333 nach eax. Das +0 könnte hier weggelassen werden
mov ebx,[edx+4] ;444 nach ebx
mov ecx,[edx+8] ;555 nach ecx
mov esi,[edx+12] ;666 nach esi
mov eax,222 ;222 nach eax
mov [edx+4],eax ;222 nach daten+4. Die 444 wird also durch 222 ausgetauscht.
Ups, die eckigen Klammern bedeuten, das nicht der Registerinhalt übergeben wird, sondern der Inhalt, auf den das Register zeigt.
Invoke ist eigentlich kein richtiger Befehl, sondern auch schon High-Level-Syntax. invoke startet eine API oder eine Dll-Funktion. Übergeben werden alle nötigen Parameter. KompilierenMarkierenSeparieren Wenn die API einen Rückgabewert übergibt, steht er nach dem Aufruf im Register eax. addr speicherbereich übergibt den Zeiger auf einen Variablenspeicher, ist aber nur bei invoke gestattet. Ebensogut hätte man schreiben können: KompilierenMarkierenSeparieren So, das wären die versprochenen 10 Befehle Aber wie können wir jetzt Register und Variablen vergleichen und Bedingungen und Verzweigungen programmieren ? Ganz einfach, den Rest können wir mit High-Level-Syntax machen. Ähnlich wie in Profan...
.while und .endw ist das Assemblergegenstück zu Profans While und EndWhile. KompilierenMarkierenSeparieren .break und .continue gibt es auch, genauso wie in Profan.
Für Bedingungen und Verzweigungen gibt es .if, .elsif, .else und .endif. Und das funktioniert so wie in Profan KompilierenMarkierenSeparieren Das == ist übrigens das Gleichzeichen.Weitere Vergleichsoperatoren sind: KompilierenMarkierenSeparieren Sollen mehrere Bedingungen abgefragt werden, dann sind die einzelnen Bedingungen in Klammen zu setzen, z.B. .if (eax==0) && (ebx>=0).
Ein Synonym für Profans whileloop gibt es ebenfalls.Das geht mittels einer .repeat / .until Schleife: KompilierenMarkierenSeparieren Eine .repeat / .until Schleife kann ebenfalls mittels .break verlassen, und mittels .continue neu gestartet werden.
So, hier endet unser Assembler Crashkurs. Ich hab wirklich alles Unnötige weggelassen. und somit dem User die Möglichkeit gegeben, von Grund auf anzufangen. Es gibt noch viele viele Befehle mehr, aber die meisten sind wirklich durch konfortablen High-Level Befehle ersetzt worden. Ein gute Auflistung aller Befehle gibt es hier: [...] (auch im Anhang zum Runterladen)
Ich habe hier auch darauf verzichtet, irgendwelche Optimierungen vorzunehmen (xor eax,eax anstatt mov eax,0), nur weil es ein paar Taktzyklen schneller ist. Assembler ist wirklich so sauschnell und die neuen Prozessoren arbeiten so gut, das solche Optimierungen kaum noch was hermachen.
Es lohnt sich , das komplette MASM32 Paket (Freeware) runterzuladen.
|