Open Source Institute | CyberArmy Intelligence & Security | CyberArmy Services & Projects

[Asm] x86 Assembler für Anfänger - Teil 1


[Reply] [View by Thread] [Help]
[Back To Article Discussion Forum]

Posted by Author Null Device On 2008-06-08 09:14:44




View and vote on the article here: x86 Assembler für Anfänger - Teil 1


x86 Assembler für Anfänger - Teil 1

Category
Asm
Summary
Dies ist der erste Teil der Cyberarmy Assembler Tutorials.Wir werden ganz am Anfang beginnen,
mit - 16-bit 8086 Assembler Code - um euch zu helfen die Grundlagen und Arbeitsweisen von Assembler zu verstehen.
Body

Int16h, 29. August 2007

Willkommen zum ersten Teil der Cyberarmy Assembler Tutorials.Wir werden ganz am Anfang beginnen,
mit - 16-bit 8086 Assembler Code - um euch zu helfen die Grundlagen und Arbeitsweisen von Assembler und
der CPU zu verstehen, ohne euch mit Dingen wie 32-bit Registern,Abgesicherter Modus und so weiter abzulenken.Von da aus werden wir zum modernen Gebrauch von Assembler kommen und euch zeigen,dass es weit davon entfernt ist,veraltet zu sein und es keinen Grund gibt,es nicht mehr zu unterrichten.

Asm ist eine Sprache,die mir nahe liegt,schon seit den Amiga Zeiten,wenn,abgesehen von Blitz BASIC und AMOS, es das einzigste war,womit viele Menschen arbeiten mussten.Der Rückgang von Assembler begann vor ein paar Jahren,möglicherweise wegen der Beliebtheit von Microsofts schnellen Programmentwicklungs Lösungen, wie Visual Basic und Borlands Delphi.
Hinzukommend zu solchen einfach verwendbaren IDEs,wurden neue Sprachen und Systeme wie C# und .Net entwickelt,welche sich rasch zu einem Standard in der Software Entwicklung in Microsoft Betriebssystemen bewegen.Obwohl solche Technologien die Arbeit eines Programmiers erleichtern können,resultieren sie auch in einer höheren Verbreitung von Programmen schlechter Qualität, die in den Umlauf kommen.

Bei einem Versuch, Assembler schmackhafter für Informatikstudenten zu machen,gab es Bestrebungen,Assembler zu modernisieren und es leichter benutzbar zu machen, indem man Dinge wie HLA(High Level Assembly)entwickelte.

Ich kann nicht wirklich etwas zu HLA sagen,da ich es nie benutzt habe - jedoch scheint es Assembler mit einem C-artigem Ansatz zu sein.
Ein weiteres,welches wahrscheinlich nicht Wert ist genannt zu werden, ist Microsofts ILASM für .Net.
Es ist nichts,was ich persönlich benutzen würdem um .Net Anwendungen zu entwickeln - ich bin aber auch kein
großer .Net Fan.

------------------------------------------------------------------------------------

Die 8086 CPU wurde 1978 von Intel entwickelt und hat 14 zugreifbare Register,jedes 16 bits lang.
Diese CPU ist die Grundlage auf welcher die heutige x86 CPU aufgebaut ist.Die ersten (und am gebräuchlichsten)vier Register sind Daten Register, welche AX, BX, CX, & DX genannt werden.
Dann gibt es noch Zeiger/Index Register - SP, BP, IP, SI und DI.

Auf die Daten Register kann man,obwohl 16 bits lang, durch zwei 8-bit Register zugreifen: AX ( AH & AL), BX (BH & BL), CX (CH & CL), DX (DH & DL) - Das "H" und "L" sind die oberen und unteren Teile des Registers.
Eine Beschränkung beim Benutzen der Register auf diese Weise ist,dass wenn man den unteren Teil von DX (DL) benutzt, DX nicht als 16-bit Register zur selben Zeit verwenden kann.Wenn zum Beispiel das DX Register 6944h(ex) enthält - würde DH (das obere 8-bit Register) 69h enthalten und DL 44h.

Hier eine Liste der Register,die wir gerade behandelt haben, mit kompletten Namen und einer Funktionsbeschreibung:
AX    -  Akkumulator     - Berechnungen und Eingabe/Ausgabe
BX    -  Base            - Kann als Index benutzt werden
CX    -  Zähler          - Wird für Schleifen verwendet
DX    -  Daten           - Eingabe/Ausgabe und Multiplikation/Division
IP    -  Befehlszeiger   - 16-bit Zahl,welche zum offset des nächsten Befehls zeigt
BP    -  Base Zeiger     - Zum weiterleiten/empfangen von Daten vom Stack
SP    -  Stack Zeiger    - 16-bit Zahl,welche zum Stack Offset zeigt
SI    -  Quell Index     - Wird bei der String Bearbeitung als Quelle benutzt
DI    -  Ziel  Index     - Wird bei der String Bearbeitung als Ziel genutzt
Die nächsten Register,die ich noch nich erwähnt habe, sind Segment Register.Diese Zeigen zu dem
jeweiligen aktiven Segment:
CS    -	 Code Segment	-     16-bit Nummer, welche zum aktiven Code Segment zeigt
DS    -	 Daten Segment	-		"
SS    -	 Stack Segment	-		"
ES    -	 Extra Segment	-		"
Ihr werdet wahrscheinlich bemerkt haben,dass wir bisher nur 13 Register haben.Das letzte Register ist das Flag Register, welches eine ausführlichere Erläuterung benötigt als die anderen...

