Register

Die Register sind kleine Speicherstellen, die Zahlen enthalten. Sie sind den Variablen aus den Programmiersprachen ähnlich, sind aber nicht ganz gleich wie diese. Der Mikroprozessor hat eine bestimmte Anzahl von Registern, die nicht Teile des Hauptspeichers sind (sie sind Bestandteile des Mikroprozessors).

 

Der Debug-Befehl R (Register) zeigt am Bildschirm den Inhalt der Register an. Last uns audprobieren! Die erste vier - AX, BX, CX, DX – sind Allzweckregister, während die anderen - SP, BP, SI, DI, DS, ES, SS, CS und IP – haben eine bestimmte Rolle. Die, aus vier Ziffern bestehende Zahl nach dem Namen des Registers, ist in hexadezimale Form. Ein Register ist also zwei Bytes (ein Wort) lang (das ist zumindest für die Register des I8086, I8088-er Mikroprozessors gültig).

 

Wir haben früher gesagt, dass die Register den Variabeln ähnlich sind, ihren Inhalt kann also verändert werden. Wenn wir nach dem Befehl R des Debugs einen Registername schreiben, dann sagen wir den Debug Programm, dass wir den Inhalt des Registers erst anschauen, dann verändern möchten.

Z. B:

-R AX

AX 0000      Antwort der Maschine

:3A7         das geben wir ein

 

So können wir den Inhalt der Register beliebig ändern. Die neuen Werte können wir mit dem Befehl R überprüfen.

 

Die Allzweckregister AX, BX, CX und DX lassen sich in zwei 8-Bit-Register unterteilen. Der hohe und der niedrige Teil lassen sich getrennt ansprechen. Man kann aber alle 16 Bits auf einmal auslesen oder beschreiben. Will man zum Ausdruck bringen, dass man alle 16 Bit des Registers meint, so hängt man noch ein X zum eigenen Kennbuchstabe des Registers an. Die Kennung lautet dann AX, BX, CX oder DX. Meint man nur Bit 0 bis einschliesslich Bit 7, so schreibt man AL (A-Low), BL, usw. Für Zugriffe auf Bit 8 bis Bit 15 schreibt man AH (A-High), BH, usw.

Anmerkung: Mit dem Debug-Befehl R kann man nur die 16 Bits als Ganzes ansprechen.

Der Speicher

 

Jetzt können wir schon zwei Zahlen in Register AX und BX eingeben. Wie könnten wir den Processor sagen, dass er diese zwei Werte addieren sollte, und das Ergebnis im Register AX behalten sollte? Wir geben einige Zahlen in den Speicher des Rechners ein. Der Rechner hat wenigstens 640Kb Speicherstelle. Wir werden in diese grosse Speicherstelle irgendwo einen 2 Byte langen Maschinekode einschreiben. In diesem Fall wird der Maschinekode aus zwei binäre Zahlen bestehen. Dieser Kode sagt den Prozessor, das er Register BX mit Register AX addieren soll. Damit wir auch sehen können was passiert, werden wir den Befehl mit der Hilfe von Debug ausführen.

 

In welchem Ort des Speichers sollen wir aber diesen Kode einschreiben und wie sagen wir den Prozessor wo er ihn suchen soll? Der Prozessor teilt den Speicher in 64Kb grosse Teilen, die als Segmenten genannt werden.

 

Im allgemeinen sind wir mit dem Speicher innerhalb eines Segmentes beschäftigt, ohne zu wissen wo dieses Segment beginnt. Das ist uns möglich wegen der Art auf den der Prozessor den Speicher bezeichnet.

 

Jedes Byte vom Speicher ist mit einer Nummer bezeichnet, mit 0 angefangen. Die grösste, aus vier Ziffern bestehende hexa Zahl (die Kapazität eines Registers) ist 65535, also 64Kb ist die obere Beschränkung des Labels. Mit einem kleinen Trick kann der Prozessor einen viel grösseren Speicherbereich adressieren: er benützt zwei Zahlen, eine für die Bezeichnung der 64Kb-er Segmente, und noch eine für jedes Byte oder Offset (Verschiebung) innerhalb des Segments. Jedes Segment beginnt an dem Vielfachen von 16. So kann der Prozessor einen Speicherbereich bis 1Mb handeln.

 

Die, von uns benutzte Adressen sind die Offset-Adressen (relativ zum Anfang des Segmentes). Wenn wir eine Adresse angeben wollen, geben wir die Segmentnummer, dann das Offset. Z. B. die Adresse 3756:0100 bedeutet, dass wir am Offset 100h innerhalb des Segmentes 3756h sind. Mit Debug arbeiten wir innerhalb eines einzigen Segments, so werden wir nur die Offset-Adresse geben.

 

 

