Benutzername: - Remote files noch nicht unterstützt.
Adresse / Links | ||
Daten / Rechts |
Der MC16B Prozessor ist ein reiner 16 Bit CPU, d.h. alle Berechnungen und Adressen finden auf 16 Bit statt. Im Gegensatz zu vielen anderen 16 Bit Architekturen ist hier der Speicher auch in diese Einheiten geteilt (ein Wort ist die kleinste edressierbare Einheit). Wie bei einer 8 Bit CPU gibt es somit keine Endianess.
Der Prozessor besitzt 16 Allzweckregister, welche im Code mit $0 bis $15 bezeichnet werden. Ein solches Register ist exakt ein Wort groß.
Weiterhin gibt es das PC Register, welches auf den nächsten auszuführenden Befehl zeigt. Es kann mit den Sprungbefehlen verändert werden. Wird ein CPU Reset durchgeführt so wird dieses auf 0 gesetzt. Dieses Register ist ein Wort groß.
Zusätzlich gibt es noch das LINK Register, welches bei einem Sprung auf den vorherigen PC gesetzt wird. Damit sind Unterprogrammaufrufe möglich. Dieses Register ist ein Wort groß.
Es gibt drei Flags (jeweils 1 Bit Register), welche bei Rechnen (ALU) Operationen eventuell verändert werden. Sie heißen CARRY (z.B. für Additonsübertrag), SIGN (wenn das Ergebnis negativ war = 15 Bit gesetzt) und ZERO (wenn das Ergebnis 0 war). Die Flags können bei den Sprungbefehlen als Bedingung verwendet werden.
Operation | Pseudocode |
---|---|
add $A,$B | $A := $A+$B |
adc $A,$B | $A := $A+$B+CARRY |
sub $A,$B | $A := $A-$B |
sbb $A,$B | $A := $A-$B-CARRY |
rsub $A,$B | $A := $B+$A |
cmp $A,$B | Setzt nur Flags wie sub $A,$B |
and $A,$B | $A := $A & $B |
test $A,$B | Setzt nur Flags wie and $A,$B |
xor $A,$B | $A := $A xor $B |
or $A,$B | $A := $A | $B |
mov $A,$B | $A := $B, ändert keine Flags |
shr $A,$B | $A := $A >> $B, zieht 0 nach |
ror $A,$B | $A := $A >> $B, zieht CARRY nach |
sar $A,$B | $A := $A >> $B, zieht MSB von $A nach |
rol $A,$B | $A := $A << $B, zieht CARRY nach |
shl $A,$B | $A := $A << $B, zieht 0 nach |
Operanden | Beispiel | Anmerkungen |
---|---|---|
op $A, $B | add $0,$4 | Reg $0 := Reg $0 + Reg $4 |
op $A, #B | and $8,99 | Reg $8 := Reg $8 & 99 |
op $A, short #B | add $11, 1 | für kleine Werte -31 .. 31 |
op $A, long #B | and $12, 0xFF00 | für alle Werte |
Wenn als zweiter Operand ein Wert angegeben wird, so wird ohne Angabe von short / long üblicherweise die long Variante verwendet.
Sind beide Operanden Register, oder ist der rechte Operand ein short Wert, so benötigt der Opcode nur ein Wort, sonst zwei.
Ein Wert kann auch ein konstanter Ausdruck sein (d.h. vom Assembler zur Assemblierzeit auswertbar).
Die Schieberegister shr,ror,sar,rol,shl können auch ohne zweiten Operanden verwendet werden. Dies entspricht einem Shift um eins mit der kurzen Kodierung.
Statt add $A, short 1 kann auch inc $A benutzt werden; für sub $A, short 1 kann dec $A,1 verwendet werden.
Mit neg $A wird das Ergebnis negiert, mit not $A invertiert (Kurzschreibweise des rsub Befehls)
Keine Operation wird mit nop (ohne Parameter) durchgeführt.
Operation | Umgangssprachlich | Flags |
---|---|---|
jb | vorzeichenlos < | CARRY == 1 |
jae | vorzeichenlos >= | CARRY == 0 |
jl | vorzeichnbehaftet < | SIGN == 1 |
jge | vorzeichnbehaftet >= | SIGN == 0 |
jbe | vorzeichenlos <= | ZERO == 1 | CARRY == 1 |
ja | vorzeichenlos > | ZERO == 0 & CARRY == 0 |
jle | vorzeichnbehaftet <= | ZERO == 1 | SIGN == 1 |
jg | vorzeichnbehaftet > | ZERO == 0 & SIGN == 0 |
je | == | ZERO == 1 |
jne | != | ZERO == 0 |
jmp | immer | ohne Bedingung |
Operanden | Beispiel | Anmerkungen |
---|---|---|
op $A | jmp $6 | PC := $6 |
op #B | jmp loop | PC := loop |
op near #B | jmp near loop | für kleine Werte -511 .. 511 |
op far #B | jmp far library | für alle Werte |
Wird near oder far weggelassen, so wird near genommen. Sprünge mit einem Wert sind immer relative Sprünge im Vergleich zum PC nach dem Befehl.
Sprünge mit Registern sind immer absolute Sprünge.
Bei jedem durchgeführten Sprung wird der vorherige PC in ein spezielles Link register gesichert. Mit dem Befehle loadlink $A wird das Linkregister in ein Allzweckregister kopiert.
Mit load $A,[$B] wird der Wert von Adresse aus Register $B in Register $A geladen.
Mit store [$B],$A wird der Wert aus Register $A an die Adresse von aus Register $B gespeichert.
Es gibt keine Möglichkeit, direkt Werte zu speichern, oder Adressen direkt anzugeben. Diese müssen vorher z.B. mit einem mov Befehl in ein Register geladen werden.
Man kann in einem load Befehl problemlos das Adressregister als Zielregister verwenden: load $A,[$A] ist möglich, die Adresse wird erst benutzt und anschließend wird das Register mit dem Wert überschrieben.
Der Assembler kann Ausdrücke auswerten. Somit kann man an allen Stellen, wo konstante Werte erlaubt sind auch konstante Ausdrücke schreiben. Somit ist mov $0,8+1 gleichbedeutend zu mov $0,9. Nicht erlaubt sind verbindungen von Ausdrücken mit Register, da diese nicht mehr konstant auswertbar wären.
Zur Vereinfachung der Sprungbefehle kann man zu Begin einer Zeile ein Label voranstellen. Damit wird die nun kommende Programmstelle benannt. Ein Label besteht aus einem Bezeichner gefolgt von einem Doppelpunkt.
Labels können hierarisch organisiert werden, dazu werden die verschiedenen Ebenen mit einem Punkt getrennt. Damit ist es z.B. möglich lokale Labels innerhalb einer Funktion zu deklarieren.
func1:
mov $0,5
.loop: dec $0
jnz .loop
func2: and $2,4
.loop: xor $2,0xFF
je .loop
func3:
.part1: mov $10,99
jmp .end
.part2: mov $10,11
.end:
func4: jmp func3.part1
Ähnlich wie Labels können auch Konstanten definiert werden. Statt des Doppelpunktes verwendet man nach dem Bezeichner ein Gleichheitszeichen gefolgt vom dem konstanten Ausdruck.
SizeOfArray=20*40
mov $0,SizeOfArray
Das Berechnen der Bitmaske für die Operandendisplays kann etwas aufwändig werden. Hier gibt es ein eingebautes Tool um den Code zu ermitteln.
MC16B CPU entwickelt von ThiloA, brainsh und Merlin09
HTML Assembler Version 0.1
Dieser HTML / JavaScript Assembler verwendet
Diese MC16b Ide + Assembler + Emulator wurde entwickelt von Thilo Ackermann und ist unter MIT Lizenz freigegeben.