Version 2.0 Aktualisiert: 30.03.04



==> Die für den Anfang besonders wichtigen Befehle wurden mit einem roten "!" versehen! Die Liste wurde um einige Opcodes ergänzt, welche in der Regel am Ende der Beschreibung in eckigen Klammern stehen. Hat ein Befehl mehr als ein Opcode, dann werden diese mit einem ; getrennt. Alle Opcodes sind Hex-Werte! (Ein Opcode ist quasi der übersetzte Assembler Befehl)
ADD
Addiere beide Operanden und lege das Ergebnis in den Ersten.
Beispiel:
mov  ah,7
mov  bh,3
add  bh,ah   ;bh = 10

AND
Logische UND-Verknüpfung: Der Zieloperand wird bitweise mit dem Quelloperand verknüpft.
AND Ziel,Quelle. Das Ergebnis wird im Zieloperand abgelegt.
Beispiel:
mov ah,10010100b  ;ah=10010100b
mov al,10110101b  ;al=10110101b
and ah,al         ;ah=10010100b

!CALL
Aufruf eines Unterprogramms. Der IP wird auf dem Stack gespeichert, dann wird der IP
mit der Adresse des CALL-Befehls geladem, RET kehrt vom Unterprogramm zurück.
Beispiel:
.
.
call Write        ;Das Unterprogramm Write aufrufen
.
.
Write  PROC  Near ;Deklaration des Unterprogramms
mov  ah,09h       ;Beispielcode
int  21h
ret               ;Zurück
Write  ENP        ;Ende der Prozedur

CALL ist das Gleiche wie CALL NEAR.
Mit CALL FAR Kann man Prozeduren aufrufen, die nicht im selben Segment liegen.
Bei CALL FAR muss man RETF verwenden.
[E8;FF;9A]

CLC
Clear Carry Flag d.h. CF = 0. Das Carry Flag wird oft als Schalter verwendet, 
z.B  um Fehler in einem Unterprogramm anzuzeigen. Mit CLC kann das Carry vorher
gelöscht werden. 

CLD
Clear Direction Flag: Setzt das Direction Flag auf 0. Damit erfolgen alle 
Stringoperationen (z.B. stosb) von links nach rechts (default!!).

CLI
Lösche das Interruptflag. Die extern maskiebaren Interrups werden gesperrt.
D.h. es werden z.B Interrupts die vom Keyboard oder von der Maus erfolgen gesperrt.
Dies ist vor allem dan erforderlich, wenn Zeitkritische Operationen ablaufen, die nicht
gestört werden sollen.

!CMP
Mit CMP werden zwei Operanden verglichen. Die Operanden müssen gleich gross sein,
d.h. entweder Byte/byte oder Word/word. Das Ergebnis des Vergleichs kommt ins Statusregister.
Beispiel:
mov ax,0FFFFh
cmp ax,Var1
je  Gleich       ;Wenn gleich springe zum Label Gleich
jg  Grösser ;Wenn grösser springe zum Label Grösser
jl  Kleiner      ;Wenn kleiner springe zum Label Kleiner
[3A;3B;3C;3D;38;39;80;81;83]
 
CMPS
CMPSB (Compare Strings Bytes) / CMPSW (Compare Strings Words)
Mit dem Befehl REP /REPNE können mehrere Daten verglichen werden. 
Der Befehl CMPS vergleicht zwei Strings miteinander, wobei der erste Operand über 
das Registerpaar DS:SI  und der zweite Operand über ES:DI adressiert wird. Nach dem
Vergleich werden SI und DI automatisch erhöht oder bei gesetztem Direction Flag erniedrigt.
Das Ergebnis des Vergleichs kommt ins Statusregister.
Beispiel:
lea  di,String1      ;Wenn di auch im Datensegment einfach ES=DS z.B. so: push ds  pop es
lea  si,String2      ;lea si,String2 entspricht mov si,OFFSET String2 
mov  cx,12           ;Anzahl der Wiederholungen von REP
rep  cmpsb           ;Vergleichen
je   Weiter          ;Springen wenn gleich

!DEC
Decrementieren um 1. D.h. es wird 1 vom Operanden subtrahiert.
Gegenteil: INC.
Beispiel:
mov  ah,09h
dec  ah     ;ah=08h

Oder als LOOP Ersatz (glaub sogar schneller):

           mov  cx,4
Schleife:  
           dec  cx
           .
           .
           jnz  Schleife

Oder um eine Variable zu Dekrementieren:
dec  Var1
 
DIV
Dividiert AX bzw. das Registerpaar DX:AX durch den Divisor.

Divident    /   Divisor         =  Quotient     Rest
AX (16 Bit) /  Operand (8 Bit)  =    AL           AH
DX:AX       /  Operand (16 Bit) =    AX           DX

Beispiel:
mov ax,300    ;AX = Divident
mov bh,12     ;bh = Divisor
div bh        ;AX/BH = AL(Quotient)  AH(Rest)