Unserer 2 Byte-er Befehl für die Addition von AX und BX schaut so aus: ADD AX, BX. Dieser Befehl werden wir in den Speicherstellen 100h und 101h, innerhalb des aktuellen,  von Debug gerade benützten Segmentes einschreiben. Wenn wir uns auf den ADD Befehl beziehen, sagen wir, dass es an der Stelle 100h ist, weil an dieser Stelle das erste Byte des Befehls liegt. Um die Speicherstellen anzuschauen und zu verändern können wir den Befehl E (Enter, also Eingabe) benützen. Last uns diesen Befehl verwenden um die zwei Bytes des ADD Befehls in den Speicher einzugeben:

Nachdem wir

-E 100          

eingeben, erscheint die aktuelle Adresse (Segment:Offset) und ihr aktuellen Wert, dann können wir nach dem "." den neuen Wert eingeben

xxxx: 0100 xx.01

-E 101

xxxx: 0101 yy.D8

 

Die Zahlen 01h und D8h an der Stellen xxxx:0100 und xxxx:0101 sind die entsprechende 8088-er Maschinkode des ADD Befehls. Die, hier mit xxxx bezeichnete Segmentnummer kann von Zeit zu Zeit unterschiedlich sein, das wird aber unser Programm nicht beeinflussen. Genauso können beim E Befehl jedesmal verschiedene Werte erscheinen (wir haben es mit xx und yy bezeichnet). Diese Zahlen entsprechen den alten Inhalt der Offset-Adressen 100h und 101h, innerhalb des, von Debug gewählten Segmentes. Last uns die Einschreibung in den Speicher ausprobieren!

 

-E 100

xxxx:0100 xx.01

-E 101

xxxx:0101 yy.D8

-R         

 

In der Zeile unter den Registerwerte können wir die eingegebene Speicherwerte sehen.

 

Ausführung eines Befehls

Jetzt können wir schon die Registerwerte  verändern, also können wir die Operanden eingeben, und können wir den Additionsbefehl in Maschinekode in den Speicher eingeben. Damit wir diesen Befehl ausführen können, sollen wir noch den Prozessor sagen, wo er den Befehl suchen soll.

 

Der 8088-er sucht die Adresse des nächsten Befehls in zwei spezielle Register, CS und IP, die wir bei der Registerausschreibung (mit Befehl R) schon sehen könnten. Die Segmentnummer ist in CS  (Code Segment). Das ist von Debug schon angestellt. Der andere Teil der Adresse, das Offset innerhalb des Segmentes ist im Register IP (Instruction Pointer). Wenn wir den Prozessor sagen wollen, wo er den nächsten Befehl  suchen soll, dann sollen wir IP auf 100h anstellen. Wenn wir nachschauen, der Wert des IP Registers ist schon 100h. Wir waren schlau: das Debug  Programm schaltet am Anfang den Wert von IP auf 100h. Deswegen haben wir mit Absicht die Adresse 100h gewählt um unseren ersten Befehl einzuschreiben, so müssen wir jetzt IP nicht einsetzen. Diese Lösung ist bemerkenswert!

 

 

Jetzt werden wir an Debug sagen, dass er unseren einzigen Befehl ausführen soll. Wir benützen den Befehl T (Trace - verfolgen), das führt einen einzigen Befehl aus und dann ergibt die Registerwerte am Bildschirm. Nach jeder Ausführung soll IP auf den nächsten Befehl zeigen. In diesem Fall zeigt es 102h. Wir haben keinen Befehl auf die Adresse 102h eingegeben, so wird die letzte Zeile der Registerausschreibung irgendeinen Befehl eines vorigen Programms zeigen. Schreiben wir einen Befehl ein, und verfolgen wir seine Ausführung mit dem Befehl T. Wenn wir noch einmal T eingeben, dann wird der nächste Befehl ausgeführt, das noch nicht von uns eingeschrieben war.

 

Wenn wir die vorige Addition noch einmal ausführen möchten, wir möchten also noch einmal den Wert von BX zu AX addieren, dann sollen wir das Register IP mit der Hilfe des R Befehls noch einmal auf 100h einsetzen. Last uns ein Paar Additionen ausprobieren!

 

-R AX

 

:3D4

-R BX

:123

-E 100       

            .01

-E 101

            .D8

-R

-T

-R IP       

:100

-R

-T

 

Die Maschinekodes von ein paar Additionsbefehle (Anmerkung: nur keine Angst, sie sollen nicht auswendig gelernt werden):

ADD AX, BX              01D8

ADD AX, CX              01C8

ADD AX, DX              01D0

ADD BX, CX              01CB                              

ADD BX, DX             01D3                                 

ADD CX, DX             01D1

 

Es gibt eine einfachere Möglichkeit um ein kleines Programm mit dem Debug Programm in den Speicher einzugeben:

Das Debug hat einen Befehl A (Assemble-übersetzt) womit man die Assembler-Befehle direkt mit dem Mnemonik (für den Mensch einfach zu lesende Form) angeben kann (statt der numerischen Kode 01 D8 kann man ADD AX, BX schreiben).

