- die eine Folge
als Quelle
und eine als Ziel benützen (MOVSB, MOVSW,
CMPSB, CMPSW)
- die benützen nur
eine Folge als Quelle
(LODSB, LODSW)
- die benützen nur
eine Folge als Ziel
(STOSB, STOSW, SCASB, SCASW)
(Move String = MOVS
Compare String = CMPS
Load String = LODS
Store String = STOS
Scan String = SCAS)
- Typ der
Elemente (Oktett oder Wort)
=> bezeichnet durch dem letzten
Buchstabe
des Befehls (B=byte, W=word); beide
Folgen sind
vom gleichen
Typ
- die Adresse
des ersten Elementes - ist eine folgenderweise
gegebene
FAR Adresse
- in DS:SI - für die Quell-Folge
- in ES:Di - für
die Ziehl-Folge
- Direktion der
Durchlauf => ist
durch dem Wer von DF (Direktionsflag)
bezeichnet (wenn 0 - von kleinere Adressen zu größeren, wenn
1 -
von
größere Adressen zu kleineren; siehe
CLD, STD)
- Anzahl der
Elemente => wenn gebraucht, wird es im CX
gespeichert
LODSB - Es wird das Oktett von der Adresse <DS:SI> in Al geladen
Wenn DF=0, dann inc(SI), sonst dec(SI)
LODSW - Es wird das Wort von der Adresse
<DS:SI> in AX geladen
Wenn DF=0, dann SI:=SI+2, sonst SI:=SI-2
STOSB - Das Oktett von Al wird an die Adresse <ES:DI> gespeichert
Wenn DF=0, dann
inc(DI), sonst dec(DI)
STOSW - Das Wort von AX wird an die Adresse <ES:DI> gespeichert
Wenn DF=0, dann
DI:=DI+2, sonst DI:=DI-2
MOVSB - Das Oktett von der Adresse <DS:SI> wird an die Adresse
<ES:DI> gespeichert.
Wenn DF=0, dann
SI:=SI+2, DI:=DI+2, sonst dec(SI),
dec(DI)
MOVSW - Das Wort von der Adresse <DS:SI> wird an die Adresse
<ES:DI> gespeichert.
Wenn DF=0, dann
inc(SI), inc(DI), sonst SI:=SI-2, DI:=DI-2
Beispiel: Wir
haben eine gegebene Quell-Folge (die Elemente sind
Wörter). Kopieren Sie
es in eine andere Ziel-Folge. Wir nehmen an,
dass wir die Anzahl der Elementen
wissen.
mov CX, dim_Reihe
mov SI, OFFSET Quell_Folge
mov AX, SEG Quell_Folge
mov DS, AX
mov DI, OFFSET Ziel_Folge
mov AX, SEG Ziel_Folge
mov ES, AX
CLD
Wieder:
LODSW
STOSW
;(oder direkterweise mit MOVSW)
SCASB - CMP AL, <ES:DI>
Wenn DF=0, dann inc(DI), sonst dec(DI)
(veräderte Flags: OF, SF, ZF, AF,
PF, CF)
SCASW - CMP AX, <ES:DI>
Wenn DF=0, dann DI:=DI+2, sonst DI:=DI-2
(OF, SF,
ZF, AF, PF, CF)
CMPSB - CMP <DS:SI>, <ES:DI>
Wenn DF=0, dann inc(SI), inc(DI), sonst dec(SI), dec(DI)
(OF, SF,
ZF, AF, PF, CF)
CMPSW - CMP <DS:SI>,
<ES:DI>
Wenn DF=0, dann SI:=SI+2, DI:=DI+2, sonst SI:=SI-2,
DI:=DI-2
(OF, SF,
ZF, AF, PF, CF)
Beispiel:
Es ist eine
Okett-Folge gegeben. Finden Sie den letzten "0" Charakter.
;... es sind
alle Daten über der Ziel-Folge
geladen
MOV
MOV CX, Dim_Folge
STD
suche_weiter: ; wir suchen weiter...
SCASB
JE Gefunden
...
Gefunden:
DEC DI ; wir kehren zurück zum
Charakter der noch
;
vor dem
Inkrementierung von DI gefunden
war
Prefix_Befehl Instruktion_über_Reihe
ist gleich wie
Wieder:
Instruktion_über_Reihe
... wo Prefix_Befehl kann REP (gleich wie REPE - Repeat While
Equal -),
REPZ (Repeat While Zero) sein, der die Befehle SCAS_ oder CMPS_
wiederholt
bis CX 0 wird, oder bis es
eine Ungleichartigkeit
getroffen
wird ( => ZF=0)
... oder kann REPNE (Repeat While Not Equal) oder
REPNZ (Repeat
While Not Zero) sein, der die Befehle SCAS_ oder CMPS_ wiederholt
bis CX 0 wird, oder bis
es eine Gleichheit
getroffen wird ( =>
ZF=1)
Anmerkungen:
- Bei der
Operationen über Folgen werden die Flags nicht verändert
nach der veränderungen von Register SI, DI oder
CX
- LODS_, STOS_, MOVS_ - verändert kein Flag, weil
SCAS_ und CMPS_
verändert die Flags dem durchgeführte Komparationsbefehl
entsprechend.
**********************************************************************
Ergänzungen
- Man sollte doch
auch den Norton Guide lesen
- Schleife:
Allgemeine Form:
Rückkehr_Label:
Befehle
- im allgemeinen Fall werden die Befehle CX-mal (der Wert,
der schon nach vorne in CX hingelegt war) wiederholt
- wenn
die Kondition für Wiederholung komplexer ist kann man die
andere warianten benützen LOOPE (LOOP While Equal), LOOPNE (LOOP
While Not Equal) (wenn vor dem
Instruktion,
Komparation, usw. - wird man von der
Schleife
herauskommen wenn CX 0 wird oder wenn
man eine "Ungleichartigkeit"
trifft, bei LOOPE, bzw. eine
"Gleichheit" für
LOOPNE)
(siehe Beispiel.asm)
- Unterprogrammen
Name_Unterprogramm PROC
Befehle...
RET
Name_Unterprogramm ENDP
Es wird (im
allgemeinen) mit
CALL Name_Unterprogramm
gerufen.
Beispiel:
; Es ist eine Oktett-Folge gegeben. Bilden Sie eine neue
Folge,
; die wird von der
erste Reihe die Elemente enthalten die mehrere
; 1-Bits als
0-Bits haben.
assume ds:data,cs:code
data segment
a db
47h,65h,35h,41h
d equ $-a
r db d dup(0h)
data ends
code segment
start:
; die nötige Adressen in Register laden
mov ax,data
mov ds,ax
mov es,ax
mov si,offset
a
mov di,offset
r
mov cx,d
cld
wieder:
lodsb
call zaehlen
mov bh,8
sub bh,bl ;bh=nr 0, bl=nr 1
cmp bl,bh
jbe nichtstun
stosb
nichtstun:
loop wieder
jmp ende
zaehlen
proc ;
zählt die Bits 1 von Al
push cx ;
CX speichern
mov cx,8
xor bx,bx
noch:
rcl al,1
adc bl,0
loop noch
;in BL haben wir die Anzahl
der Bits 1
pop cx ;
CX zurücklegen
ret ;
Rückkehr vom Unterprogrammm
zaehlen endp
ende:
mov ax,4C00h
int 21h
code ends
end start