Das Flag Register hat 9 Status bits,diese werden Flags genannt und sind entweder "on" oder "off",wie binäre & elektronische Schalter.Hier sind die Abkürzungen,Namen,Nummern und Beschreibungen für jedes Flag:
OF	Overflow Flag	11	Ein Overflow ist vorhanden
DF	Direction Flag	10	Überprüfe Richtungen bei String Operationen
IF	Interrupt Flag	 9	Interrupts sind aktiv
TF	Trap Flag	 8	CPU kann im Schrittmodus arbeiten
SF	Sign Flag	 7	Nummer der Rechnungen ist Negativ
ZF	Zero Flag	 6	Number der Rechnungen ist Null
AF	Aux Flag	 4	Ein zweites Carry Flag
PF	Parity Flag	 2	Zeigt Gleichwertigkeiten an (gleich/ungleich)
CF	Carry Flag	 0	Beinhaltet das letzte linke bit nach Rechnungen
Jetzt,da wir die Register kennen,sollten wir uns die Speicherverarbeitung von MSDOS anschauen,da wir zuerst 16-bit Assembler behandeln werden.Wenn die CPU 16-bit Daten speichert,tut sie dies in vertauschter Reihenfolge.
Zum Beispiel würde 6944h als 44h 12h gespeichert werden(als 2 separate Bytes in umgedrehter Reihenfolge).
Speicher in MSDOS(mit einem 8086) wird in 64KB Segmente unterteilt.Jedes hat eine "Referenz"Nummer welche in den Segment Registern gespeichert werden.Wenn man den Speicher debuggt,sieht man, dass die Adressen in folgendem Format sind: SEGMENT:OFFSET (xxxx:xxxx).Wir werden mehr über Speicher reden,wenn wir 32-bit Assembler behandeln,da es zum jetztigen Zeitpunkt noch nicht so wichtig ist.

Bis vor kurzem war mein lieblings x86 Assembler Borlands Turbo Assembler.Ich bin mir nicht sicher, ob es bereits Abandonware ist,jedoch ist es ein tolles Packet und relativ einfach verfügbar,wenn man es ausprobieren möchte (Turbo Assembler 5.0).Wenn ich mich richtig erinnere,war Version 4 oder 5 die erste Version,welche 32-bit Assembler und Linker beinhaltete,daher ist es möglich damit Win32 Programme zu schreiben.(Jedoch werden wir masm32 auch für den 32-bit Teil dieser Tutorials benutzen, - mehr darüber später).

Die folgenden MSDOS Beispiele benutzen TASM Syntax . Wenn du tasm5.zip findest,probiers aus.Es sollte gut mit Windows XP funktioneren,da ich ein Gegner von aufgeblähtem Müll bin habe ich es nicht unter Windows Vista getestet.Wenn ihr keine Kopie von TASM finden könnt,ist es trotzdem kein Problem den Rest des Artikels mitzuverfolgen.

Der folgende Teil ist ein typisches "Hello World" Beispiel - geschrieben in Assembler.Nach dem Quelltext werde ich jeden einzelnen Teil des Quelltexts erklären.
(ex01.asm)
.model tiny
.stack
.data
harro   db "Harro CyberArmy - I rove you rong time!", "$"

.code

main   proc
   mov   ax,seg harro
   mov   ds,ax
   mov   ah,09
   lea   dx,harro
   int   21h
   mov   ax,4c00h
   int   21h
main   endp
end main
Ihr könnt dieses Programm mit TASM zusammenfügen,indem ihr erst "tasm ex91" und danach "tlink ex01" schreibt.
Habt ihr kein TASM,könnt ihr durch die Kommentare trotzdem verstehen was passiert.
.model tiny - Dies sagt Assembler,dass wir nicht viele Ressourcen für dieses Programm brauchen
.stack      - Dies ist der Anfang des Stack Segment,welches wir nicht benutzen - da wir aber 
              eine .EXE anstatt einer .COM erstellen - brauchen wir das
harro db    -  "Define Byte", definiert einen byte-String,welcher als "harro" identifiziert wird.

.code       - Der Code Abschnitt beginnt
main proc   - Vergleichbar mit int main() oder void main() aus C/C++
            - Der Quelltext sollte in einer main Prozedur sein

