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.
|