AnsichtenInhaltsverzeichnis Schnell-Kurs (Assembler)Dies hier ist ein sehr kompakter Schnell-Kurs für Assembler. CPU-ASM ganz KurzASM ist im wesentlichen der Code der in direkter Prozessor- oder Maschinensprache geschrieben ist. ASM Programmen können daher viel effizienter sein als Hochsprachen Programme, und eine Runtime oder Compiler muß seine Code-Basis in ASM zur Verfügung haben. FunktionenMnemonic (ASM-Codes)Mnemonic werden die Assembler (ASM) Funktionen genannt, sie repräsentieren direkten Binären Maschinen/Prozessoren Code in Textform lesbar geschrieben. Sie werden direkt vom ASM-Kompiler in Binärcode übersetzt. Mnemonic Ziel, Quelle Mnemonic Ziel, Quelle1, Quelle2, Quelle3 SpeicherFlat-Memory ModelIn den alten 16Bit DOS-Systemen wurde der Speicher über die Kombination aus Segment-Register und Offset gebildet. Die Segmente konnten nur 64KB (65536 Byte) adressieren. Protected-Mode Memory (Real-Mode)Im Real-Mode unter DOS war es möglich das Programme andere Speicherbereiche überschreiben konnten wenn meistens Programmierfehler dies versuchten. So konnten auch Betriebssystem Prozeduren überschrieben werden und ein Systemabsturz verursachen. Little-Endian, Big-EndianDie Daten werden im Speichern mit dem kleinsten Wert/Byte zuerst geschrieben, also umgekehrt als die Zahlen im Dezimalsystem. RegisterDie Register sind die im Prozessor vorhandenen Speicherfelder die für alle Operationen verwendet werden. Der Prozessor kann keine Operationen zB. aus dem RAM-Speicher direkt durchführen, alle Werte müssen zuerst in die entsprechenden Register kopiert werden.
? --> A B C D Da diese mit allen Programmen und auch dem Betriebssystem in Multitasking geteilt werden, und es nur so wenige sind, gelten spezielle regeln zur effizienten und Sicheren Nutzung.
Programm-RegisterDas Programm-Register enthält die aktuelle Position im Programmlauf. Es kann nicht direkt beeinflußt werden sondern nur indirekt über ASM-Funktionen die den Programmlauf beeinflussen.
Haupt-RegisterRegister können aber auf eine Stelle im Speicher zeigen, der Prozessor rechnet also direkt mit dem Wert im Register, oder holt sich den Wert von der Adresse aus dem RAM-Speicher auf die das Register Zeigt.
(? --> LHX) Die Register können unterschiedlich Lang sein, 8 16 32 Bit. Je nach Längen gibt es verschiedene Zeichen. Diese gelten für alle 4 Haupt-Regsiter.
Segmente und Segment-RegisterDer Speicher ist eigentlich ein einziger riesiger Block. Um diese aber besser organisieren zu können verwendet ein Programm ein speziell Deklarierten Bereich für ein bestimmten Zweck. Diese Bereiche werden Segmente genannt. Zur Handhabung dieser Segmente gibt es spezielle Segment-Register.
Stack und Stack-RegisterStack funktioniert, wie der Name (Stack = Stapel) schon sagt, wie eine Liste von Werten die auf diesen Stapel gelegt oder entfernt werden können. Der Stack wird auch für die Parameterübergabe an Prozeduren (CALL, RET) verwendet. Wird also über ein CALL eine Prozedur aufgerufen, werden die Parameter (Werte, Referenzen, Zeiger) auf dem Stack abgelegt. Obwohl die aufrufende Prozedur dafür verantwortlich wäre, das, was sie auf den Stack gelegt hat, auch wieder von diesem zu entfernen, wird dies in der Praxis normalerweise über die Funktion RET erledigt, welche die zur aufgerufenen Prozedur gehörigen Parameter wieder vom Stack löscht und dann aus der Prozedur heraus springt. Eigentlich kann nur die aufrufende Prozedur wissen ob diese Parameter nicht vielleicht breites in der nächsten Operation wieder in gleicher Reihenfolge im Stack benötigt werden. Erwähnenswert ist vielleicht noch, daß Stacküberlauf-Fehler auch von schädlicher Software genutzt werden können, um Code in Programme einzuschleusen. Dazu wird ein Stacküberlauf genutzt, um gezielt Programmcode so zu überschreiben, daß am Ende der fremde eingeschleuste Code statt des eigentlichen Programms ausgeführt wird. Besonders Programmierer von Sprachen wie C müssen besonders darauf achten, daß durch fehlerhafte Daten keine solchen Fehler im Programmcode auftreten können. Da C einen allfälligen Stacküberlauf nicht prüft und somit auch nicht als Fehler erkennt, ist es sogar möglich, daß manipulierte passive Daten wie Bilder, Musik usw. verwendet werden können, um Viren und andere schädliche Software auf andere Computer einzuschleusen.
Index-RegisterDie Index-Register werden für Bereichsoperationen verwendet, also zB. Für String- oder Tabellen-Operationen.
FlagFlags dienen dem Prozessor um zusätzliche Resultate zu den Registern zu speichern oder zu lesen. Ein Flag kann nur 2 Zustände speichern 0=Ungesetzt 1=Gestezt. ZF PF AF OF CF SF sind die Status-Flags, werden durch Operationen vom CPU gesetzt. DF TF IF sind Steuerungsflags und werden vom Programm gesetzt um den Programmlauf zu beeinflussen.
Werte in Register kopierenRegister = RegisterMOV EAX, ECX ; EAX = ECX Register = SpeicherMOV EAX, [ECX] ; EAX = Var1 (Wert auf die ECX im Speicher zeigt) MOV EAX, Var1 ; EAX = Var1 (Wert auf die Var1 im Speicher zeigt) MOV [EBX], EAX ; EBX Adresse = EAX MOV Var1, EAX ; Var1 Adresse = EAX LEA EAX, Var1 ; EAX = Adresse-Var (Kopiert die Adresse und nicht den Wert von Var1) LEA EAX, Var1 ; EAX = Adresse-Var (Kopiert die Adresse und nicht den Wert von Var1) MOV Var1P, EAX ; Var1P = ist nun ein Pointer/Zeiger der auf Var1 Zeigt MOV EAX, Var1P ; EAX = Var1P MOV EAX, [EAX] ; Var1 (Wert auf die Var1P im Speicher zeigt, dereferenzieren) Register = KonstanteMOV EAX, 1 ; EAX = 1 MOV EAX, "1" ; EAX = ASCII(1) MOV EAX, 01h ; EAX = HEX(1) Speicher = SpeicherMOV Var2, Var1 ;!!! Speicher-Adresse kann nicht direkt kopiert werden ; MOV EAX, Var1 ; über Register kopieren MOV Var2, EAX ; PUSH Var1 ; über Stack kopieren POP Var2 Fehler-Quellen;Es können nur gleich lange Wörter miteinander berechnet werden MOV EAX, CL ; FEHLER: da EAX 32-Bit und CL 8-Bit ist ;Diese müssen erst Konvertiert werden MOVZX EAX, CL ; Mit 0 erweiterter Unsigned-Integer MOVSX EAX, CL ; Signed-Integer (mit 00 oder FF erweitert je nach Vorzeichen.) ;(Alte Variante) MOV AL, CL ; copy CL INTO AL CBW ; convert BYTE in AL to WORD in AX CWDE ; convert WORD in AX to DWORD in EAX Adress-Berechnungen für Arrays;Um zB. in Tabellen eine Adresse im Speicher verwalten zu können, gibt es spezielle Adressierungs-Funktionen MOV EAX, [ BasisAddresse + Index * Skalierung + Offset ] ; ([ BaseAddress + Index * Scale + Displacement ]) MOV EAX, [EBX + ECX * 4 + 8]
MOV AL, [EBX+ECX] ; Für ein Byte-Array ohne Offset MOV EAX, [EBX+ECX*4] ; Für ein Long-Array ohne Offset ;Für Lokale Arrays die als Parameter übergeben werden MOV EAX, [EBP-(displacement)] ;Diese Schreibweise ist erlaubt MOV EAX, Arr1[ECX*4] ;=[EBP-(displacement)+ECX*4] Signed und UnsignedSigned bedeutet das die Zahl ein Negativ-Zeichen enthalten kann, dafür wird das letze Bit der Zahl verwendet, das anzeigt ob die Zahl positiv oder 0 ist (=0) oder negativ (=1). Dem Zahlenwert geht also ein Bit verloren. Der Prozessor selbst unterscheiden nicht zwischen Signed- und Unsigned-Werten, es werden die gleichen Register verwendet. Für Addition und Subtraktion existieren noch nicht einmal besondere Funktionen, da sie nicht zwangsläufig notwendig sind wie bei Multiplikation und Division. Der Programmierer oder der Compiler ist dafür verantwortlich die Funktionen gemäß der Deklarationen der Variablen korrekt anzuwenden. zB. wird für eine Überlaufsprüfung bei einem Signed-Typ das Overflow-Flag OF geprüft, bei einem Unsigned-Typ das Carry-Flag CF. Operationsarten, Adressierung
Viele Operationen ermöglichen es nicht nur die Register zu verwenden, sondern auch Daten aus dem Speicher zu holen, und es sind auch Funktionen für Array/String möglich. Ebenso ist es möglich mit einem Register auf eine Speicheradresse zu verweisen. Hier sind nun eine Liste zusammengestellt, auf welche Weise der OpCode in Assembler umgesetzt werden kann. Aus denn Tabellen läßt sich ablesen welche Kombinationen erlaubt sind. Adressioerung
[Base + Index * Scale + Displacement]
BeispieleMOV EAX, EBX ;Op reg32, reg32 MOV EAX, DWord Ptr [Name1] ;Op reg32, mem MOV EAX, [EBX] ;Op reg32, mem MOV EAX, [EBX+ECX] ;Op reg32, mem MOV EAX, [EBX+ECX*4] ;Op reg32, mem MOV EAX, [EBX+ECX*4+1] ;Op reg32, mem MOV EAX, [EBX+1] ;Op reg32, mem MOV EAX, [ECX*4+1] ;Op reg32, mem MOV EAX, -2 ;Op reg32, imm MOV EAX, 0xFFFFFFFE ;Op reg32, imm MOV DWord Ptr [Name1], EAX ;Op reg32, mem ;... Call Übergabe von ParameternPUSH Var2 PUSH Var1 CALL Proc1 Proc1: MOV EAX, Var1 ; Var1 = [EBP+8] RET ;Alle Regster und Flags vor einem API-Call sichern (Ist langsam aber in Entwicklungszeit sinnvoll) PUSHAD ; Sichert Alle Register (ohne Flags) ; Code zum Call POPAD PUSHFD ; Sichert Alle Register und Flags ; Code zum Call POPFD Unterschied zwischen Adresse und WertMan kann direkt mit Werten Arbeiten oder mit Werten auf die eine Adress-Zeiger verweist.
Daten-DeklarationUm Explizit anzugeben um welchen Daten-Typ es sich handelt gibt es Schlüsselwörter die Angeben wie Lang das Wort ist.
Struct
RECT STRUCT left DWORD ? top DWORD ? right DWORD ? bottom DWORD ? RECT ENDS Schleifen
Anmerkung : Kopfgesteuerte Schleife; Hier Anfangwerte für Register 1 und 2 festlegen Schleifenanfang: CMP Register1,Register2 JNZ Schleifenende ; Schleife umgehen, falls Register 1 und 2 unterschiedlich sind ; beliebig viele Anweisungen ; sinnvollerweise entweder Register 1 oder 2 auch verändern, sonst droht Endlosschleife JMP Schleifenanfang Schleifenende: Fußgesteuerte Schleife; Hier Anfangwerte für Register 1 und 2 festlegen Schleifenanfang: ; beliebig viele Anweisungen ; sinnvollerweise entweder Register 1 oder 2 auch verändern, sonst droht Endlosschleife CMP Register1,Register2 JNZ Schleifenanfang ; Schleife wiederholen bis Register 1 = Register 2 Zählschleife; Hier ein Register zum Zählen vergeben ; und auf den gewünschten Maximalwert setzen(wie oft soll die Schleife durchlaufen ?) Schleifenanfang: ; beliebig viele Anweisungen DEC reg_zaehlen ; Anzahl der noch durchzuführenden Durchläufe um 1 verringern JNZ Schleifenanfang ; Schleife wiederholen bis reg_zaehlen auf 0 gesunken ist Anmerkung : Segmente im SpeicherDaten ------------ Daten-Ende -------- Stack-Pointer ESP ----- Stack-Ende ---------- Code ----------- Code-Ende -----
Weitergehende InformationenExceptionExceptions sind Fehler die der Prozessor erzeugt und die entweder abgefangen werden müssen, oder sogar zu einem Programmhalt führen können. Ein Typischer solcher Fehler ist zB. "Teilung durch 0" die in vielen Programmen auftreten kann wenn ein Wert 0 ist, obwohl dies nicht erwartet wurde. Control-Register
Debug-Register
| |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||