Adok's Way to Assembler
Folge 1

Hier ist mein Kurs fr alle, die Assembler lernen wollen! Wir fangen praktisch
bei  Null  an,  so  da  jeder  anfangen  kann,  egal  ob  er  Einsteiger oder
Programmier-Profi  ist.  Voraussetzung fr diesen Kurs  ist  es, da ihr einen
Assembler  habt.  Im  Kurs  selbst beziehe  ich  mich  auf den Turbo Assembler
(TASM),  der den meisten Borland-Programmiersprachen kostenlos beiliegt. Falls
ihr  den Turbo Assembler nicht habt,  knnt ihr auch den kompatiblen Microsoft
Makroassembler  (MASM) verwenden, bei dem allerdings die Kommandozeilenaufrufe
zum Compilieren und Linken anders aussehen.

+++ Unser Komm-Puter +++

So, beginnen wir einmal mit einem kurzen berblick ber das Innere des Compis.
Das  Herz  des Computers ist der Prozessor,  auch CPU genannt. Hier werden die
Assemblerbefehle  verarbeitet.  Das  funktioniert,  einmal  ganz  grob gesagt,
folgendermaen:  Der  Prozessor ist in zwei  Teile geteilt. Der eine Teil holt
sich die Befehle aus dem Arbeitsspeicher und gibt sie in die Warteschlange des
Prozessors.  Der zweite Teil des Prozessors holt  sich dann der Reihe nach die
Befehle  aus  der Warteschlange, bersetzt  und verarbeitet sie. Dabei spricht
er,  je  nach Befehl, den  Arbeitsspeicher  an, rechnet einfache arithmetische
Operationen aus oder gibt den Befehl an die Peripheriegerte weiter.

Das  ist  im  Moment alles, was wir  ber  den Prozessor wissen mssen. Weiter
geht's  mit dem Arbeitsspeicher, dem RAM. Wie wohl jeder wei, kann man diesen
Speicher  frei  beschreiben  und lesen, nur  gehen  die Informationen nach dem
Ausschalten wieder verloren. Jede Speicherstelle im RAM wird Adresse genannt.

+++ DOS' Speicheradressierung +++

Bei  dieser  Gelegenheit  knnen wir  gleich  die Speicheradressierung von DOS
besprechen:  Da in DOS 1 MB Speicher adressiert werden kann, im Real Mode (dem
Prozessormodus,  in welchem DOS normalweise  arbeitet) die Adreleitung jedoch
nur  16  Bit  breit ist (fr 1 MB  Speicher  bruchte man 20 Bit), mu man ein
bichen  tricksen.  Der  Speicher wird in  DOS  nicht linear, sondern ber ein
Segment und einen Offset adressiert. Das Segment wird mit 16 multipliziert und
der Offset dazuaddiert - dann hat man die "physikalische" Adresse.

Ein Segment ist 64 KByte gro. Folglich kann die Offsetadresse zwischen 0h und
FFFFh  (eine  Hexadezimalzahl, welche der  Dezimalzahl  65535 entspricht) gro
sein.  Das Segment kann ebenfalls 0h bis FFFFh sein. Wenn man mal nachrechnet,
ergibt  sich,  da manche  Segment-Offsetkombinationen einander berschneiden.
Aber gehen wir vorlufig nicht darauf ein, damit es nicht zu kompliziert wird.

Jau, und die Adresse wird immer in der Form xxxx:xxxx geschrieben, und zwar in
hexadezimalen  Zahlen, da diese die Basis 16  haben und man somit leichter die
physikalische  Adresse  berechnen kann! Falls  jemand nur Bahnhof versteht: In
unserem  dezimalen  Zahlensystem haben wir die  Basis  10. Wir haben auch zehn
Ziffern:  von 0 bis 9. Die Dezimalzahl 10 ist, wie wohl jedes Baby wei, zehn.
Beim  Hexadezimalsystem  mit  der  Basis 16  haben  wir  auch  16 Ziffern. Man
verwendet  hierbei nach der 9 die Buchstaben A bis F, also geht das Hex-System
von  0  bis F. Nach F folgt dann  10,  und diese Zahl ist im Hexadezimalsystem
nicht zehn, sondern sechzehn! Zur besseren Unterscheidung schreibt man deshalb
nach  jeder  Hexadezimalzahl ein kleines h.  Alles klar? Wenn nicht, schaut in
einem Mathe-Lexikon nach!

