1.3 ALU-Funktion und Simulation mit VisUAL2

Präsentation: Funktionsweise ALU und Flags

Funktion der ALU und die Flags N,Z,C

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
  • In VisUAL geht bx lr nicht, verwende mov pc,lr
  • VisUAL2 kann keinen mul-Befehl?! 😭

Addition, Subtraktion und Flags

Mission: Übersetze in Assembler mit Hilfe der Formelsammlung und simuliere mit VisUAL2
Das sollte dazu schon verstanden worden sein: Ganzzahlige und negative Zahlen, Ausdrücke und Operationen.

// 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
PAP-While-Schleife
While Schleife

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
PAP For-Schleife
PAP For-Schleife

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
PAP Do-While-Schleife
PAP Do-While-Schleife

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
PAP Switch
PAP Switch

Einfacher Unterprogramm-Aufruf

Prinzip Unterprogrammaufruf

Unterprogramme werden mit dem bl label (Branch Linked) Befehl aufgerufen, dabei wird die Adresse des dem Aufruf Befehls folgenden Befehls im LR-Register (R14) gespeichert, damit am Ende des Unterprogramms wieder die richtige Stelle des aufrufenden Programmteils zurückgesprungen werden kann. Für den Rücksprung aus dem Unterprogramm wird bei STM32 der Befehl bx lr und bei Visual2 mov pc, lr (move ProgramCounter <- LinkRegister) ausgeführt.
In diesem Beispiel werden noch keine Parameter und Rückgabewerte betrachtet, es wird nur auf globale Variablen zugegriffen.
Testen Sie das Assemblerprogramm: Achten Sie dabei auf die Register LR (R14) und PC (R15).
Erstellen Sie einen PAP.

int r0 = 2; // Testwert
int r1 = 1; // Testwert
void main(){ // Hauptprogramm
  max(); // Unterprogrammaufruf
  r1 = 4;
  max();
}
void max(){
  if (r1>r0) r0=r1;
}
       mov     r0,#2
       mov     r1,#1
main   bl      max ; Unterprogrammaufruf
       mov     r1,#4
       bl      max
       end ; Pseudobefehl Programm zu Ende
max    cmp     r1,r0
       ble     maxend
       mov     r0,r1
maxend mov     pc,lr ; bx lr bei STM32
Lösung PAP
PAP Unterprogramm
PAP Unterprogramm

Mögliche Aufgabenmuster

  • C/Java Programm -> Assembler mit PAP, dazu Fragen zu Werten, Tabelle mit Ein- Ausgabewerten bzw. Werteverlauf
  • Assembler-Programm -> PAP erstellen und Code analysieren, Tabelle mit Ein- Ausgabewerten bzw. Werteverlauf
  • Textuelle Beschreibung von Problem -> PAP und Assembler
  • Tabelle mit Ein- Ausgabeverhalten -> PAP und Assembler

Assembler-Befehle ausführen

Die Ergebnisse nach der Ausführung der Assembler-Befehle sollen in die Tabelle eingetragen werden. N,Z,C sind die gesetzten Flags durch den Befehl. Hex,Dec,Bin ist das Format in dem in den Spalten R0,R1 die Werte von R0 und R1 nach der Ausführung des Befehls angezeigt werden sollen. Sie können mit Visual2 Ihre Ergebnisse überprüfen.

BefehlNZHexBinDecR0R1
movs r0,#100X10
add r1,r0,#1000X0b10b1011
subs r1,r0,#1X
subs r1,r0,#3X
ands r1,r1,#0x7X
orrs r1,r0,#0x10X
movs r1,#0x20X
tst r1,#0b10110X
movs r1,#-1X
mvns r0,#2X
Code für Visual
movs    r0,#1
add     r1,r0,#10
subs    r1,r0,#1
subs    r1,r0,#3
ands    r1,r1,#0x7
orrs    r1,r0,#0x10
movs    r1,#0x20
tst     r1,#0b10110
movs    r1,#-1
mvns    r0,#2

Spass mit Modulo-Operator % und bitweisem Und &

Welche Werte hat das Register nach der jeweiligen Operation?
Der Modulo-Operator % gibt den Rest einer Division zurück.

Lösung
r0r0%2r0&1r0%4r0&3r0&6
000000
111110
200222
311332
400004
511114
Modulo-Operator und bitweises Und
r0r0%2r0&1r0%4r0&3r0&6
00
11
20
31
40
51
Modulo-Operator und bitweises Und

Aufgabe if-Anweisung1

r0=-1; // Testwerte
if(r0<0) r0=0;
else if(r0>3) r0=3;

Erstellen Sie eine eine Tabelle mit Testwerten und erwarteten Ergebnissen. Begründen Sie die Wahl ihrer Testwerte. Übersetzten Sie Assembler und überprüfen Sie Ihr Programm mit den Testwerten. Erstellen Sie einen PAP.

Lösung Tabelle
r0 vorherr0 nachher
-10
00
11
22
33
43
Tabelle mit Testwerten
Lösung Begründung

Testen mit negativer Zahl, 0, und immer um die Grenzwerte der Bedingungen um Fehler zu entdecken.

Lösung Assembler
       mov     r0,#-1
       cmp     r0,#0
       bge     else
       mov     r0,#0
       b       ende
else   cmp     r0,#3
       ble     ende
       mov     r0,#3
ende   
Lösung PAP
PAP IF-Anweisung
PAP IF-Anweisung

Textaufgabe1

Der Wertebereich des Registers r0 soll auf {-2..2} begrenzt werden, erstellen Sie PAP, Assembler, Testtabelle..

Lösung Assembler
       mov     r0,#3 ; Testwerte
       cmp     r0,#-2
       bge     else
       mov     r0,#-2
       b       ende
else   cmp     r0,#2
       ble     ende
       mov     r0,#2
ende   

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
PAP Aufgabe
PAP Aufgabe

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
PAP Aufgabe
PAP Aufgabe

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
PAP Aufgabe
PAP Aufgabe

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
PAP SPS

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.
Das wäre mein Lösungsversuch, leider kann VisUAL2 kein mul…

int r0,r1; // Glob. Variablen
main(){
  r0 = 1; // Testwerte
  fak();
}
void fak(){
  int r2=2;
  r1=1;
  while (r2<=r0){
    r1=r1*r2;
    r2++;
  }
}
       mov r0,#1 ; Testwerte
       bl fak ; Unterprogrammaufruf
       end
fak    mov r1,#1
       mov r2,#2
while  cmp r2,r0
       bgt fakend
       mul r1,r1,r2
       add r2,r2,#1
       b while
fakend mov pc,lr