HLT
Der Befehl HLT (HaLT) hält den Prozessor an bis ein Interrupt erfolgt.

IN
In liest ein Byte oder Word aus einem Port in al oder ax ein.
Beispiel:
in  al,60h   ;Byte vom Tastaturpuffer in al lesen

INC
Addiert (Incrementiert) den Operanden um 1.
Beispiel:
mov  ax,07h
inc  ax      ;ax=08h
inc  Var1    ;Incrementieren einer Variablen im Speicher

!INT
Löst einen Interrupt aus. Wenn ein Interrupt über den INT Befehl ausgelöst wird
passieren zwei Dinge:
1. Das Flagregister wird auf den Stack gepusht
2. Ein FAR CALL wird ausgelöst zu der Segment:Offset Adresse die sich in der 
   Interruptvektor-Tabelle befindet (dort umgekehrt abgespeichert Offset:Segment).
   Bei dieser Adresse befindet sich der Code des Interrupts. Die Rückkehr ins
   Programm erfolgt durch einen IRET Befehl.
[CD; Speziell Int 3: CC]
 
Diese Tabelle besteht aus 256 Doppelwörtern und reicht von 0000:0000 bis 0000:0400h.
Die Offset-Adresse der Interruptvektoren kann man errechnen indem man die Interruptnummer 
mit 4 multipliziert. Die Segmentadresse ist immer 0000h. So ist z.B. die Adresse für den
Interrupt 21h in der Tabelle an der Stelle 21h*4 = 84h also 0000:0084h.
    
IRET
Rückkehr aus einer Interruptroutine. CS:IP und das Statusregister (Flags) wird
vom Stack genommen.

!JMP
Unbedingter Sprung zur angegebenen Adresse bzw. Label.
JMP FAR kann auch zu Zielen springen, die nicht im eigenen Segment liegen.
Beispiel:
        jmp   Weiter
           . 
           .
           .
Weiter:
[EB;E9;FF;EA]


!Bedingte Sprünge:
JE/JNE/JZ/JNZ/JC/JNC/JG/JL/JLE/JGE/JNLE/JNGE sind wichtige bedingte Sprünge.
Sie werden nur ausgeführt, wenn eine bestimmte Bedingung erfüllt ist.
JE: Jump if equal. Springe wenn gleich.
Beispiel:
cmp  ax,Var1    ;vergleicht die Variable Var1 und ax indem beide subtrahiert werden.
je   Gleich     ;Sind sie gleich gross, ist das Ergebnis 0 und das Zero Flag wird
                ;gesetzt. JE prüft dieses Flag und springt wenn es gesetzt also 1 ist. 

JE  : Jump if equal. Springe wenn gleich. [74;0F84]
JNE : Jump if not equal. Springe wenn nicht gleich.  [75;0F85]
JZ  : Jump if zero. Springe wenn 0. Eigentlich das Gleiche wie JE, es hat sogar den gleichen
     Opcode, d.h. es wird in die gleiche Zeichenfolge übersetzt. Aber: Übersichtlicher
     wenn man nicht nur eins verwendet. [74;0F84]
JNZ : Jump if not zero. Springe wenn nicht 0. [75;0F84]
JC  : Jump if Carry. Springe wenn Carry Flag gesetzt. [72;0F82]
JNC : Jump if not Carry. Springe wenn Carry Flag nicht gesetzt. [73;0F83]
JG  : Jump if greater. Springe wenn grösser. [7D;0F8D]
JNG : Jump if not greater. Springe wenn nicht grösser. [7E;0F8E]
JL  : Jump if less. Springe wenn kleiner. [7C;0F8C]
JNL : Jump if not less. Springe wenn nicht kleiner. [7D;0F8D]
JLE : Jump if less-equal. Springe wenn kleiner oder gleich.
JGE : Jump if greater-equal. Springe wenn grösser gleich.
JNLE: Jump if not less-equal. Springe wenn nicht kleiner oder gleich.
JNGE: Jump if not grater-equal. Springe wenn nicht grösser oder gleich.

Bedingte Sprünge haben lediglich eine Reichweite von -128 bzw. +127 Bytes. Es kann
daher schnell passieren, dass ein Ziel ausserhalb der Reichweite liegt. In diesem Fall
meldet der Assembler einen Fehler der wie folgt behoben werden kann:

Wenn es so nicht geht:

Anfang:
           .
           .      ;Über 128 Bytes Programmcode
           .
          cmp  ax,00h
          je   Anfang   ;Sprungziel zu weit entfernt. --> Fehler
          mov  bx,40h

Dann geht es so:

Anfang:         
           .
           .      ;Über 128 Bytes Programmcode
           .
          cmp  ax,00h
          jne  Weiter1   ;Sprungziel zu weit entfernt. --> Fehler
          jmp  Anfang
