|
MOV kopiert ein Byte von Quelle nach Ziel.
Dabei kann das Ziel natürlich nur ein Register bzw. eine Speicherstelle sein. Quelle hingegen kann
sowohl eine Konstante als auch eine andere Speicherstelle sein, wobei letztere auch über indirekte Adressierung
angegeben werden kann.
; kopiert den Inhalt des Ports P1 zum Port P3
mov P3,P1
; schreibt 56 in das A-Register
mov a,#56
; schreibt den Inhalt der Speicherstelle 56 nach A
mov a,56
; dito, über indirekte Adressierung
mov R0,#56
mov a,@R0
Da die Assemblerinstruktionen direkt in Maschinencode übersetzt werden, sind auch nur
die Befehlskombinationen möglich, die im Prozessorkern hart verdrahtet sind. So ist beispielsweise
der Befehl mov R0,R7 von der Logik her durchaus nicht falsch, jedoch im
Befehlssatz des Controllers nicht enthalten. An solchen Stellen muss man sich anders behelfen,
beispielsweise das Wissen anwenden, dass R7 auf Speicherstelle 7 liegt: mov R0,7
ist durchaus erlaubt.
Folgende MOV-Befehle sind möglich:
MOV [Ziel],[Quelle] |
Quelle |
A |
Rn |
@Rn |
Byte im RAM |
#Konstante |
Bit im RAM |
C-Flag |
Ziel |
A |
|
X |
X |
X |
X |
|
|
Rn |
|
|
X |
X |
X |
|
|
@Rn |
X |
|
|
X |
X |
|
|
Byte im RAM |
X |
X |
X |
X |
X |
|
|
DPTR |
|
|
|
|
X |
|
|
Bit im RAM |
|
|
|
|
|
|
X |
C-Flag |
|
|
|
|
|
X |
|
|
|
Diese beiden Befehle dienen dem gleiche Zweck: Sprünge nach [Sprungziel] durchzuführen.
Das Sprungziel, zumeist als Label bezeichnet, ist eine Markierung im
Quelltext, die eine Position angibt, auf die der nach dem AJMP- oder LJMP-Befehl
als nächstes abzuarbeitende Befehl steht. Ein Label beginnt immer mit einem
Buchstaben, darf danach aber auch Ziffern enthalten. Abgeschlossen wird ein Label stets
mit einem Doppelpunkt.
AJMP [Sprungziel] |
LJMP [Sprungziel] |
hallo:
; ... mehr als 2048 Bytes an weiteren Befehlen ...
ajmp hallo2
; ... irgendetwas ...
hallo2:
; ... weitere beliebige Befehle ...
ljmp hallo
Dabei unterscheiden sich AJMP und LJMP nur in der Art der Adressierung:
AJMP (abgeleitet von absolute jump) verwendet eine 11 Bit-Adresse,
LJMP (long jump eine 16 Bit-Adresse. LJMP besitzt also eine größere
Reichweite, verbraucht dabei aber im Programmspeicher ein ganzes Byte mehr.
Wenn wie beim 89C2051 sowieso nur 211=2048 Bytes zur Verfügung stehen, reicht
AJMP immer aus. Eine elegante Lösung, um nicht ständig mit der manuellen Berechnung
der Entfernung des Sprungziels konfrontiert zu werden, besteht darin, das dem Assembler zu überlassen.
Gibt man als Mnemonic statt AJMP oder LJMP nur JMP an, so berechnet der ASEM-51 die Entfernung
des Sprungziels automatisch und setzt den jeweils passenden Befehl ein. Das angegebene Beispiel
würde man also bequemerweise mit JMP formulieren und dabei das selbe Ergebnis wie oben erhalten.
hallo:
; ... mehr als 2048 Bytes an weiteren Befehlen ...
jmp hallo2
; ... irgendetwas ...
hallo2:
; ... weitere beliebige Befehle ...
jmp hallo
|
|
Nun sind die Befehle, die mindestens 50% jedes Programms ausmachen, bereits bekannt.
Daher kann nun schon das erste Programm geschrieben werden. Dieses Programm soll
als Aufgabe die an die Pins von P3 angelegten Daten an P1 weitergeben.
Dies soll so lange geschehen, wie der Controller läuft - also in einer Endlosschleife.
Das Programm sieht etwa so aus:
$NOMOD51
$INCLUDE (89C1051.MCU)
mov P3,#11111111b ; Die Quell-Pins auf Input stellen
main:
mov P1,P3 ; die Arbeit durchführen
jmp main ; zurück zum Programmanfang springen
END ; Dem Assembler das Programmende mitteilen
Nur die blauen Zeilen sind das Programm, der Rest sind notwendige Anweisungen an den Assembler.
Die ersten beiden Zeilen teilen dem ASEM-51 - Assembler mit, für welchen
Controller assembliert werden soll. Dabei handelt es sich um eine Eigenheit des
verwendeten Assemblers. Andere Assembler haben teilweise völlig andere Mechanismen dafür.
Das END zeigt das Ende des Programmtextes an und muss jedes Assemblerprogramm abschließen.
In den Beispielen der nächsten Seiten werden diese Zeilen aus Gründen
der Übersichtlichkeit weggelassen - zum Assemblieren des Programms sind
sie jedoch unbedingt hinzuzufügen.
|