+++ E/A-Ports +++

Weiters  finden  wir im PC die  Peripheriegerte (Drucker, Monitor, Tastatur &
Co.)  und  Zusatzkarten. (Nicht Asse,  Piks und Konsorten, sondern Soundkarte,
Grafikkarte  und  so weiter! ;) ) Diese  Teile  werden alle ber die E/A-Ports
angesprochen.

So,  das wre einmal alles, was wir  ber das Innere des Compis wissen mssen!
Bevor  wir  das erste Assembler-Programm  schreiben  knnen, mssen wir jedoch
noch etwas Theorie lernen...

+++ Register +++

Register  -  genauer gesagt, Prozessorregister,  denn auch die Grafikkarte und
andere  Peripherie kann eigene Register  haben - sind eigentlich 16-Bit-breite
Integer-Variablen,  die  Werte von 0 bis  65535  annehmen knnen, nur sind sie
schneller  als  normale Variablen (die  ja  im Hauptspeicher abgelegt werden),
weil  die Register ein Bestandteil des  Prozessors sind. Es gibt mehrere Arten
von Registern:

- Allgemeine Register: Diese  sind  frei  verwendbar,  allerdings  mssen  bei
  manchen  ASM-Befehlen  in  ihnen  bestimmte  Werte stehen. Folgende Register
  werden bei folgenden Befehlen zu folgendem Zweck benutzt:

  AX = Meistbenutztes allgemeines Reg. Bei Interrupt-Aufrufen (Erklrung folgt
       spter)  steht  hier meistens die Funktionsnummer. Auerdem wird AX fr
       manche Rechenoperationen bentigt.
  BX = Parameter fr Interrupts, indirekte Adressierung (z.B. beim MOV-Befehl,
       den wir noch SPTER besprechen werden).
  CX = Zhlreg fr Schleifen.
  DX = Wird von Befehlen, die die E/A-Ports  ansprechen,  verwendet.  Auerdem
       wird das DX-Register auch von einigen Rechenoperationen verwendet, wenn
       AX "nicht mehr reicht".

  Jedes allgemeine Reg lt sich in zwei 8-Bit-Regs teilen, die dann nicht mit
  X,  sondern  mit  H bzw. L enden. Genauer gesagt: Ein 16-Bit-Reg wie AX lt
  sich als vierstellige Hexadezimalzahl darstellen. Die  oberen  zwei  Stellen
  (Hi-Byte) sind AH, die unteren (Lo-Byte) AL. Somit drfte auch geklrt sein,
  wozu  Hexadezimalzahlen  gut  sind:  8  Bit  (1 Byte) lassen sich durch zwei
  Hex-Stellen, 16 Bit (1 Word) durch vier  Hex-Stellen  darstellen.  Noch  ein
  Beispiel zur Vertiefung:

  AX = 1234h => AH = 12h, AL = 34h.

- Segmentregister:  Was  die  Segmente  sind,  haben  wir  ja  schon  bei  der
  Adressierung des Arbeitsspeichers in DOS geklrt. In diesen Segmentregistern
  wird nun die Segmentadresse des jeweiligen Segments  (schon  wieder  so  ein
  Wortspiel)  angegeben.  Dabei gibt es mehrere Segmente, die fr verschiedene
  Aufgaben GEDACHT sind. Ich sage 'gedacht', weil  man  sie  auch  fr  andere
  Zwecke mibrauchen kann!  So lassen sich mit einem einfachen Trick Variablen
  auch im Codesegment anlegen. Dann kann man gleich ein Segment einsparen, was
  fr COM-Dateien essentiell ist - siehe unten.  Doch nun zur bersicht, damit
  jeder versteht, wovon ich quassle.

  CS = Zeigt auf das Codesegment, in dem (normalerweise, hehe) die ASM-Befehle
       eines Proggys (also das eigentliche Proggy) steh[en/t].
  DS = Zeigt auf das Datensegment, in dem die Variablen des Proggys stehen.
  ES = Kann  auf ein  beliebiges Segment  im RAM  zeigen,  das frei  verwendet
       werden darf!
  SS = Zeigt   auf   das   Stacksegment,   in  dem  meistens   Daten  temporr
       zwischengespeichert werden.

  WICHTIG:  COM-Dateien drfen nur ein Segment haben, nmlich das Codesegment!
  Deshalb mu man etwas tricksen, wenn man Variablen in COMs  verwenden  will.
  Das werden wir aber noch spter besprechen.