mov ax, seg harro - "MOV" ist in Assembler ein Befehl, der Daten verschiebt
                  - in diesem Fall verschieben (oder kopieren) wir die Segment Adresse von "harro
                    nach AX
mov ds,ax         - Jetzt schieben/laden wir unsere Daten in DS, im Gegensatz zu Daten Registern können 
                    wir nicht einfach "seg harro" in ein Segment Register schieben.
mov ah, 09        - Schiebe die Zahl ß in den oberen Teil von AX (AH)
lea dx, harro     - Lade die tatsächliche Adresse von "harro" in DX.Mit anderen worten,wir kopieren
                    das Offset im Daten Segment von "harro" in DX, so dass wir wissen, was unser byte-string 
                    bei DS:DX ist.
int 21h           - Das ist Interrupt(dt.:"Unterbrechung") 21h - zu diesem Zeitpunkt wird AX(AH/AL) gelesen.
                  - Der Wert entspricht einer Funktion innerhalb int 21h.
                  - In diesem Fall beinhaltet AH 09, welches einen String auf stdout ausgibt.

mov ax, 4c00h     - Schiebt 4c00 h(ex) in AX
int 21h           - wieder Interrupt 21h. Jetzt beinhaltet AX(AH/AL) 4C00h
                  - der niedrigere Wert (AL) wird als Exit Befehl benutzt
                  - in dieser Instanz (00h) bedeutet es "ohne Fehler"
Mit Microsofts DEBUG.EXE, welche glücklicherweis immernoch bei Windows XP dabei ist, können wir sehen wie dieser assemblierte und gelinkte Quelltext im Speicher aussieht:

Führe "debug.exe ex01" aus.

Wenn man an der Eingabeauffoderung ist,kann man durch drücken von "d [enter]" einen Hex Auszug des Programms sehen, drückt man "u [enter]", bekommt man eine disassemblierte Version des Programms im Speicher,ähnlich wie folgende, zu sehen:
157E:0000		B87E15		MOV	AX,157E
157E:0003		8ED8		MOV	DS,AX
157E:0005		B409		MOV	AH,09
157E:0007		BA1200		MOX	DX,0012
157E:000A		CD21		INT	21
157E:000C		B8004C		MOV	AX,4C00
157E:000F		CD21		INT	21
Wie man sieht, wurden die Befehle "mov ax, seg harro" zu "mov ax,157E" umgewandelt,welches das vertauschte Segment ist,wo unsere Nachricht liegt.

In Maschinensprache wird "mov ax" zu "B8" übersetzt, danach folgt unsere Zahl.Der Befehl "lea dx, harro"(Welcher,wie ihr wissen solltet die reale Adresse von "harro" lädt) wurde als "mov dx, 0012"
interpretiert.Das sagt uns,dass unser String im Segment 157E(7E15),Offset 0012, zu finden ist.Wenn ihr zurück zum debug Fenster geht,können wir anzeigen, was an dieser Stelle ist, indem wir schreiben:"d 157E:0012".

Was ihr jetzt sehen solltet, ist etwas wie folgendes:
157E:0010  	         48 61 72 72 6F 20-43 79 62 65 72 41 72 6D     	  Harro CyberArm
157E:0020  	79 20 2D 20 49 20 72 6F-76 65 20 79 6F 75 20 72   	y - I rove you r
157E:0030  	6F 6E 67 20 74 69 6D 65-21 24   			ong time!$
Es sollte noch erwähnt werden,dass der Speicher in einem 32-bit Betriebssystem anders verwaltet wird als in einem schlcihten 16-bit Betriebssystem, wie MS-DOS.Mehr davon in einem späteren Teil.
It should be noted that memory is handled differently under a 32-bit operating system than in a humble, 16-bit Disk Operating System, such as Microsoft's MS-DOS. More about that in a later part.

Soviel zu Teil 1, ich hoffe, ihr wart nicht zu sehr gelangweilt.

Begleitend zu Teil 1 dieses Tutorials,hier ein paar Quellen, die ihr vielleicht hilfreich findet:

HelpPC - Eine Umfangreiche Hilfe für DOS Programmierer
Borland Turbo Assembler 5.0 User's Guide
Programming from the Ground Up - Linux Asm book
Intel ia-32 Dev Manuals - vol1-3
680x0 Programming Manual (Motorola)
PowerPC Programmer's Manual
MOS 6510 Datasheet (Commodore, C64)

Lesenswert:

http://www.ctyme.com/rbrown.htm - Ralph Brown's Interrupt List

This article was originally published by CyberArmy.net in the CyberArmy Library.





There are no replies to this post yet.



Guest:
Subject:
Message:
Signature:
Optional Image Link:
http://

CyberArmy::Forum v0.6
Generated In 0.00853 seconds


About Us | Privacy Policy | Mission Statement | Help