1.3 ALU-Funktion und Simulation mit VisUAL2
Präsentation: Funktionsweise ALU und Flags
Seltsame Unterschiede zwischen STM32CubeIDE und VisUAL2
- Kommentare in Cube mit // in VisUAL mit ;
- Marken werden in VisUAL ohne : am Ende definiert
- In Cube IDE kann # oft weggelassen werden
Addition, Subtraktion und Flags
Übersetze in Assembler mit Hilfe der Formelsammlung und simuliere mit VisUAL2
// C/Java-Code
r0 = 5;
r1 = r0 + 10;
r2 = r0 - r1;
r2 = r2 + 10;
; ARM-Assember-Code
mov r0,#5
add r1,r0,#10
sub r2,r0,r1
add r2,r2,#10
Flags N,Z,C,V werden mit angehängtem ‘s’ gesetzt
; ARM-Assember-Code
movs r0,#5
adds r1,r0,#10
subs r2,r0,r1
adds r2,r2,#10
Für bedingte Verzweigungen sind die Nebenergebnisse einer ALU-Operation von Interesse: Ist das Ergebnis negativ (negative), ist es Null (Zero), gibt es einen Überlauf (Carry) usw. Um diese Nebenergebnisse in Flags zu speichern, um sie bei nachfolgenden bedingten Verzweigungen verwenden zu können muss ein ‘s’ an die Assembler-Befehle angehängt werden. Rechts unten in VisUAL werden diese als Flags angezeigt N = Negative, Z = Zero, C = Carry und V = Overflow
Beobachte beim Steppen durch das Programm diese Flags rechts unten bei VisUAL2. Die Operationen verändern die Flags.
Beispiele und Aufgaben zu Flags
Unbedingte Sprünge mit b (Branch)
Um an eine bestimmte Stelle im Programm zu springen benutze den b (Branch) Befehl. Der Assembler hilft die Adresse der Einsprungstelle bequem markieren zu können mit Marken (engl. Label). Wenn eine Marke vor einen Befehl gesetzt wird, merkt sich der Assembler die Speicherstelle des Befehls hier subs mit der Adresse 0x4. Beim Sprungbefehl wird beim Assemblieren der Wert der Marke in den Maschinenbefehl eingefügt.
mov r0,#2
marke subs r0,r0,#1
b marke ; springe zu marke
Bedingte Sprünge, das Prinzip
Bedingte Sprünge werden in Abhängigkeit der Werte der Flags N,Z,C,V ausgeführt. Damit lässt sich das bedingte Verhalten von if-else, switch, while, do-while. und for realisieren. In der Formelsammlung stehen die Bedingungen. Z.B. bne also branch if not eq (equal), wenn zwei gleiche Zahlen abgezogen werden, ist das Ergebnis nicht 0, also z=0. Oder wenn das Ergebnis einer Operation nicht 0 ist, also nicht equal to Zero -> Z=0. Dann wird bei NE gesprungen.
mov r0,#2
marke subs r0,r0,#1
bne marke ; != 0 dann marke
r0 = 2;
while (r0 != 0){
r0 = r0 - 1;
}
if-else-Anweisung
Um Werte zu vergleichen werden sie schlicht von einander abgezogen also r0>10 wird zu r0-10 und dabei werden die Flags gesetzt, die leistet der cmp (Compare) Befehl. Bei signed werden auch negative Werte zugelassen. Mit welchen Werten für r0 sollten Sie den Code testen? Versuchen Sie den C-Code zu assemblieren und decken sie die rechten Lösungen zunächst ab 😁.
r0 = 11; // Werte zum Testen
if (r0>10){
r1 = 1;
} else {
r1 = 0;
}
mov r0,#11
cmp r0,#10 ; r0-10 Flags setzen
bgt true ; r0>10?
mov r1,#0
b ende
true mov r1,#1
ende
while-Schleife
Welche Werte nimmt r1 während der Schleife an, welchen Wert hat r0 nach der Schleife?
Testen Sie den Code. Erstellen Sie einen PAP.
r0 = 0;
while(r0<=5){
r1 = r0;
r0++;
}
mov r0,#0
while cmp r0,#5
bgt ende
mov r1,r0
add r0,r0,#1
b while
ende
Lösung PAP
for-Schleife
Welche Werte nimmt r1 während der Schleife an, welchen Wert hat r0 nach der Schleife? Testen Sie den Code. Erstellen Sie einen PAP.
for(r0=3;r0<6;r0++){
r1 = r0;
}
mov r0,#3
for cmp r0,#6
bge ende
mov r1,r0
add r0,r0,#1
b for
ende
Lösung PAP
do-while-Schleife
Welche Werte nimmt r1 während der Schleife an, welchen Wert hat r0 nach der Schleife? Testen Sie den Code. Erstellen Sie einen PAP.
r0 = 4;
do{
r1 = r0;
r0--;
} while (r0>0);
mov r0,#4
do mov r1,r0
subs r0,r0,#1
bgt do
ende
Lösung PAP
switch-Anweisung
Welche Werte nimmt r1 für die Testwerte 0,1,2,-1 für r0 an? Erstellen Sie einen PAP.
r0 = 2; // Werte zum Testen
switch (r0){
case 0:
r1 = 100;
break;
case 1:
case 2:
r1 = 200;
break;
default:
r1 = 0;
}
mov r0,#2
cmp r0,#0 ; case 0
beq case0
cmp r0,#1 ; case 1
beq case1
cmp r0,#2 ; case 2
beq case1
mov r1,#0 ; default
b ende
case0 mov r1,#100
b ende
case1 mov r1, #200
ende
Lösung PAP
Aufgabe while-Schleife1
r0 = 1;
while(r0<16){
r0 = r0<<1;
ausgeben(r0); // Ausgabe auf LEDs
}
Welche Werte in Binär werden ausgegeben?
Welchen Wert hat r0 nach der while-Schleife?
Assemblieren Sie (ausgeben(r0) weglassen) und testen Sie die Werte für r0.
Erstellen Sie einen PAP.
Lösungsvorschlag Assembler
mov r0,#1
while cmp r0,#16 ; r0-16 setzt Flags
bge ende ; r0>=16?
lsl r0,r0,#1
b while
ende
Lösungsvorschlag PAP
Aufgabe while-Schleife2
r0 = 64;
while(r0>0){
r0 = r0>>1;
}
Welche Werte in Binär nimmt r0 an?
Assemblieren und testen Sie.
Erstellen Sie einen PAP.
Was würde bei der Bedingung r0>=0 passieren?
Lösungsvorschlag Assembler
mov r0,#64
while cmp r0,#0 ; r0-0 setzt Flags
ble ende ; r0<=0?
lsr r0,r0,#1
b while
ende
Lösungsvorschlag PAP
Aufgabe while-Schleife3
Welche Werte in Binär nimmt r0 an?
Assemblieren und testen Sie.
Erstellen Sie einen PAP.
r0 = 1;
while(r0<32){
r0 = r0*2+1;
}
Lösungsvorschlag Assembler
mov r0,#1
while cmp r0,#32 ; r0-32 setzt Flags
bge ende ; r0>=32?
lsl r0,r0,#1
add r0,r0,#1
b while
ende
Lösungsvorschlag PAP
Was würde bei r0=r0<<1+1 passieren?
Siehe https://mezdata.de/pi-basis/010_ausdruecke/index.php
Aufgabe SPS-Schaltung
r0 = testwert;
if((r0&0b11)==0b11){
r0 |= 0b100;
}else{
r0 &= ~0b100;
}
// welchen Wert hat r0[2] jetzt?
Erklären Sie mit Beispiel bitweises und &, bitweises oder |, Zuweisungen |=, &=, bitweises Invertieren ~.
Erstellen Sie eine Tabelle mit Testwerten für r0: 0..7 und den Ergebnissen nach Ausführung des Codes.
Welche logische Funktion wird dabei simuliert?
Hinweis: Einzelne Bits in einem Register werden in [] Klammern dargestellt, z.B. r0[1:0] meint die Bits 1 und 0 in Register r0.
Erstellen und testen Sie den Assemblercode, r0[1:0] dürfen dabei nicht verändert werden. Tipp: Verwenden Sie ggfs. ein Hilfsregister, z.B. r1.
Erstellen Sie einen PAP dazu.
Lösungsvorschlag Assembler
mov r0,#3 ; Testwert
and r1,r0,#0b11 ; Maske
cmp r1,#0b11 ; r1-0b11 setzt Flags
bne else
orr r0,r0,#0b100
b ende
else bic r0,r0,#0b100
ende
Lösungsvorschlag PAP
Bonus-Aufgabe Fakultätsfunktion fak(n:GZ):GZ
Erstellen Sie ein C/Java-Programm für die Fakultätsfunktion https://de.wikipedia.org/wiki/Fakultät_(Mathematik)
Erstellen Sie ein Assembler-Programm wobei r0 den Eingabeparameter enthält und r1 den Rückgabewert.
Testen Sie das Programm mit den Werten 0,1,2,4,6.