- Weitere  Register, die man meistens frei verwenden kann, sind BP, SI und DI.
  BP  wird in Hochsprachen zum Adressieren  von Variablen verwendet, SI und DI
  finden  vor  allem  bei den  Stringbefehlen  ihre  Verwendung. Abzuraten ist
  jedoch  von  IP (zeigt auf die nchste  Anweisung im Programm) und SP (zeigt
  auf die aktuelle Position im Stack)! Wer diese verndert, mu mindestens mit
  einem Absturz rechnen, wenn nicht etwas noch schlimmeren!

So, nun zu den...

+++ Interrupts +++

Interrupts  sind,  mal oberflchlich  betrachtet, stinknormale Unterprogramme.
Doch es gibt zwei Arten von Interrupts:

- Hardware-Interrupts und
- (tatatatamm) Software-Interrupts!

Hardware-Interrupts  werden  immer automatisch  durch  ein bestimmtes Ereignis
ausgelst.  Zum  Beispiel wird beim  Drcken einer Taste der Tastaturinterrupt
ausgelst,  der dann herausfindet, welche Taste gedrckt wurde, und sie in den
Tastaturpuffer  speichert. Das geht so schnell,  da ein normaler User gar nix
davon merkt!

Wenn  man  das  Ganze  genauer betrachtet,  gibt's  zwei  Arten  von Hardware-
Interrupts:  Whrend die wenigen nicht-maskierbaren Interrupts IMMER ausgelst
werden,  kann  man  die maskierbaren  Interrupts  mit dem Assembler-Befehl CLI
abschalten und mit STI wieder einschalten.

Das  zweite  sind  die Software-Interrupts, die  keine  Interrupts in dem Sinn
sind,  sondern  wirklich  nur Unterroutinen! Sie  werden  vom BIOS und vom DOS
bereitgestellt und dienen hauptschlich dazu, dem Coder bei der ohnehin harten
Arbeit  ein  wenig  zu  untersttzen. So  beinhaltet  der  Interrupt 33h viele
Funktionen,   mit   denen   man   ohne   groe  Schwierigkeiten  Maussteuerung
programmieren kann.

Die  Software-Interrupts  werden in Assembler  mit  dem Befehl INT aufgerufen.
Danach  folgt  die  Nummer  des  Interrupts.  Viele  Interrupts  haben mehrere
Funktionen.  So kann der BIOS-Interrupt  10h den Bildschirmmodus wechseln, den
Bildschirmmodus  abfragen, Text ausgeben, den  Cursor positionieren und vieles
mehr.  Deshalb  bentigt  man eine Funktionsnummer.  Sie  mu  meistens im AH-
Register (Erinnert ihr euch? AH ist das Hi-Byte von AX!) bergeben werden, nur
beim  Interrupt 33h im "groen" AX. Die Parameter fr die Interrupts werden in
den  anderen  Registern  bergeben.  Welche das  sind,  ist  von  Interrupt zu
Interrupt  verschieden. Auerdem haben einige Interrupts sogar Unterfunktionen
und Unter-Unterfunktionen und Unter-Unter-Unter... Diese werden meistens in AL
bergeben.

So,  das  war die Theorie! Mit  diesem Wissen werden wir das Beispielprogramm,
das in der nchsten Folge kommt, viel besser verstehen. Bis dahin noch viiiiel
Spa wnscht euch Adok!