Weiter1:  mov  bx,40h

        
!LEA
LEA Ziel,Quelle (Load Effective Address). LEA berechnet den Offset und speichert das Ergebnis
im Zieloperand, d.h. im angegebenen Register.
Beispiel:
lea  dx,String1
mov  dx,OFFSET String ;hat fast den selben Effekt, LEA ist besser.

LODS
Lädt über das DS:SI Register ein Byte in das AL Register (LODSB) oder ein Wort
in das AX Register (LODSW). Danach wird das Si Register entsprechend (Byte oder Word) um
1 oder 2 erhöht ist das Direction-Flag gesetzt wird es erniedrigt.


!LOOP
Loop springt zur angegebenen Adresse bis das CX Register null ist. Loop subtrahiert vom
CX Register 1 und überprüft CX auf null. Ist CX nicht null springt LOOP zur angegebenen
Adresse, wenn LOOP null ist wird das Programm mit dem nächsten Befehl fortgeführt. 
Beispiel:
           mov  cx,11   ;Die Schleife wird 11 mal durchlaufen
DoLoop:    
           nop          ;zu wiederholende Befehle hier: NOP
           
           Loop  DoLoop


LOOPE-LOOPZ
Springt zur angegebenen Adresse, wenn CX ungleich null ist und das Zero-Flag gesetzt ist.
Beispiel:
          mov  cx,11   ;Die Schleife wird max. 11 mal durchlaufen
DoLoop:    
           nop          ;zu wiederholende Befehle hier: NOP
           cmp  ax,Var1
           Loope DoLoop ;Springe wenn cx ungleich null und ax und Var1 gleich

LOOPNE-LOOPNZ
Springt zur angegebenen Adresse, wenn CX ungleich null ist und das Zero-Flag nicht gesetzt ist.
Beispiel:
          mov  cx,11   ;Die Schleife wird max. 11 mal durchlaufen
DoLoop:    
           nop          ;zu wiederholende Befehle hier: NOP
           cmp  ax,Var1
           Loope DoLoop ;Springe wenn cx ungleich null und ax und Var1 ungleich


!MOV
Der Befehl MOV Ziel,Quelle (engl. move bewegen) überträgt ein Byte oder Word vom 
Quelloperanden in den Zieloperanden. Der Quelloperand selbst wird nicht verändert.
Quell und Zieloperand müssen gelich gross sein, etwas wie z.B. mov al,cx funktioniert
nicht. Auch kann man mit MOV nicht die Register CS, IP und das Flagregister nicht verändern.
Mögliche Operandenkombinationen:

mov  Reg,Reg         Bsp: mov  cx,ax     
mov  Reg,Seg. Reg    Bsp: mov  ax,ds
mov  Reg,Mem         Bsp: mov  cx,Variable
mov  Reg,Wert        Bsp: mov  bx,40h
mov  Seg. Reg,Reg    Bsp: mov  es,cx
mov  Seg. Reg,Mem    Bsp: mov  ss,old_ss
mov  Mem,Reg         Bsp: mov  Variable,ax
mov  Mem,Seg. Reg    Bsp: mov  Var,es
mov  Mem,Wert        Bsp: mov  Var2,12

Abk.: Reg=CPU Register, Seg. Reg=Segment-Register, Mem=Memory(Speicher) 

MOVS 
MOVSB (MOVe String, Byte) bzw. MOVSW (MOVe String, Word) überträgt ein Byte oder Word
das durch DS:SI adressiert wird nach ES:DI, MOVS stellt also eine Kombinatiom von LODS und STOS
dar. Nach jeder Übertragung werden SI und DI je nach Direction Flag erhöht (default) oder 
erniedrigt (je nach Direction Flag - siehe auch STD bzw. CLD). Mit REP können mehrere Daten
kopiert werden.
Beispiel:
lea  si,Quelle  ; Woher kopieren ?
lea  di,Ziel    ; Wohin kopieren (vorher es setzen)
mov  cx,Laenge  ; Wieviel kopieren ?
rep  movsb      ; Kopieren

MUL
MUL Multipliziert den vorzeichenlosen Wert des Operanden mit dem vorzeichenlosen Wert im 
Akkumulator miteinander. Man unterscheidet zwischen Byte und Word Multiplikation.

Byte Multiplikation:
Der erste Wert muss sich im AL Register befinden, der andere wird hinter MUL angegeben und muss
sich in einem 8 Bit Register oder einer Byte Speicherstelle befinden. Das Ergebnis wird in AX 
abgelegt.

Beispiel:
mov  bl,10
mov  al,8
mul  bl     ;==> ax = 80
 
mov  al,20
mov  Var1,20
mul  Var1   ;==> ax = 400

Word Multiplikation:
Ein Operand muss sich im AX Register befinden, der andere in einem 16 Bit Register oder einer
Word Speicherstelle. Der High-Teil des Ergebnisses wird in DX abgelegt, der Low-Teil in AX.

Beispiel:
mov  ax,350
mul  ax     ;DX:AX = AX * AX
Weiter zu Teil 2.
Zurück Weiter Inhalt