Maschinensprache i8086/ BWS schreiben
Theorie:
Einleitung – Maschinensprache –
Assembler – Zahlensysteme –
RAM-Adressen – BWS – Debug –
CPU-Register – Einfache Befehle – Stringbefehle – Interrupts –
I/O-Ports
Versuch:
BWS1 – BWS2 –
Hallo Welt – Bootsektor – MBR
Nützlich:
Befehlsliste – PAUSE – Filter
Analyse:
Bootloader
Kleines Maschinensprache-Programm zur Zeichenausgabe auf Bildschirm
BearbeitenUnter DOS oder im DOS-Fenster das Programm debug starten, mit
- a 100 die Eingabe von Assemblerbefehlen beginnen: mov ax,b800 mov es,ax
Für die Lücke hinter dem Befehlscode (hier: mov) können Sie Leerzeichen oder Tabulator verwenden. Drücken Sie nach dem zweiten Befehl zweimal Enter, damit endet die Eingabe.
Mit dem Befehl
u 100
erhält man eine Darstellung der bisher eingegebenen Befehle. Dabei steht xxxx für die Segmentadresse, die je nach Belegung des Arbeitsspeichers jedesmal anders ist. Die Bytes ab 0105 enthalten Datenmüll.
Die ersten beiden Befehle belegen 5 Byte. Setzen Sie deshalb die Eingabe ab Adresse 105 fort mit
a 105 mov di,0 mov cx,50
usw. Zur Kontrolle sollte man sich alle eingegebenen Befehle anzeigen lassen:
-u 100 11e Anzeige Befehle von 100 bis 11e
Angezeigt wird etwa folgendes (die Kommentare sind nachträglich hinzugefügt):
xxxx:0100 B800B8 MOV AX,B800 ; Beginn Bildwiederholspeicher (Text) xxxx:0103 8EC0 MOV ES,AX ; Das Extrasegment wird benutzt xxxx:0105 BF0000 MOV DI,0000 ; Relative Adresse = Null xxxx:0108 B95000 MOV CX,0050 ; Anzahl auszugebender Zeichen (50 Hex = 80 Dezimal) xxxx:010B B84107 MOV AX,0741 ; Farbe 07, Zeichen A (ASCII 65 Dez = 41 Hex) xxxx:010E 26 ES: ; Der nächste Befehl bezieht sich auf das Extra-Segment xxxx:010F 8905 MOV [DI],AX ; 2 Byte ins ES schreiben xxxx:0111 47 INC DI ; Offset der Zieladresse +1 xxxx:0112 47 INC DI ; nochmal +1 xxxx:0113 E2F9 LOOP 010E ; Rücksprung solange CX noch nicht Null ist xxxx:0115 B80000 MOV AX,0000 ; auf Tastendruck warten xxxx:0118 CD16 INT 16 ; Aufruf Tastatur-Interrupt xxxx:011A B8004C MOV AX,4C00 ; Programm beenden xxxx:011D CD21 INT 21 ; DOS-Interrupt xxxx:011F
Wenn Sie beim Eintippen einen Fehler gemacht haben oder etwas ändern wollen - kein Problem! Mit dem Befehl "a adresse" können Sie jederzeit Änderungen vornehmen. Setzen Sie statt "adresse" die gewünschte Zahl ein. Beispiel: Wir wollen nicht 50h Zeichen, sondern doppelt so viel ausgeben. Tippen Sie ein:
a 108 mov cx,a0
Die Eingabe beenden mit zweimal Enter. Zur Kontrolle die Änderung ansehen, dabei mindestens die vorhergehende Befehlszeile mit einschließen. Geben Sie "u 105" ein und vergleichen Sie!
Jetzt wollen wir das eingegebene Programm abspeichern. Dazu sind drei Schritte notwendig:
- Ein Namen für das Programm muss festgelegt werden (hier: TEST.COM).
- Die Länge des Programms muß ermittelt und ins CX Register geschrieben werden. Das Programm beginnt ab 0100 und 011F ist das erste unbenutzte Byte hinter dem Programm. Die Länge ist also 11F - 100 = 1F.
- Mit dem Befekl „W“ wird das eigentliche Speichern durchgeführt.
-r cx Programmlänge eingeben 1f Länge = 1f n test.com Namen für die Datei festlegen w write = Schreiben q quit = debug beenden
Im aktuellen Verzeichnis finden Sie jetzt eine neue Datei "test.com", 31 Byte (=1fh) Byte groß. Mit Eingabe des Befehls "test" oder "test.com" können Sie jetzt das neue Programm ausprobieren. Tippen Sie an der Eingabeaufforderung "test" ein und beobachten Sie, was passiert!
Wie man das Programm schrittweise testet, siehe nächste Seite.
debug test.com debug starten und Programm in RAM laden -g 10e führt das Programm bis vor den Befehl 10E aus -t führt einen einzelnen Befehl aus Wiederholen Sie den Befehl t mehrmals! -g 118 stoppt vor dem Befehl 118 ab hier mit Einzelschritten weiterzumachen, ist sinnlos. Hier geht's für die nächsten tausend Befehle in die Abgründe von DOS und BIOS. Sie können hier mit dem Befehl -p diesen INT 16 abarbeiten oder gleich mit dem Befehl -g das Programm bis zum Ende durchlaufen.
Modifikationen des Programmes
BearbeitenUm das Programm ein wenig zu verändern, können Sie es mit dem Befehl
debug test.com
in den Speicher holen. Mit dem Befehl „u“ bzw. „u 100“ können Sie jederzeit den aktuellen Programmcode anzeigen lassen.
- Tipp
- Um nach Ihren Änderungen nicht versehentlich die Originaldatei „test.com“ zu überschreiben, sollten Sie jedem neuen Experiment einen neuen Namen geben, z.B. mit
n test2.com
Beispiel 2
BearbeitenUnd jetzt geht's los mit kleinen Veränderungen:
-a 105 mov di,a00 ; Beginn ab Bildschirmzeile 17 (80*2*16=A00h) mov cx,10 ; nur 16 Zeichen ausgeben mov ax,ce21 ; Ausrufezeichen gelb blinkend auf roten Grund w q
Anmerkung: Das Register CX enthält beim Laden des Programmes dessen Länge, also „1F“. Weil das Programm durch diese Veränderungen nicht länger geworden ist, braucht das Register CX vor dem Speichern nicht gesetzt zu werden.
Beispiel 3
BearbeitenEs gibt eine beachtliche Anzahl von Spezialbefehlen für häufig wiederkehrende Befehlskombinationen. Einer dieser Befehle ist „STOSW“ (STOre String Word). Er speichert zwei Byte (=Word) auf den Speicherplatz, dessen Adresse durch ES:DI festgelegt ist, und erhöht das Register DI um zwei. Die vier Befehle 10E bis 112 (fünf Byte) können somit durch einen einzigen Befehl STOSW ersetzt werden. Die nicht mehr benötigten Byte werden in unserem Beispiel durch die entsprechende Anzahl NOP Befehle (No OPeration) ersetzt, um nicht den gesamten Rest des Programmes erneut eintippen zu müssen:
-a 10e stosw nop nop nop nop
Beispiel 4
BearbeitenSieh dir die Beispiele zum INT 16 an!
Ein Wort mehrmals auf Bildschirm ausgeben
BearbeitenBisher haben wir eine Folge von Buchstaben auf den Bildschirm geschrieben. Unter Nutzung des Stringbefehls STOSW wollen wir nun eine Folge von Worten ausgeben. Wir nutzen dafür den Anfangs- und Endteil des obigen Programms, nur der Mittelteil wird anders.
Unter DOS oder im DOS-Fenster das Programm debug starten, die Eingabe von Assemblerbefehlen mit
- a 100 beginnen:
mov ax,b800 mov es,ax mov di,0 mov cx,50 mov ax,074f stosw mov ax,074b stosw mov ax,0721 stosw mov ax,0720 stosw loop 10b mov ax,0 int 16 mov ax,4c00 int 21 n ok.com r cx 27 w u 100 127 |
|
Es geht allerdings auch einfacher:
|
Anzeige der Befehle von 100 bis 127
xxxx:0100 B800B8 MOV AX,B800 xxxx:0103 8EC0 MOV ES,AX xxxx:0105 BF0000 MOV DI,0000 xxxx:0108 B95000 MOV CX,0050 xxxx:010B B84F07 MOV AX,074F xxxx:010E AB STOSW xxxx:010F B84B07 MOV AX,074B xxxx:0112 AB STOSW xxxx:0113 B82107 MOV AX,0721 xxxx:0116 AB STOSW xxxx:0117 B82007 MOV AX,0720 xxxx:011A AB STOSW xxxx:011B E2EE LOOP 010B xxxx:011D B80000 MOV AX,0000 xxxx:0120 CD16 INT 16 xxxx:0122 B8004C MOV AX,4C00 xxxx:0125 CD21 INT 21 xxxx:0127
Dasselbe nochmal mit Kommentaren:
xxxx:0100 B800B8 MOV AX,B800 ; Beginn Bildwiederholspeicher (Text) xxxx:0103 8EC0 MOV ES,AX ; Das Extrasegment wird benutzt xxxx:0105 BF0000 MOV DI,0000 ; Relative Adresse = Null xxxx:0108 B95000 MOV CX,0050 ; Anzahl auszugebender Zeichen (50 Hex = 80 Dezimal) xxxx:010B B84F07 MOV AX,074F ; Farbe 07, Zeichen O (ASCII 79 Dez = 4F Hex) xxxx:010E AB STOSW xxxx:010F B84B07 MOV AX,074B ; Farbe 07, Zeichen K (ASCII 75 Dez = 4B Hex) xxxx:0112 AB STOSW xxxx:0113 B82107 MOV AX,0721 ; Farbe 07, Zeichen ! (ASCII 33 Dez = 21 Hex) xxxx:0116 AB STOSW xxxx:0117 B82007 MOV AX,0720 ; Farbe 07, Leerzeichen (ASCII 32 Dez = 20 Hex) xxxx:011A AB STOSW xxxx:011B E2EE LOOP 010B ; Rücksprung solange CX noch nicht Null ist xxxx:011D B80000 MOV AX,0000 ; auf Tastendruck warten xxxx:0120 CD16 INT 16 ; Aufruf Tastatur-Interrupt xxxx:0122 B8004C MOV AX,4C00 ; Programm beenden xxxx:0125 CD21 INT 21 ; DOS-Interrupt xxxx:0127