Maschinensprache i8086/ BWS schreiben

Aus Wikibooks

Theorie:  EinleitungMaschinenspracheAssemblerZahlensystemeRAM-AdressenBWSDebugCPU-RegisterEinfache BefehleStringbefehleInterruptsI/O-Ports
Versuch:  BWS1BWS2Hallo WeltBootsektorMBR
Nützlich: BefehlslistePAUSEFilter
Analyse:  Bootloader


Kleines Maschinensprache-Programm zur Zeichenausgabe auf Bildschirm[Bearbeiten]

Unter 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[Bearbeiten]

Um 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[Bearbeiten]

Und 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[Bearbeiten]

Es 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[Bearbeiten]

Sieh dir die Beispiele zum INT 16 an!

Ein Wort mehrmals auf Bildschirm ausgeben[Bearbeiten]

Bisher 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

  


Falls Sie zu den Leuten gehören, die sich Befehlsfolgen durch unermüdliches Abtippen am besten einprägen können, so tippen Sie fleißig die nebenstehenden Befehle ein.

Es geht allerdings auch einfacher:

  • Markieren Sie die nebenstehenden blauen Zeilen von „mov ax,b800“ bis einschließlich „u 100 127“. Kopieren Sie den markierten Text (mit Strg + C in die Zwischenablage.
  • Öffnen Sie ein DOS-Fenster und geben Sie den Befehl „debug“ ein, gefolgt von Enter. Das Debug-Programm meldet sich mit einem Minuszeichen als Prompt.
  • Klicken Sie mit der rechten Taste auf die blaue Titelleiste hinter „Eingabeaufforderung“. Weiter mit „Bearbeiten“ „Einfügen“. Schnell wie von Zauberhand entsteht das Programm!
  • Sie müssen nur noch q und Enter eingeben, um den Debugger zu beenden und zur Eingabeaufforderung zurückzukehren.
  • Geben Sie den Befehl „dir“ ein, und Sie sehen Ihr neues Programm „OK.COM“ und können es testen.

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