# ARM Hochsprache Strukturen
## Unterprogrammtechnik
- wird durch `bl Unterprogramm` aufgerufen
  - _Unterprogramm_ muss zu dem Zeitpunkt bereits ein bekanntes Label sein

| Blatt-Routinen                 | Nicht-Blatt-Routinen     |
|--------------------------------|--------------------------|
| rufen keine Unterprogramme auf | rufen Unterprogramme auf |


## Unterprogrammaufruf
![image_482.png](image_482.png)

## Indirekte Unterprogrammaufrufe
- Falls Adresse zur Compilezeit nicht bekannt ist

- Annahme: aufzurufende Programmadresse steht in r0
  - `mov   lr, pc`
  - `mov   pc, r0`
  - Durch Pipelining entsteht im PC die aktuelle Bitadresse +8
  - Da jeder Befehl Länge von 4 Byte hat
    - Linkregister zeigt auf Rücksprungadresse

## ARM Procedure Calling Standard (APCS)
- Schnittstelle zwischen Programmteilen
  - Wie werden Parameter an Unterprogramme übergeben
  - Welche Register dürfen zerstört werden
  - Wie werden Ereignisse zurückgegeben
  - Wie sieht das Stackframe eines Unterprogramms aus

### Konvention zur Parameterübergabe von 32Bit-Daten
- ![image_483.png](image_483.png)
- Parameter 1-4 werden in den Registern r0-r3 übergeben
- Rückgabewert von Funktionen steht im Register r0 oder r0/r1
- Register r0-r3 und Register ip sind Scratch Register
  - Inhalt darf im Unterprogramm zerstört werden
- Informationen in r4-r10, fp, sp müssen erhalten werden
- Inhalt von lr wird zur Rückkehr ins aufrufende Programm benötigt

## Parameterübergabe bei anderen Prozessoren (CISC)
- ![image_484.png](image_484.png)
- Übergabe in Registern typisch für Load/Store-Architekturen
  - vermeidet Zugriffe auf Speicher
- Andere Prozessoren verwenden Stack
  - Parameter
  - Rücksprungadresse (PC)
- Ergebnis im ACC zurückgeben

## Blatt-Funktionen
- können lokale Variablen in Scratch-Registern speichern
- Rückkehradresse kann im Linkregister bleiben
- ![image_485.png](image_485.png)

## Nicht-Blatt-Funktionen
- Linkregister wird durch neue Rücksprungadresse überschrieben
  - vorher auf Stack retten
- Scratchregister dürfen durch neues Unterprogramm frei verwendet werden
  - keine lokalen Variablen speichern
- Variablenregister verwenden
  - von Anfang an auf Stack
- ![image_486.png](image_486.png)

## Unterprogramm
- Unterprogrammaufruf mit Parameterübergabe
- Dokumentation
  - Übergabewerte & lokale Variablen
- Eingangsprüfung Parameter
  - ggf. Abbruch
- ggf. Register retten
- Initialisation Rückgabeparameter, lokale Variablen
- Programmkörper beachten
  - Anweisungen, Schleifen, Verzweigungen: Grenzfälle der Indizes
- Speicherzugriffe passend zur Datengröße
- ggf. Register restaurieren
- Rückgabewert setzen
- Rücksprung

## Operanden in Ausdrücken
- Argument im Register
- Argument auf dem Stack
  - Stackpointer
  - Relative Adressierung
    - Stackpointer + Offset
- Als Konstante im Literal-Bereich der Prozedur
  - PC-relative Adressierung mit Offset
- Als lokale Variable
  - liegt im Stack
  - Zugriff relativ zum Stack-Pointer / Frame-Pointer mit LDR
- Als globale Variable
  - liegt im statischen Datenbereich im Speicher
  - Adresse liegt relativ zur statischen Basisadresse
- Zeiger
- Array
  - Kurzschreibweise für Zeiger + Offset


## Kontrollfluss
### IF-ELSE
![image_487.png](image_487.png)

### Switch
![image_488.png](image_488.png)
```c++
int testswitch( int a, int* b, int c ) { 
  switch (a) {
    case 0:
      *b = 0;
      break;
    case 1:
      if ( c > 100 ) *b = 0;
      else *b = 3;
      break;
    case 2:
      *b = 1;
      break;
    case 3:
      break;
    case 4:
      *b = 2;
      break;
    }
}
```

### While
![image_489.png](image_489.png)

### Do-While
![image_490.png](image_490.png)

### For
![image_491.png](image_491.png)
```c++
void testfor( int a[]) {
  for (int i = 0; i < 10; i++){
    a[i] = 0;
  }
}
```

## Objekte, (virtuelle) Methoden
### Methodenaufrufe bei Objekten
- Methode bekommt als ersten Parameter immer einen Zeiger auf das betreffende Objekt (this)
  - Zugriff auf Daten des Objektes gewährleistet

### Statischer Objektaufruf
- Falls Methoden einer Klasse nicht virtuell
  - Compiler kann zur Compile-Zeit schon Klasse bestimmen und Adresse der Methode einsetzen

### Dynamischer Methodenaufruf
- ![image_492.png](image_492.png)

## Beispiele Assemblerprogramme
### my_max
```c++
#include <stdlib.h>
void my_max(int a, int b, int* c) {}
  if (a > b)
    *c = a;
  else 
    *c = b;
}
```

#### my_max ohne Optimierung
![image_493.png](image_493.png)

#### my_max mit Optimierung
![image_494.png](image_494.png)