Zum Beispiel:

 

-A 100

xxxx:0100 ADD AX, BX

xxxx:0102 ADD BX, CX

xxxx:0104

-

 

Wenn wir mit der Eingabe der Befehle fertig sind, sollen wir nur auf Enter drücken und erhalten wir wieder die Debug-Kommandozeile (prompt).

 

Wir haben mit dem A Befehl den Debug gesagt, dass wir die Befehle mit dem Mnemonik angeben möchten und die Zahl 100 heisst, dass wir die eingabe der Befehle an der Adresse 100 anfangen  wollen.

 

Bis jetzt haben wir das Debug benützt um die Registerwerte zu ändern. Wir werden aber unsere Programmen nicht immer mit Debug ausführen. Die Registerwerte können selbst vom Assembler-Programm gegeben werden, dazu wird der MOV Befehl benützt.

Mit MOV kann man Registerwerte in andere Registern kopieren. Z. B.:

MOV AH, DL    - der Wert von DL wird in AH kopiert (DH und AL bleibt unverändert)

MOV AX, BX   - der Wert von BX wird in AX kopiert

Der MOV Befehl hat immer zwei Operanden von gleicher Grösse (Byte-Byte oder Wort-Wort), man kann es nie zwischen einen Byte und Wort operand benützen.

Der MOV Befehl hat auch eine andere Form. Man kann damit einen Wert in einen Register eingeben. Z.B.:

MOV AX, 25

MOV BL, A3

 

Mit der Hilfe des U (Unassemmble) Debug-Befehls kann man den Inhalt des Speichers auslisten.(mit einer gegebenen Adresse angefangen).

Sie können überprüfen was Sie vorher eingeschrieben haben mit

- U 100

 

Das folgende Programm zeigt einen “*” Charakter am Bildschirm an (Sie können es mit dem Befehl A 100 in den Speicher einschreiben):

MOV     AH,02         

MOV     DL,2A         

INT     21         

INT     20

 

Der Int Befehl ruft eine Unterbrechung auf (das ist wie ein Unterprogramm, das im System uns zur Verfügung steht). Wenn AH den Wert 02 hat, wird der Befeht INT 21 eine Unterbrechung aufrufen, die ein Charakter ausgibt, deren ASCII-Code sich im DL Register  befindet (Das ist 2A für das Zeichen “*”. Sie können es beliebig ändern um eine andere Zeichen auszugeben).

INT 20 ruft eine andere Unterbrechung auf, die das Programm beendet und die Kontrolle  an DOS zurückleistet.

Überprüfen Sie, dass der Wert des IP Registers 100 ist. Jetzt können Sie das Programm ausführen (lieber nicht mit dem T Befehl, sonst werden die Befehle der Unterbrechungen auch schrittweise ausgeführt, und das könnte ziemlich lange dauern…, sondern) mit dem G (Go) Debug-Befehl.

 

Jetzt, dass wir schon ein selbstendiges Programm haben, können wir es als ein .COM Programm an die Festplatte schreiben um es direkt von dort auszuführen.

Ein .COM Programm kann von DOS sehr einfach gestartet werden, man soll nur seinen Namen in eine DOS Kommandozeile eingeben.

Unser Programm hat noch keinen Namen, wir sollen es einen geben. Geben Sie im Debug das folgende Befehl ein:

-         N STERN.COM

Dieser Befehl gibt dem Programm einen Namen, schreibt es aber nicht an die Festplatte. Wir sollen zuerst an Debug die Anzahl der Bytes angeben, die wir an die Festplatte, in eine Datei schreiben möchten. Wenn wir mit dem U Befehl nachschauen, werden wir sehen, dass wir vier Befehle haben, und jeder ist 2 Byte groß. Das bedeutet 8 Bytes insgesamt (wir subtrachieren 100h von der erste Adresse die nach unserem Programm folgt). Wir wissen schon die Länge, diese soll aber irgendwo gestellt werden. Debug benützt das Registerpaar BX:CX für die Länge der Datei. Wir werden also den Wert 8 in CX und 0 in BX eingeben, damit sagen wir den Debug, dass unser Programm  8 Bytes lang ist.

Nachdem wir an unserem Programm einen Namen gegeben haben und die Länge ist auch bestimmt, können wir das Programm mit dem W (Write) Befehl an die Festlatte schreiben lassen:

-         W

Anmerkung (das Programm wird im Standardfall in desjenigen Verzeichnis geschrieben werden, woher Sie das debug.exe Programm gestartet haben. Wenn man auf dieses Verzeichnis kein Schreibrecht hat, kann man das Programm in eine andere Verzeichnis schreiben lassen. Dann soll man aber den Namen der Datei mit dem Pfad angeben. Z.B.:

- N C:\Temp\Stern.com)

 

Jetzt haben wir schon ein Programm Stern.com auf der Festplatte. Starten Sie es, dann wird am Bildschirm ein Stern (*) erscheinen.