This commit is contained in:
David Schirrmeister
2024-12-05 13:53:10 +01:00
parent 2339530e42
commit 73e1392286
57 changed files with 7 additions and 0 deletions

View File

@ -0,0 +1,89 @@
# Historie
```mermaid
stateDiagram
[*]--> ersteAutomaten
ersteAutomaten: 60 n Chr.
note right of ersteAutomaten
Alexandriner Heron entwickelte
viele Automaten z.B.
automatische Türen mit Hebeln
_
end note
ersteAutomaten --> zeitDerUhrmacher
zeitDerUhrmacher: 1348-1364
note left of zeitDerUhrmacher
Giovanni de Dondi baute 1348-1364 die
erste Astronomische Uhr
_
end note
note left of zeitDerUhrmacher
Eingabe: Takt
Ausgabe: Zeiger
Zahnräder: innerer Zustand
_
end note
zeitDerUhrmacher --> astronomischeUhr
astronomischeUhr: 1354
note left of astronomischeUhr
Astronomische Uhr
_
end note
astronomischeUhr --> lochkartenWebstuhl
lochkartenWebstuhl: 1725-1728
note right of lochkartenWebstuhl
Basile Bouchon 1725 und Jean
Babtiste Falcon 1728 erfanden
eine Apparatur die über
Lochkarten gesteuert wurde
_
end note
lochkartenWebstuhl --> jaquesDesVaucanson
jaquesDesVaucanson: 1745
note left of jaquesDesVaucanson
Der mechanische Webstuhl wurde
durch Jacques de Vaucanson, einem
Erfinder um 1745 weiterentwickelt,
konnte sich aber immer noch nicht
durchsetzen
_
end note
note left of jaquesDesVaucanson
Vaucanson entwickelte auch andere
Automaten, so die berühmte Ente
_
end note
jaquesDesVaucanson --> jaquard
jaquard: Der Jaquard Webstuhl
note right of jaquard
erste frei programmierbare
Maschine, die in großer Menge
gefertigt wurde
_
end note
note right of jaquard
Der Lochkartenstreifen ist der
erste Datenträger, der
austauschbare Programme trägt
_
end note
jaquard --> lochkartenSteuerungMusik
lochkartenSteuerungMusik: Ende 17. Jhd
note left of lochkartenSteuerungMusik
Drehorgeln, Orchestrion
(stellt ganzen Orchester dar)
Konnte noch nicht speichern
_
end note
lochkartenSteuerungMusik --> ersteRechenmaschine
```

View File

@ -0,0 +1,129 @@
# Klassifikation
> Eigenschaften von Prozessoren
## Klassifizierung gemäß Operandenstruktur
### Stackarchitektur
- Stacks werden unabhängig von der jeweiligen Architektur verwendet
- bei Unterprogrammaufrufen und Prarameterübergaben
- Call-Befehl
- pusht Rücksprungadresse und ggf. Registerstati
- Return
- popt Werte wieder
- ![image_257.png](image_257.png)
![image_254.png](image_254.png)
### Akkumulator Architektur
- Ausgezeichnetes Register: Akku(mulator) (_ehem. ACC_)
- LOAD und STORE wirken nur auf Akku
- expliziter Operand, an jeder Operation beteiligt
- jede Operation braucht nur eine Adresse
- Sehr kompaktes Befehlsformat
- ![image_255.png](image_255.png)
- ![image_256.png](image_256.png)
### Register-Register-Architektur
- RISC (LOAD-STORE-Architektur)
- alle Operationen greifen nur auf Register zu
- 32-512 Register verfügbar
- **nur** LOAD und STORE greifen auf Speicher zu
- Einfaches Befehlsformat fester Länge
- ![image_258.png](image_258.png)
- alle Instruktionen brauchen in etwa gleich lange
- ![image_259.png](image_259.png)
### Register-Speicher-Architektur
- CISC (Mischung von Akkumulator- und Load-Store-Architektur)
- Operationen greifen auf Register und/oder Speicher zu
- Befehlsformat variabler Länge
- mächtige Befehle
- ![image_260.png](image_260.png)
- stark unterschiedliche Zeiten für Instruktionsausführung
- ![image_261.png](image_261.png)
## Klassifizierung gemäß Busaufbau
### [Vergleich Harvard- / von Neumann Architektur](MU6Rechner.md#vergleich-harvard-von-neumann-architektur)
### Bussysteme
- Systembus = Datenbus, Adressbus, Kontrollbus, Bus zur elektrischen Versorgung der Komponenten
- teilweise zstzl. I/O-Bus
- ![image_262.png](image_262.png)
## Klassifizierung gemäß Befehlssätzen
### Orthogonale Befehlssätze
> Wenn Opcode, Adressierungsart und Datentyp beliebig kombiniert werden können
| **Vorteile** | **Nachteile** |
|---------------------------------------------------|--------------------------------|
| Vereinfacht Nutzung der verfügbaren Instruktionen | Sehr umfangreiche Befehlssätze |
### CISC Kriterien
- Befehle unterschiedlicher Länge von 1-17 Byte
- Speichereffizienz
- komplexe Befehlskodierung
- Komplexer Befehlssatz
- Anpassung an Compiler
- Hochsprachenkonstrukte im Assembler
- Erleichterung der Assemblerprogrammierung
- Mächtige Befehle
- kurze Programme
### RISC Prinzipien
- Grundlegendes Design-Prinzip
- Einfachheit
- Befehle gleicher Länge (meist 32 Bit)
- Abarbeiten mit gleicher Taktzahl
- erlaubt Befehlspipelines
- Eingeschränkter Befehlssatz (32-128 Befehle)
- Explizite Lade/Speicher-Befehle (Load-Store-Architektur)
- [3-Adress-Befehle](#3-adress-befehle)
- Delayed Branches
- Pipeline enthält Befehl, dass Pipeline gelöscht wird
- währenddessen kann noch eine Instruktion ausgeführt werden (_kein Jump_)
## Klassifizierung gemäß Speicherorganisation
### Little/Big Endian
![image_269.png](image_269.png)
### 4-Adress-Befehle
![image_263.png](image_263.png)
- Allgemeinste Form für Befehlsformat
- next_i = Adresse des nächsten Befehls
- schwierig zu programmieren
- wird für Microcode verwendet (CISC Mikroprogramme)
### 3-Adress-Befehle
![image_264.png](image_264.png)
- Standard bei RISC Prozessoren (_bspw. ARM 32 Bit_)
- 3 Adressen benötigen Platz
- Format ist erst ab 32-Bit-Befehlssatz sinnvoll
- nächste Befehlsadresse implizit
- Sprungbefehle können implizites Verhalten ändern
### 2-Adress-Befehle
![image_265.png](image_265.png)
- Standardformat für 8 und 16-Bit-Mikroprozessoren
- Format für Intel Prozessoren
- RISC-Prozessoren mit komprimierten Befehlssatz nutzen ebenfalls das Format
- _bspw. ARM Thumb, MIPS_
### 1-Adress-Befehle
![image_266.png](image_266.png)
- Zielregister ist implizit und wird ACC genannt
- wird im [MU0-Design](MU0Rechner.md) benutzt
- Hohe Befehlsdichte
- geringe Flexibilität
### 0-Adress-Befehle
![image_267.png](image_267.png)
- Beide Operanden und das Ziel sind implizit
- Befehlssatz nur für Stackarchitektur möglich
- weitere Befehle mit Operanden zum Speichern / Laden nötig
- _verwendet in [Java Virtual Machine](12_Virtualisierung.md#anwendungsvirtualisierung)_
## Einordnung Prozessoren
![image_268.png](image_268.png)

View File

@ -0,0 +1,178 @@
# MU0-Rechner
## Historie
- **SSEM** _Small Scale Experimental Machine_ erste erfolgreiche Implementierung des Von-Neumann-Rechners
- 1948 erstmals Programm aus dem Speicher ausgeführt
## Elemente
![image_22.png](image_22.png)
- **[Steuerwerk](MU0Rechner.md#steuerwerk)**
- _Control_ - Takt, Steuerlogik
- _IR - Instruction Register_ - speichert den aktuellen Befehlscode
- _PC - Programm Counter_ - speichert die aktuelle Programmadresse
- **Rechenwerk**
- _[ALU](MU0Rechner.md#alu) - Arithmetic Logic Unit_ - kann rechnen
- _ACC - Akkumulator_ - Ergebnis Register für Rechnungen
- **[Speicherwerk](MU0Rechner.md#speicher)**
- _Memory_ - speichert Programme und Daten
- **Bus** - verbindet alle Elemente
### Steuerwerk
- Steuert Elemente mithilfe von Steuersignalen
- Besteht aus
- Ablaufsteuerung / Steuerlogik
- Dekodierer
- Befehlsregister IR
- Befehls-Zähler PC
- **Endlicher Automat, der gemäß der Steuerlogik Steuersignale schaltet**
- führt für jeden Befehl ein Mikroprogramm aus Mikroschritten aus
### Register
![image_23.png](image_23.png)
- Zwischenspeicher
- Register-Größe: 1 Wort (16 Bit)
- Arbeitsmodus Lesen / Schreiben
- _output enable_ liegt an → Daten ausgeben (schreiben)
- _input enable_ liegt an → Daten einlesen
- Ausgeben und Lesen erfolgt jeweils beim Flankenwechsel
- Ausgeben erfolgt einen halben Takt früher als das Lesen, sodass ein Register in einem Zyklus schreiben und lesen kann
- ![image_24.png](image_24.png)
### Speicher
- Stelle im Speicher wird über eine Adresse angesprochen
- Adresse wird vom Adressbus gelesen
- Daten werden vom Datenbus gelesen bzw. geschrieben
- ![image_25.png](image_25.png)
### Datenpfade
- je nach Steuerungscode lesen / schreiben
- geschriebene Daten liegen an Datenpfad an
- immer nur 1 Element schreiben
- ![image_26.png](image_26.png)
### ALU
- über Steuercode wird Funktion ausgewählt
- Eingang A, B führt aus
- mögliche Funktionen:
- A+Β
- A-B
- A*Β
- Konjunktion (logisches UND, bitweise)
- Disjunktion (logisches ODER, bitweise)
- Vergleich von A und B (bitweise)
- ...
## Beispiel für einen Befehlsablauf
![image_27.png](image_27.png)
## Der Rechenzyklus
### Fetch
![image_28.png](image_28.png)
1. Wert des Programmcounters auf den Adressbus legen
2. Programmcode aus dem Speicher in das Instructionregister lesen
3. ALU erhöht gleichzeitig Wert des PC und speichert diesen wieder zurück
### Decode/Execute/Write für Rechenoperationen
![image_29.png](image_29.png)
1. Adresse des Operanden aus dem Befehl dekodieren (1)
2. Wert des angesprochenen Speicherworts an einen Eingang des ALU schalten (2)
3. zweiter Eingang der ALU erhält seine Information vom Akkumulator (2)
4. Rechenoperation wird aus dem Befehl dekodiert und and der ALU über Steuercode gewählt (1)
5. Ergebnis der Rechnung wird wieder im Akkumulator gespeichert (3)
## Taktsynchronität
- Register sind Zwischenspeicher und arbeiten getaktet
- Daten liegen taktsynchron am Bus an
- ALU und Speicher sind nicht taktsynchron
- folgen Steuercodes und dem Inhalt auf dem Bus
## Umsetzung MU0-Struktur in Hardware
- Architektur muss in Gattern und getaktet umsetzbar sein
- Prinzip des minimalen Hardwareaufwands
- Festlegung der Wortbreite: 16 Bit
- [Datenpfad-Modell](MU0Rechner.md#datenpfad-modell)
- Steuerung der Elemente durch Steuercodes
- Befehle (Instruction Set)
- Kodierung der Befehle
- Steuerlogik
### Datenpfad-Modell
![image_30.png](image_30.png)
- bisheriges Bild lässt sich nicht 1:1 umsetzen
- ALU hat nur zwei Eingänge
- Getrennte Datenpfade für jeden ALU-Eingang
- Kontrolle der PFade für Daten und Adressen durch [Multiplexer](MU0Rechner.md#multiplexer)
#### Multiplexer
![image_31.png](image_31.png)
- Schalter, der durch Anlegen eines Steuersignals das ausgewählte Eingangssignal auf den Ausgang legt
#### Befehlsgruppen
- Multiplexer B steht auf 1 bei allen _Datenverarbeitungs-Befehlen_ und auf 0 bei allen _Sprung-Befehlen_
- Multiplexer A wird nur für _Fetchzyklus_ auf 0 gestellt
- ansonsten wird S (unterer Teil von IR) immer als Adresse interpretiert
- Bei _Sprung-Befehlen erfolgt kein Datenzugriff, S (IR) wird direkt nach PC verschoben
## Kennwerte
- Wortbreite des Prozessors: 16 Bit
- Registergröße
- Busbreite
- Eingänge/Ausgänge ALU
- Instruktionen immer 2 Takte lang
- Fetch + Instruction (= Execute): 2 Takte
- Schreiben + Lesen + Schreiben + Lesen: 4 Taktflanken
## Elemente und Steuercodes
![image_32.png](image_32.png)
## Speicher des MU0
- Steuersignale des Datenbus:
- MemRQ (Memory Request)
- Speicherbaustein wird angesprochen
- RnW(Read / not Write)
- gibt an, ob (von oder in) den Speicher geschrieben wird
- _Lesen bei High, Schreiben bei Low_
## Instruction Set des MU0-Rechners (Befehlssatz)
![image_33.png](image_33.png)
- Prozessor kennt keine Befehle
- zum **Laden und Speichern** von Werten
- zur **Berechnung**
- zur **Ablaufkontrolle**
- Die Instruktionen setzen sich zusammen aus
- einem 4 Bit Operation Code
- einer 12 Bit Adresse
→ 16 Befehle möglich
## MU0-Steuerlogik (_Kontroll-Logik_)
Opcode: 4Bits, Adresse: 12Bits
![image_34.png](image_34.png)
### Fetchen
![image_35.png](image_35.png)
### ADD S
![image_36.png](image_36.png)
## Ein erstes MU0-Programm
![image_37.png](image_37.png)
## Fazit
- Elemente der von-Neumann-Architektur
- Steuerwerk, Rechenwerk, Speicherwerk, I/O
- Speicherprogrammiert
- Programme (& Daten) liegen im Speicher
- Architektur muss in Gattern umsetzbar sein
- Datenpfad & Steuertabelle
- Von-Neumann-Zyklus: Fetch-Decode-Execute-Write
- Steuerlogik wird über Opcodes (Befehle) abgefragt und generiert Steuercodes
- MU0 ist ein Modellrechner zum Lernen
- 16-Bit Wortbreite, binär
- Register: PC, IR, ACC
- Befehlssatz (Instruction Set)
- 4-Bit OpCode erlaubt 16 Befehle, 8 sind implementiert
- Takt
- Immer 2 Zyklen pro Mikroprogramm

View File

@ -0,0 +1,311 @@
# MU1-Rechner
## Was kann er mehr:
- Indirekte Adressierung
- Schleifen
- Unterprogramme (Strukturen)
- Optimieren der Datenzugriffe (schneller)
## ALU
### Verbesserungen
- Funktionen der ALU
- **A+B** ist der Ausgang des Addierers
- **A-B** wird gebildet als **A+nichtB+1**
- **B** wird implementiert, indem A fest auf 0 gesetzt wird
- **A+1** wird implementiert, indem Eingang B fest auf 0 und Carry-Eingang auf 1 gesetzt wird
![image_54.png](image_54.png)
### Grundfunktionen MU1-ALU
_Im Praktikum wird nur erwartet, dass Funktion bekannt ist, nicht bspw FA, FIA, etc._
- FA: Funktion (0, A) (also eig. F0A)
- FB: Funktion (0, B)
- FIA: Funktion (Inverter, A)
- FIB: Funktion (Inverter, B)
- FC: Funktion (F1, Carry-Flag)
- F1: Funktion (0/1)
- FS: Funktionsergebnis Statusregister
- C: Funktionsergebnis C
![image_56.png](image_56.png)
![image_55.png](image_55.png)
## Der MU1-Datenpfad
- Das erweiterte Modell besitzt
- Stackpointer SP
- Register Din und Dout
- Laufzeiten sind kürzer pro Takt
- Takt kann erhöht werden
- Durch Din und Dout braucht es mehr Taktzyklen, diese sind aber schneller durchlaufen
![image_57.png](image_57.png)
## Der Reset
- Jeder Prozessor hat einen Reset-Eingang
- ist negiert angelegt → 0 macht [reset](MU1Rechner.md#reset)
- [Program Counter](MU0Rechner.md#steuerwerk) wird auf 0 gestellt, [Microprogram-Counter step](MU1Rechner.md#micro-program-counter-step) ebenfalls
- ALU wird auf Funktion NULL gesetzt
- Beim Einschalten wird Reset-Signal verzögert gesetzt
- Prozessor braucht Zeit um Startzustand herzustellen
## Micro-Program-Counter Step
- Step ist ein Speicher in der Steuereinheit (_Timing/Control Unit_)
- meiste Befehle benötigen mehrere Takte
- Micro-Program-Counter Step gibt Steuerlogik Informationen
- welche Aktionen sind auszuführen
- Step = Eingangsinformation für jeden Schritt
- Steuerungstabelle weiß welcher step welcher Schritt ist
## Befehlsablauf MU1
![image_58.png](image_58.png)
- Step == Null
- **Fetch** (lesen des Befehls in das Instruction Register)
- letzter Schritt: Step = Null
- Step wird meistens um 1 erhöht
- falls nicht → Schleife
### Fetch-Zyklus
- findet in einem Takt statt
- 1. Taktflanke
- Program Counter wird auf Adressbus und auf ALU[A] geschaltet
- An der ALU ist Befehl=A+1, S=0
- 2. Taktflanke
- Speicher liest nächste Instruktion und speichert in IR
- PC wird über ALU um 1 erhöht
![image_59.png](image_59.png)
![image_80.png](image_80.png)
### Befehl LDA (Laden des AKK aus Speicher)
- Zwei Takte
- ![image_60.png](image_60.png)
- ![image_81.png](image_81.png)
### Zustandsbeschreibung des Ladebefehls
![image_61.png](image_61.png)
- Nach Fetch entscheidet Opcode im IR und Schrittnummer, welchen Zustand der Automat als nächstes annimmt
- Step ist PC im Microcode und beschreibt Abfolge der Befehle im Microcode
- Zu jedem Schritt gehört eindeutige Funktion
- Lässt sich in Timing-Control-Logik umsetzen
## Adressierung
### Direkte Adressierung (STO/LDA)
![image_62.png](image_62.png)
- Befehl erhält direkt die Speicheradresse
- Adresse kann zur Laufzeit nicht mehr verändert werden
### Indirekte Adressierung (STR/LDR)
![image_63.png](image_63.png)
- Adresse steht an Speicherstelle
- effektive Adresse kann noch berechnet werden
- Schleifen können programmiert werden
### Adressierungsarten
#### Unmittelbare Adressierung (_immediate_)
- Befehl erhält Konstante
- bspw.: _ADD #1_
#### Direkte Adressierung (_direct, absolute_)
- Befehlt enthält Adresse im Speicher, an der sich Operand befindet
- bspw.: _LDA S_ (_S gibt Adresse im Speicher an_)
#### Indirekte Adressierung (_indirect_)
- Befehl enthält Adresse, an der dich effektive Adresse mit Inhalt befindet
- bspw.: _LDR S_ (_S gibt indirekte Adresse an_)
## Der Stack
- stellt dynamischen Zwischenspeicher dar
- Grundoperationen: [Push](MU1Rechner.md#stack-push), [Pop](MU1Rechner.md#stack-pop)
- Meiste Speicherlayouts (_Konventionen_) sehen vor:
- wächst von oben nach unten
- wächst von großen zu kleinen Adressen
### Stack - PUSH
![image_65.png](image_65.png)
- erniedrigt Stackpointer
- schiebt einen Wert in Speicherwort, auf das der Stackpointer zeigt
### Stack - POP
![image_66.png](image_66.png)
- liest ein Speicherwort von Adresse auf den der Stackpointer zeigt
- erhöht den Stackpointer
### Der Stack im Speicher
![image_64.png](image_64.png)
- Stackpointer wird auf Adresse am Ende des Speicherbereichs gesetzt
- Programme werden im unteren Speicherbereich platziert
- Programm-Counter auf Adresse 0
- Programmbereich schließt sich nach oben an Datenbereich an
- Zwischen Daten und Stack findet man Heap
### Zugriffe auf den Speicher
![image_67.png](image_67.png)
## Unterprogramme
![image_68.png](image_68.png)
- wichtiges Strukturierungsmittel für Programmierung
- werden mit Sprungbefehl (_call, bl_) angesprungen
- Nach Verlassen des UP wird ursprüngliches Programm wieder fortgesetzt
- Rücksprung erfolgt indem gespeicherte Adresse wieder in PC übertragen wird
### Unterprogramm Aufrufe
#### Call
![image_69.png](image_69.png)
- nächster nach der Rückkehr auszuführende Befehl wird auf den Stack gespeichert
- Sprungadresse wird aus IR in PC geladen
#### Return
![image_70.png](image_70.png)
- Rücksprungadresse von Stack in PC geschrieben
- fetch-Zyklus lädt neue Instruktion
## MU1-Befehlssatz
![image_71.png](image_71.png)
## Micro-Codes
**X = Y**
- Inhalt des Registers Y wird nach X verschoben
**X = [Y]**
- Inhalt von Adresse in Y wird nach X verschoben
**X = Y op Z**
- Inhalt von Y (A-Bus der ALU) wird mit Z (B-Bus der ALU) verrechnet und nach X transportiert
**[X] = Y**
- In Adresse in X wird Inhalt von Y geschrieben
**ACC = Din**
- ACC & Din sind Registernamen
- Inhalt von Din wird nach ACC transportiert
- in Din muss oe gesetzt sein, in ACC muss ie gesetzt sein
- Transport über ALU
- [ALU Funktion](MU1Rechner.md#grundfunktionen-mu1-alu) muss B sein
- Da Speicher nicht angesprochen wird (keine [ ])
- [MEMeq=0](MU0Rechner.md#speicher-des-mu0) und [RnW beliebig (laut Rapp lieber 1)](MU0Rechner.md#speicher-des-mu0)
**Din = [SP]**
- Inhalt von SP ist Adressinformation
- Adressmultiplexer muss auf 0 stehen
- Da Speicher angesprochen wird
- MEMrq = 1, RnW = 1
- Da ALU nicht benutzt wird
- ALU-Funktion kann beliebig gesetzt werden
**PC = PC + 1**
- ALU-Funktion muss [A+1](MU1Rechner.md#grundfunktionen-mu1-alu) sein
- PC wird auf A-Bus gelegt
- in der zweiten Hälfte des Takts wird Ergebnis in PC geschrieben
- oe und ie von PC müssen 1 sein
**Din = [SP], SP = SP+1**
- Beide Operationen können in einem Takt durchgeführt werden
- Adressierung in der ersten Takthälfte
- Zurückschreiben in der zweiten Takthälfte
## Regeln für MU1
**[X] = Dout**
- wird in den Speicher geschrieben, muss rechte Seite [Dout](MU1Rechner.md#der-mu1-datenpfad) sein
- [MEMrq = 1, RnW = 0](MU0Rechner.md#speicher-des-mu0)
- zu schreibender Wert muss VORHER nach Dout gebracht werden
**X = [Y]**
- wird vom Speicher gelesen
- linke Seite muss IR oder Din sein
- [MEMrq = 1, RnW = 1](MU0Rechner.md#speicher-des-mu0)
**keine Adresse**
- wird keine Adresse verwendet
- [MEMrq = 0, RnW = 1](MU0Rechner.md#speicher-des-mu0)
- **Nur ein Register darf jeweils auf einen Bus schreiben (A- oder B-Bus), aber alle dürfen lesen**
## Die Addition ADD S
- IR wird zur Adressierung verwendet und der Wert nach Din gebracht
- **Din = [IR]**
- Inhalt des AKK wird auf A-Bus gelegt, Inhalt von Din auf B-Bus
- [ALU-Funktion](MU1Rechner.md#grundfunktionen-mu1-alu) ist **A+B, S: ACC = ACC + DIN**
![image_72.png](image_72.png)
## Die Operation PUSH
**Akkumulator wird auf den Stack geschoben**
- Besteht aus 3 Schritten
1. **SP = SP-1**
- ![image_73.png](image_73.png)
2. **Dout = ACC**
- ![image_74.png](image_74.png)
3. **[SP] = Dout**
- ![image_75.png](image_75.png)
- [Micro-Program-Counter Step](MU1Rechner.md#micro-program-counter-step) wird auf 0 gesetzt
- Fetch-Zyklus schließt sich an
## MU1-Zustandsautomat für LDA, ADD, PUSH
![image_76.png](image_76.png)
- Nach dem Holen des Opcodes im Fetch-Zyklus
- Zustand des OpCode wird angesprungen
- Step-Variable (PC im Micro-Code) wird in Schleife durchlaufen
- endet bei 0 im Fetch-Zyklus
## Bedingte Sprünge
- Bedingter Sprung **JGE** (_Jump on greater or equal_)
- in Abhängigkeit des Negative-Flags im Statusregisters (~15 Bit des ACC, ACC >=0 oder ACC <0) wird ein unterschiedlicher Zustand angesprungen
- ? N = 0 (ACC >= 0)
- PC = IR
- ? N = 1 (ACC < 0)
- keine Operation wird ausgeführt (NOP)
- Bedingter Sprung **JNE** (_Jump on not equal)
- strukturell gleich, Zusatzbedingung:
- Accumulator = Null (Zero-Flag = 1)
### MU1-Steuerlogik für bedingte Sprünge
- Beide Befehle weisen 2 Zustände auf
- unterscheiden sich durch Statusbits des Akkumulators
- Beide Zustände haben Schrittnummer 1 und Folgeschritt 0
- Funktion **NOP** (**N**o **Op**eration) ist gekennzeichnet
- kein Registerinhalt wird verändert
- Alle Register haben oe und ie auf 0
- Speicher wird nicht angesprochen
- MEMrq = 0
- ![image_77.png](image_77.png)
## Der Stop-Befehl
- hat als Folgezustand _stop_
- kein Fetch-Zyklus mehr
- Zustandsmaschine wird in der Stellung angehalten
- ![image_78.png](image_78.png)
## Reset
- Zustandsmaschine geht in Zustand _reset_
- PC = 0
- Step = 0
- Beendigung des Reset-Signals mit dem fetch fortgefahren und Befehl von Adresse 0 wiederholt
- ![image_79.png](image_79.png)
## Zusammenfassung
- Funktionen ALU
- Neue Register Stackpointer, Din, Dout
- Micro-Programm-Counter Step
- Fetch-Zyklus
- Micro Programm + Micro Codes + Zustandsautomaten für LDA, ADD, Push, JGE, Stop, Reset
- Direkt und indirekte Adressierung
- Stack, Unterprogramme
- Beschreibung der Microcode-Funktion durch einfache Sprache
- Zentrales Register: ACC Akkumulator-Architektur
## Probleme des MU1-Designs
- **Speichergröße**
- begrenzt auf 4096 Worte (12Bit) bzw. 65k Worte (16Bit)
- **Anzahl Befehle**
- Begrenzung auf 4 Bit breiten Opcode
- **Absolute Adressierung**
- **Adressberechnungen**
- Müssen in einem Register zwischengespeichert werden
- **Nur ein Datenregister**
- **Berechnung Programmcounter**
- Muss jedes Mal durch ALU erhöht werden verlangsamt Prozessor
## [Weiterentwicklung MU2](MU2-3Rechner.md)

View File

@ -0,0 +1,67 @@
# MU2/3-Rechner
## MU2 Rechner
## Adressraum vergrößern
### Wortbreite vergrößern
- 16 Bit → 32 Bit
- Register, Bus, ALU
### Adressberechnung mit Offset
- Adresse = Register(bereits vorhandene Adresse) + Offset
- Offset kann mit weniger Bits angegeben werden
- Adresse hat volle Breite
**Wird benötigt für:**
- **Relative Adressierung** für Unterprogramme / Sprünge
- **Indizierte Adressierung** für Speicherzugriffe
- Wie indirektes Laden und Speichern mit Offset
- Laden von **PC-relativen Konstanten**
- Prozessoren mit fester Befehlsbreite
- Nur kleine Konstanten können im Code dekodiert werden
- Falls Konstanten in der Nähe des augenblicklichen Programms (_bspw. hinter Returnanweisung eines Unterprogramms_)
- können geladen werden
### Relative Adressierung
- ![image_128.png](image_128.png)
- Code wird im Speicher verschiebbar
#### Labels
- Umsetzung von PC-relativen Sprüngen mit Labels
- ![image_129.png](image_129.png)
### Indizierte Adressierung
#### Beispiel Stack
![image_130.png](image_130.png)
- In Unterprogrammen wird dyn. Speicher reserviert, indem der Stackpointer dekrementiert wird
- Zugriff auf Speicher über Stack + Offset(in Befehl)
- PUSH & POP nicht ausreichend
- bei mehreren Variablen auf dem Stack jeweils beim Lesen der Stack geräumt werden müsste
### Adressberechnung in der ALU
- Adresse als Ergebnis der ALU ohne Speicherung in ACC
- Keine absolute Adressierung (aus IR)
- Nur ALU schreibt auf Adressbus (ohne Multiplexer)
- 32 bit
#### Maximale Laufzeit:
![image_131.png](image_131.png)
- **Gesamtlaufzeit ist zu lang!**
- in einem Takt möglich
- falls Taktfrequenz niedrig genug
## MU3: Einführung des Adressregisters
![image_132.png](image_132.png)
- Ein Takt mehr um Daten aus dem Speicher zu holen
- Taktfrequenz kann höher sein
- Laufzeit pro Teilstück kürzer
- **Nachteil:**
- Nutzen des PC und Inkrementieren geht nicht mehr parallel
- in Aout muss vor Fetch eine Kopie des aktuellen PC stehen
- _(Fetch beginnt bei Aout!)_
### Beispiel relative Sprünge
![image_133.png](image_133.png)
## Problem im Fetch-Zyklus
**Datentransferbefehle ändern Aout**
![image_134.png](image_134.png)

View File

@ -0,0 +1,130 @@
# MU4/5-Rechner
## Registeranzahl erhöhen
### Registerarchitektur
- Gesamtzahl der Register ist normalerweise eine Zweierpotenz
- 8 (ARM-Thumb), 16 (ARM), 32 (Power PC, MIPS) und mehr Register
→ Ergebnisse von Registern können in einem von n Registern gespeichert werden
- Manchmal werden Spezialregister (_PC, SP, LR_) wie andere Register adressiert
- Vorteil: Werte können in arithmetischen Operationen und zur Adressierung benutzt werden
- _ARM: PC in R15, LR in R14, SP in R13_
**Adressierung der Quell- / Zielregister muss im Befehl enthalten sein**
- Bei 16 Registern ist 4Bit (=n) Adressinformation für QR und ZR nötig
- 2-Adress-Befehle (_bspw. add R0, R1 ; R0 += R1_)
- brauchen 2n Bits zur Dekodierung
- 3 Adress-Befehle (_bspw. add R0, R1, R2 ; R0 = R1+R2_)
- brauchen 3n Bits zur Dekodierung
- Prozessoren mit 16 Bit
- 2-Adress-Befehle, wenig Register
- Prozessoren mit 32 Bit
- 3-Adress-Befehle, viele Register
## Konsequenzen aus der Registerarchitektur
- Gut
- Register erlauben schnellere Speicherung von Werten
- arithmetische Befehle lassen sich in einem Takt ausführen
- Register erlauben indirekten Zugriff auf Variablen
- Inhalt eines Registers wird als Adresse genutzt
- Registerbreite sollte groß genug für jede Adresse sein
- Schlecht
- Direkter Zugriff funktioniert bei einem Befehlssatz mit gleicher Breite aller Befehle nicht mehr
- Laden von Konstanten (Immediate Werte) in ein Register ist schwierig
- nur kleine Immediate Werte haben Platz im Befehlscode
## Link-Register für Unterprogrammaufrufe
- Speichert Rücksprungadresse bei Ausführung eines Unterprogramms
- (vorher: Push auf den Stack)
- Am Ende des UP wird die Adresse wieder in den PC geschoben
- (vorher: Pop vom Stack)
- Erlaubt Unterprogrammaufrufe ohne Speicherung auf Stack
## MU4 mit Registersatz (Übergang von Akkumulator- zur Registerarchitektur)
![image_135.png](image_135.png)
- Einfachste Operation (_add r1, r2, r3_) kann nicht erzeugt werden
- Registerbank hat nur Zugriff auf A-Bus
**Prozessor funktioniert so noch nicht!**
_Registerbank braucht Zugriff auf A- und B-Bus_
## MU5: Verbesserung des internen Bussystems und Shifter
![image_136.png](image_136.png)
- meiste Befehle lassen sich realisieren
- Jedes Register hat Ausgang auf A- und B-Bus
- Operanden, die über B-Bus in ALU kommen, können vorher noch geschoben werden
- Auf B-Bus können kleine Immediate-Werte aus IR in Berechnungen verwendet werden
- Es werden noch zu viele Takte pro Operation benötigt
- bisher konnten Registerinhalte auf A-Bus gelegt werden, Immediate auf B-Bus
- nicht optimal, da arithmetische Operationen zwei Registeroperanden haben
- Verbesserung, wenn Registerinhalte auf A-Bus und B-Bus gelegt werden können
### Shifter
- erlaubt es Operanden des B-Bus vor der Verarbeitung nochmal zu schieben
- Wichtig für Adressberechnungen
- häufig ein Wortoffset in eine Adresse auf Byte-Basis umgewandelt
## MU5: Verbesserte ALU
![image_137.png](image_137.png)
- Einsatz von Modifikatoren
- Kann Eingang durchschalten
- Kann alle Bits auf 0 / 1 setzen
- Einsatz eines Shifters
- Kann Wert um Shiftweite nach links / rechts schieben
- Kann Rotation durchführen
- Weitere Funktionen der ALU
- Neben **A+B, A-B, A+B+1**
- **A AND B**
- **A OR B**
- **NOT A**
- **NOT B**
- **A XOR B**
## MU5 Fetch-Zyklus
![image_138.png](image_138.png)
- in Aout muss Kopie von PC stehen
- vorheriger Befehl muss sicherstellen, dass das gegeben ist
- Insbesondere Datentransfer-Befehle
## Arithmetische Operationen
![image_139.png](image_139.png)
- brauchen ein Taktzyklus + Fetch
## Datentransfer
![image_140.png](image_140.png)
## Steuermatrix des MU5
![image_141.png](image_141.png)
![image_142.png](image_142.png)
## Vergleich MU5 - ARM-Design
- Datenverarbeitungsbefehle können wie bei ARM in einem Takt durchgeführt werden
- Datentransferbefehle
- MU5: 3 Takte
- ARM: 2 Takte
- Dout-Register gibt Informationen direkt an Speicher
- Din braucht auch keinen Takt Verzögerung
- ARM-Prozessor
- Kann Daten über Din direkt in Registerbank zu schreiben
- sonst wären einige Adressierungsarten nicht möglich
## MU5a
### Verbesserte Adressberechnung und Umstellung der Speicheradressierung
![image_143.png](image_143.png)
#### Optimierung der Speicheradressierung
- 32 Bit → Register, Bus, ALU
- Speicher bisher wortweise
- verbraucht für kleine Datenwerte viel Speicher
- Umstellung auf byteweise Adressierung erlaubt Einführung neuer Befehle für Adressierung von Halbwörtern
- zusätzlicher Incrementer für Register mit Speicheradressen
- effiziente Inkrementierung um 2 oder 4
![image_144.png](image_144.png)
#### Speicheradressierung
![image_145.png](image_145.png)
![image_146.png](image_146.png)
> AB 01 CD 23 steht im Speicher als 23 CD 01 AB

View File

@ -0,0 +1,30 @@
# MU6-Rechner
## Harvard-Architektur
- Trennung von Daten und Befehlsbus
- In einem Takt können Daten geholt/geschrieben und ein Befehl geholt werden
- Durchsatz wird deutlich erhöht
- Adressregister erhält einen Addierer, um Blocktransfers von Daten zu ermöglichen
- Zurückschreiben der letzten Adresse in ein Register erfordert Zugriff auf C-Bus
## Vergleich Harvard- / [Von-Neumann-Architektur](Prozessorkonzepte.md#von-neumann-rechner-speicherprogrammierter-rechner)
| Harvard | Von Neumann |
|-----------------------------------------------------------|----------------------------------------|
| je ein Befehls- und Datenbus | Nur ein Bus für Befehle und Daten |
| schnellerer gleichzeitiger Zugriff auf Programm und Daten | Kein Programm Fetch bei Datenzugriffen |
| ![image_149.png](image_149.png) | ![image_150.png](image_150.png) |
## Datenpfad mit Harvard-Architektur
![image_151.png](image_151.png)
- Barrelshift-Einheit der ARM-Prozessoren im B-Bus hier nicht eingezeichnet
- I-MEM = Speicher für Programme / Cache
- D-MEM = Speicher für Daten / Cache
## MU6-Architektur
- Wichtigste Änderung: Trennung von Instruktions- und Datenspeicher
- Da PC immer Instruktionsadresse vorgibt
- PC und Instruktions-Adressregister (IADR) sind identisch
- PC taucht im Registerfile noch auf
- sein Wert kann auf A- / B-Bus gelegt werden
- Werte im Instruktionregister können für [ALU-Operationen](MU4-5Rechner.md#mu5-verbesserte-alu) verwendet werden
- Man könnte Takte sparen
- WENN Dout und Din nicht Register, sondern ein direkter Zugriff möglich

View File

@ -0,0 +1,50 @@
# MU7-Rechner
## Pipeline
- erlaubt den nächsten Befehl zu holen während der letzte noch bearbeitet wird
- für Implementierung notwendig:
- Ergebnisse jeder Pipelinestufe in Zwischenregistern speichern
- Stufen werden unabhängig voneinander
- Stufen können gleichzeitig arbeiten
- Für jede Stufe eigenes Instruktionsregister
- steuert Abarbeitung des jeweiligen Befehls
- Sprungbefehle führen zu äußerem Eingriff in den Ablauf der Pipelinestufen
- kann Ausführung der jeweiligen Operation verhindern
- **Moderne Pipelines:**
- Pipelines mit 5-17 Stufen
- längere Bearbeitung von Floatingpoint-Befehlen → lange Pipelines
## Datenpfad mit 5-Stufen Pipeline
![image_152.png](image_152.png)
## Pipeline 6-stufig
![image_153.png](image_153.png)
- **fetch**: nächsten Befehl aus Speicher holen
- **dec**: Befehl dekodieren (Befehlsart ermitteln)
- **reg**: Operanden aus Registerbank holen
- **ALU**: ALU Berechnung / Speicheradresse berechnen
- **mem**: Zugriff auf Speicher
- **res**: Ergebnis in Registerbank zurückschreiben
## Pipeline-Hazard durch Registerzugriff
read after write Hazard
![image_154.png](image_154.png)
## Nachteil der Pipeline: Sprungbefehle
- Sprungbefehle brauchen 5 Takte zusätzlich um nächste gültige Instruktion auszuführen
- alle Befehle in der Pipeline müssen verworfen werden
- Ausweg: **Forwarding**
- Nach Berechnung der neuen Sprungadresse
- Direkt in IADR Register/PC schreiben
- nur noch 3 Leertakte
- ist in allen modernen Prozessoren vorhanden
## Pipeline-Hazard durch Sprungbefehl
Sprungverhalten einer Pipeline mit Forwarding
![image_155.png](image_155.png)
## Datenpfad mit 5-Stufen Pipeline und Forwarding des PC
![image_156.png](image_156.png)

View File

@ -0,0 +1,33 @@
# Prozessorkonzepte
## Was sollte ein Rechner können
- Rechnen
- **`+` `-` `*` `/`**
- **Datenbewegung** (kopieren)
- **Strukturierte Lösung eines Problems**
- Abfolge von Rechenoperationen
- Verwendung von Daten, indirekte Adressierung, Pointer
- Schleifen, Sprünge
- Unterprogramme (Strukturen)
- **Spezielle Befehle** (z.B. Interrupts zur Anbindung von Peripherie)
- **Performance**
- Optimierung der Datenzugriffe (schneller)
- mehr Daten
- spezielle Algorithmen z.B. Graphik, Audio-Codecs, ...
- **Energieeffizienz**
## Von-Neumann-Rechner (Speicherprogrammierter Rechner)
Veröffentlicht 1945
![image_20.png](image_20.png)
- _Arithmetic Logic Unit_ - Rechenwerk
- _Control Unit_ - Steuerwerk
- _Memory_ - Speicherwerk
- _Input/Output_ - Ein-/Ausgabewerk
## MU0 - MU7
### [MU0 - Rechner: Basiskonzept](MU0Rechner.md)
### [MU1 - Rechner: kompletter Rechner](MU1Rechner.md)
### [MU2/3 - Rechner](MU2-3Rechner.md)
### [MU4/5 - Rechner: Adressberechnung, Register-Architektur, Load-Store](MU4-5Rechner.md)
### [MU6 - Rechner: Harvard-Design](MU6Rechner.md)
### [MU7 - Rechner: Pipelining](MU7Rechner.md)

View File

@ -0,0 +1,104 @@
# ARM
## ARM Prozessoren
### Architektur Revisionen
- Unterschiedliche Features
- bspw. unterschiedliche Multiplikationsbefehle, Adressierungsarten, ...
- jeweils gleiches Befehssatzdesign für jede Revision
- aktuell: v7 / v8
### Profile: Konkrete Prozessor-Implementierungen
- Application Profil ['A']:
- High Performance
- bspw. Mobile, Enterprise
- Real Time Profil ['M']:
- Embedded Anwendungen
- bspw. Automotive, Industriesteuerungen
- Microcontroller Profil ['M']:
- Mikrocontroller für große Bandbreite an Anforderungen
- Anzahl Gatter, Kosten, Realtime, Performance
- Aktuell in 2017:
- v7 (32Bit):
- Cortex A7, Cortex M4, Cortex M0+
- v8 (64Bit):
- Cortex A53, Cortex A57
## Bedeutung des Befehlssatzes (ISA)
- Befehlssatz = Instruction Set Architektur
- ISA Level
- ist das Interface zwischen Soft- und Hardware
- definiert die Sprache, die von Soft- & Hardware verstanden werden muss
- ![image_291.png](image_291.png)
### ARM Instruction Sets
![image_292.png](image_292.png)
- ARM unterstützt derzeit 3 IS
- A64 instruction set
- eingeführt mit ARMv8-A, um 64 Bit zu unterstützen
- A32 instruction set ("ARM")
- 32 Bit Befehlsatz in pre-ARMv8-Architekturen
- T32 instruction set ("Thumb"/"Thumb2")
- komprimierter 16/32 Bit Befehlssatz (gemischt)
- in pre-ARMv8-Architekturen
## Coding Standards UAL und APCS
### Unified Assembler Language (UAL)
- Coding Standard, der von Compilern für ARM (32bit) und Thumb verstanden wird
- Macht Programme möglich, die mit verschiedenen Prozessoren kompatibel sind
### ARM Program Calling Standard (APCS)
- Regelt Aufruf von
- Unterprogrammen
- Verwendung von Registern
- ...
- Ermöglicht Verwendung von Objektbibliotheken, welche von anderen Compilern übersetzt wurden
## Architektonisches Erbe der ARM-Prozessoren
**Verwendete Merkmale**
- RISC
- Grundlegendes Design-Prinzip: Einfachheit
- Load/Store Architektur (Register-Register), von Neumann
- 32Bit oder 64Bit (1 Wort)
- 1Byte = 8Bit
- Byteweise Adressierung des Speichers
- Little-Endian und Big-Endian kompatibel
- Vorteil für Einsatzzweck als Standard CPU in Kommunikationsgeräten
- Standard: Little-Endian
- [3-Adressbefehle](Klassifikation.md#3-adress-befehle) (32Bit) oder Thumb
**Verworfene Merkmale**
- Registerfenster
- wird nur bei SPARC Prozessoren genutzt
- Delayed Branches
- der dem Branch folgende Befehl wird ausgeführt bevor der Sprung durchgeführt wurde
- Behandlung von Interrupts und Exceptions schwieriger
- Ausführung aller Befehle in einem Taktzyklus
- setzt [Harvard](MU6Rechner.md#harvard-architektur) voraus
- Kompensation durch verbesserte Adressierungsmodi
## Ein erstes ARM-Programm (GNU)
![image_293.png](image_293.png)
### Wie wird aus einem Programm Maschinencode?
![image_294.png](image_294.png)
- Codierungsvorgang immer gleich
- kann von Programm (_Assembler_) übernommen werden
- Kann weitere Erleichterungen ermöglichen
- Bezeichner Konstanten, Daten, Adressen
- Reservieren von Speicherbereichen für (Zwischen-)Ergebnisse
- Anlegen und Initialisieren von Daten und Datenstrukturen beim Programmstart hinzufügen
-
## [ARM Toolchain](arm_toolchain.md)
## [ARM Befehle](arm_befehle.md)

View File

@ -0,0 +1,130 @@
# ARM Adressierung
## Datentransfer-Befehle
- Einzelregister-Transfer-Befehle (MOV, MVN, MRS, MSR)
- Einzeltransfer-Load/Store-Befehle
- Blocktransfer-Load/Store-Befehle
## Datentransfer
### Datentransfer zwischen Speicher und Register
ldr r0, [r1]
str r0, [r1]
- R0: Zielregister
- R1: enthält Speicheradresse, von der geladen/gespeichert wird
- Langsamer Transfer zwischen Speicher- und Rechenwerk
### Zwischen Registern
mov r0, r1
- R0: Zielregister
- R1: Quellregister
- Schneller Transfer innerhalb des Rechenwerks
## Speicherorganisation
- Byte-orientierter Speicher
- Speicherstelle: **1 Byte**
- Transfer-Befehle liefern meist 32 Bit
- ![image_423.png](image_423.png)
### Little Endian
![image_424.png](image_424.png)
### Alignment im Speicher
- Ausrichtung der Adressen für Zugriffe an Worten (32Bit = 4 Byte)
- ![image_425.png](image_425.png)
- erlaubt einfachere Speicheranbindung, wenn Wortweise gelesen wird
- Cache Speicherung mindestens nach Worten ausgerichtet
- Wenn man Bytes frei anordnen würde, könnte eine Hälfte im Cache stehen, die andere nicht verfügbar
- **Intel:**
- Jedes Wort kann auf jeder Adresse stehen
- nicht ausgerichtete Wörter brauchen 2 Speicherzugriffe
- wäre langsamer
## Speicheraufteilung / Assembleranweisungen
- **.text**
- Legt Textbereich an
- **.align #Bits**
- nachfolgende Anweisung steht auf Speicherstelle, deren unteren #Bits 0 sind
- **.data**
- Legt Datenbereich an
- **.comm symbol, size**
- Legt Symbol in globale bss-Section für uninitialisierte Daten
- **.word Ausdruck**
- Legt initialisierten Speicherbereich mit Größe 4 Byte an
- **.byte Ausdruck**
- Legt initialisierten Speicherbereich mit Größe 1 Byte an
![image_426.png](image_426.png)
## Befehle LDR und STR
- Zugriff erfolgt indirekt
- Speicherung kann indiziert / mit Offset vorgenommen werden
- zum Zugriff genutzter Zeiger kann vor / nach Zugriff in-/dekrementiert werden
![image_427.png](image_427.png)
## Immediate Adressierung
- ![image_428.png](image_428.png)
- Operand wird direkt im Befehl gespeichert
- Kein weiterer Speicherzugriff erforderlich
## Direkte Adressierung
- ![image_429.png](image_429.png)
- Adresse befindet sich im Opcode
- Kann während der Laufzeit nicht mehr geändert werden
- **Achtung:**
- RISC kann nicht 32Bit im Opcode → nicht möglich
## PC-relative Adressierung
- Zugriff auf Daten mit _ldr register, label_
- Laden der ADresse erfolgt über Konstante
- wird PC-relativ adressiert
- Befehl ldr r0, Label
- Pseudobefehl, wird vom Assembler in passenden Befehl umgesetzt
- Beispielsweise:
- ```
add r0, pc, #8
sub r0, pc, #0xb7
ldr r0, [r0]
ldr r0, [pc, #8]
```
- Speicherinhalt an Stelle Label wird geladen
## Pipelining
- ![image_430.png](image_430.png)
- im PC immer aktuelle Befehlsadresse + 8
## Register-Adressierung
- `mov r0, r1`
- ![image_431.png](image_431.png)
- Wie [direkte Adressierung](#direkte-adressierung). nur mit Speicher- statt Registeradresse
### Register-indirekte Adressierung
- Beispiel: `ldr r0, [r1]`
- ![image_432.png](image_432.png)
- Benutzt Registerwert (**Basisregister**) als Speicheradresse
- zum Laden/Speichern des Wertes an der Adresse
- einer der Operanden aus dem Speicher, andere im Register
- Registeradressierung über Pointer
- Gesamter Speicherbereich kann adressiert werden, ohne dass Adresse in der Instruktion sein muss
### Beispiel Kopieren
![image_433.png](image_433.png)
## Indizierte Adressierung
- Register + Offset Adressierung
- Beispiel: `ldr r0, [r1, #8]`
- ![image_434.png](image_434.png)
- Kommt häufig vor, dass Speicher zugegriffen wird, der einen Offset relativ zur Basisadresse besitzt
- Adressierung über Register plus konst. Offset = **indexed Adressing**
- Arm:
- ![image_435.png](image_435.png)
- ![image_436.png](image_436.png)
## Beispiel Kopieren indiziert
- ![image_437.png](image_437.png)
- ![image_438.png](image_438.png)
-

View File

@ -0,0 +1,404 @@
# ARM Befehle
## ARM 7
- Architektur: ARM v4T, Prozessor ARM7 TDMI
- 1994 rausgekommen
- 12-70 MHz, 0,889 DMIPS/MHz
- [RISC](Klassifikation.md#risc-prinzipien), Load-Store-Architektur
- 3-stufige [Pipeline](MU7Rechner.md#pipeline)
- Instruction Set
- ARM 32 bit oder Thumb
- [3-Adress-Befehle](Klassifikation.md#3-adress-befehle)
- Little Endian als Standard
### ARM-Datenpfad
![image_302.png](image_302.png)
### ARM7-ALU
![image_303.png](image_303.png)
### ARM7-Pipeline für ALU-Befehle
![image_304.png](image_304.png)
- Latenz
- 3 Zyklen
- Durchsatz
- 1 Befehl je Zyklus
#### Multi-cycle Execution
- Execute benötigt einen Takt für simple Instruktionen
- Bei Speicherzugriff mind. 2 Takte
- Adress Berechnung
- Speicherzugriff
- ![image_305.png](image_305.png)
## Load/Store Befehle Hazard in Von-Neumann
![image_306.png](image_306.png)
![image_307.png](image_307.png)
## ARM Registerstruktur
![image_309.png](image_309.png)
## Statusflags
- **N** (Negative)
- Das Ergebnis der ALU ist negativ (Bit 31=1)
- **Z** (Zero)
- Das Ergebnis der ALU ist Null (Bit 0..31 = 0)
- **C** (Carry)
- Bei arithmetischer Operation wird C auf Carry-Out der ALU gesetzt
- Sonst auf Carry-Out des Shifters bzw. ohne Shift Operation bleibt C erhalten
- **V** (Overflow)
- Wenn Zahlensystem geändert wird
- Wenn mit unsigned gerechnet wird ist V ohne Interesse
## Current Program Status Register (CPSR)
- ![image_310.png](image_310.png)
- **T-Bit**
- T = 0
- Prozessor in Arm State
- T = 1
- Prozessor in Thumb State
- **Interrupt Disable Bit**
- I = 1, disables IRQ
- F = 1, disables FIQ
- **Mode Bits**
- Spezifizieren Prozessor Mode
## Übersetzungstabelle Assembler - Binärcode
![image_311.png](image_311.png)
## Thumb Befehlsatz
- zusätzlicher Befehlssatz
- 16 Bit
- Intern werden sie auf 32 Bit erweitert
- Programme verbrauchen nur halben Speicher
- weniger Register stehen zur Verfügung
- Während Programmausführung kann zwischen ARM-32 und Thumb gewechselt werden
- Thumb-2 ist ein gemischter 16/32 Bit Befehlssatz
- Prozessor ARM7TDMI unterstützt sowohl ARM als auch Thumb
## ARM Befehlssatz
- Drei Befehlstypen
- zur Datenverarbeitung (bspw. Addition)
- Ablaufsteuerung (bspw. Verzweigungen)
- Befehle zur Adressierung
- Groß-Kleinschreibung wird ignoriert
### ARM-Befehle: MOV
- MOV ist ein Datentransferbefehl
- Kopiert Daten in ein Register
- Beispiele
- mov r0, r1 @Inhalt von R1 wird nach R0 kopiert
- mov r1, #0 @Zahl 0 wird nach R1 kopiert
- mov pc, lr @PC wird auf LR gesetzt
- Variante:
- mvn r1, r2
- Wendet zusätzlich zu mov ein EOR auf Inhalt von r2 an
### ARM-Befehle: ADD
- Die arithmetischen Befehle der ARM Prozessoren sind 3-Register-Befehle
- Alle Operanden sind 32Bit
- Das Ergebnis ist 32 Bit
- 3 Operanden: 2 als Input, 1 als Ergebnis
- Beispiel
- ADD r0, r0, r3 @R0 = R0 + R3
### ARM-Befehle: SUB
- ARM-Prozessoren implementieren keine Subtraktion
- Addition mit 2er Komplement
- Beispiel
- SUB r0, r0, r3 @R0 = R0 - R3 = R0 + (-R3)
### ARM-Befehle: CMP
- Befehl vergleicht zwei Werte auf Gleichheit und setzt Statusflags entsprechend
- CMP r0, #5 @r0 == r5?
- Dazu wird folgende Berechnung (r0=3) ausgeführt
- CMP r0, #5 @r0-5 = 3-5 ausgeführt
- MOV r1, #5
- SUBS r1, r0, r1
- Folgende Statusflags werden gesetzt
- ![image_312.png](image_312.png)
### ARM-Befehle: -S
- Setzen des Statusregisters bei arithmetischen und logischen Befehlen
- Bedingungsbits des Statusregisters werden nur bei Test-/Compare-Befehlen automatisch gesetzt
- Alle anderen Befehle müssen explizit setzen
- Beispiel
- add r0, r0, r3 @lässt Statusregister unverändert
- subs r0, r0, #1 @schreibt alle Flags NZCV
### ARM-Befehle: - {cond}
- Jeder Befehl kann bedingt ausgeführt werden
- Bedingung (bezogen auf vorher gesetzte Werte des Statusregisters) als Ergänzung an den Befehl angehängt
- Beispiel
- CMP r0, #5
- ADDNE r1, r1, r0
- SUBNE r1, r1, r2
- if (r0 != 5) {r1 = r1+r0-r2}
- NE = not equal
- Bezogen auf die vorherigen Werte des Statusregisters
#### Bedingte Ausführung von Befehlen
![image_313.png](image_313.png)
##### Signed/unsigned
![image_314.png](image_314.png)
##### carry set / higher same
- Beispiel:
- CMP r0, r1 @berechnet R0-R1, also R0 + (-R1) und setzt NZCV
- JCS sprungziel @springt zur Marke "sprungziel", wenn CS erfüllt ist
- Bedeutung: Wenn **unsigned >=** dann C gesetzt
- R0 = 3,R1 = 2 (nur 4-Bit Darstellung)
- R0 = 0011 2k = 1110
- Berechnet: 0011 + 1110 = 3 + (-2) = 0001
- C = 1
- R0 = 2, R1 = 3 (nur 4-Bit Darstellung)
- R0 = 0010 R1 = 0011
- Berechnet: 0010 + 1101 = 2 + (-3) = 1111
- C = 0
##### Bedingte Ausführung LT (Less than)
- Beispiel
- CMP R0, R1 @berechnet R0-R1 und setzt NZCV
- JLT sprungziel @springt zur Marke "sprungziel", wenn CS erfüllt ist
- Bedeutung: wenn **signed <** dann N ungleich V
- Beispiel 1
- R0 = 3, R1 = 4 (nur 8 Bit)
- R0 = 00000011 R1 = 00000100
- Berechnet: 00000011 + 11111100 = 3 + (-4) = 11111111
- N = 1, V = 0
- Beispiel 2
- R0 = -127, R1 = 2
- R 0 = 10000001 R1 = 00000010
- Berechnet: 10000001 + 11111110 = -127 + (-2) = 127 (?)
- N = 0, V = 1
### ARM-Befehle: Der Barrel Shifter
![image_315.png](image_315.png)
#### LSL: Logical Shift Left = Arithmetic Shift Left (ASL)
- ![image_316.png](image_316.png)
- Multiplikation mit einer Zweier-Potenz
- ![image_317.png](image_317.png)
- LSL R0, R1, #5 -> R0 = R1*2^5
#### LSR: Logical Shift Right
- ![image_318.png](image_318.png)
- Division durch eine Zweier-Potenz
- ![image_319.png](image_319.png)
- LSR R0, R1, #5 -> R0 = R1/2^5
#### ASR: Arithmetic Shift Right
- ![image_320.png](image_320.png)
- Division durch eine Zweier-Potenz unter Erhaltung des Vorzeichens
- ![image_321.png](image_321.png)
- ASR #5, positiver Operand
#### ROR: Rotate Right
- ![image_322.png](image_322.png)
- ![image_323.png](image_323.png)
#### RRX: Rotate Right Extended
![image_324.png](image_324.png)
#### Multiplikation mit einer Konstanten
- mit 2^x oder als 2^x +-1 darstellen lassen
- können in einem Zyklus durchgeführt werden
- Beispiel: Mul mit 5
- ADD r0, r1, r1, LSL #2
- Durch Zusammensetzen mehrerer Instruktionen können auch komplexere Multiplikationen durchgeführt werden
- Beispiel: Mul 10
- ADD r0, r1, r1, LSL #2
- LSL r0, r0, #1 @mov r0, r0, LSL#1
- Beispiel Mul mit 119 = 17·7 = (16+1)·(8-1)
- ADD r2, r3, r3, LSL #4 @r2 = r3·17
- RSB r2, r3, r2, LSL #3 @r2 = r2·7
## UAL (Unified Assembler Language)
- gemeinsamer Syntax für ARM32 und Thumb
- gleicher Code für beide Modi
- Falls Befehl nicht umgesetzt werden kann
- Assembler gibt Fehlermeldung aus
- Beispiel 1
- vorher
- Thumb: AND R0, R1
- ARM: AND, R0, R0, R1
- Jetzt: AND **R0, R0, R1**
- Beispiel 2
- vorher
- Thumb: LSL R0, R1, #2
- ARM: MOV R0, R1, LSL #2
- Jetzt: **LSL R0, R1, #2**
## Arithmetische und logische Befehle
![image_325.png](image_325.png)
### Binärcodierung arithmetischer und logischer Befehle
![image_326.png](image_326.png)
![image_327.png](image_327.png)
### Assembler Format
- Arithmetische und logische Befehle haben eins der beiden logischen Formate
- \<op\>{\<cond\>}{S} -> Rd, Rn, #\<32-Bit-Immidiate\>
- \<op>{\<cond\>}{S} -> Rd, Rn, Rm, {\<shift>}
- Rd: Destination
- Rn: Operand 1
- Rm: Operand 2
- Beispiel:
- ADD r0, r1, r2
- ADD r0, r2, #4
- MOV r0, r1
- ADDGTS r0, r1, r2, LSR r3
#### Operand 2 als Konstante (Immidiate)
- Befehlsformat für Datenverarbeitungsbefehle reserviert 12 Bits für Operand 2
- ergäbe einen Wertebereich von max 2^12 = 4096
- oder aufgeteilt in Wertebereiche mit 8 Bits (0-255)
- Diese 8 Bits können (links) rotiert werden
- gerade Anzahl von Positionen (0, 2, 4, ..., 30)
- Ergibt weitaus größere Abdeckung des Zahlenbereichs
- 8 zusammenhängende Bits innerhalb des 32-Bit-Wertebereichs
- ![image_328.png](image_328.png)
- Einige Konstanten müssen dennoch vom Speicher geladen werden
- oder in einem Register konstruieren
- ![image_329.png](image_329.png)
#### Operand 2 als Konstante
- Wertebereich
- | 0-255 | [0-0xff] |
|-----------------------------|--------------------------------------------|
| 256, 260, 264, ..., 1020 | [0x100-0x3fc, step 4, 0x40-0xff ror 30] |
| 1024, 1040, 1056, ..., 4080 | [0x400-0xff0, step 16, 0x40-0xff ror 28] |
| 4096,4160, 4224,..,16320 | [0x1000-0x3fc0, step 64, 0x40-0xff ror 26] |
- Beispiel MOV-Befehl
- MOV r0, #0xFF000000 @MOV r0, #0xFF, 8
- Beispiel MVN: erzeuge das bitweise 1er-Komplement
- MOV r0, #0xFFFFFFFF @umgesetzt zu MVN r0,#0
- Falls benötigte Konstante nicht erzeugt werden kann
- Assembler erzeugt Fehlermeldung
## Multiplikation
![image_330.png](image_330.png)
## Befehle zur Ablaufsteuerung
### Sprungbefehle (Branch)
- dienen dazu den Kontrollfluss von Programmen zu kontrollieren
- in Kombination mit Vergleichsbefehlen
- können alle wichtigen Anweisungen (if, else, while, for, switch) darstellen
- Ziel ist immer eine Marke (Label)
- Assembler erzeugt Sprungadresse
- Beispiel
- ```
CMP R0, #0
BNE Marke 1
...
...
Marke 1: MOV R5, #5
```
- ![image_331.png](image_331.png)
### Sprungbefehle
![image_332.png](image_332.png)
#### Unterprogramme (Branch-with-Link)
- Der Befehl BL führt einen Sprung aus
- speichert die Rücksprungadresse im Link-Register r14(LR)
- Weitere Subroutinen müssen r14(LR) im Speicher sichern
- bspw. auf Stack und bei Rückkehr in r15(PC) wieder herstellen
- Arbeitsregister können ebenfalls gesichert werden
- wenn Unterprogramm diese benötigt
- Übergabe von Parametern nach APCS-Standard
- Beispiel
- ![image_333.png](image_333.png)
#### Sprungbefehle mit Mode-Wechsel (32Bit Thumb)
- **BX Rn Branch and Exchange**
- Als Argument erhält der Befehl eine Registeradresse
- Inhalt wird in PC kopiert
- Falls ungerade → Wechsel in Thumbmode
- Falls gerade → Wechsel in ARM-Mode
- Befehl **BX LR** ist Standardbefehl um Unterprogramme zu verlassen
- Rücksprungadresse steht noch im Linkregister
- **BXL Label - Branch and Link with Exchange**
- Standardbefehl zum Aufruf von Unterprogrammen
- wird in Programmen mit gemischtem 32-Bit/Thumb Code genutzt
- **BLX Rn**
- Führt Modewechsel durch
- Speichert nächste Adresse im Linkregister
#### Unterprogrammaufruf mit Modewechsel
![image_334.png](image_334.png)
### Befehle zur Ablaufsteuerung - Beispiele
- ![image_335.png](image_335.png)
- Befehle MOV PC, Rd, ist nach Einführung des Thumb Befehlssatzes nicht mehr empfohlen
- Lässt direkten Zugriff auf PC nicht zu
- Stattdessen BX, BLX
- Alle Sprungbefehle können bedingt ausgeführt werden
- Offset der Sprungbefehle bis zu 32 MByte
- FÜr größere Sprünge muss Zieladresse erst in ein Register geladen werden
### Assembler-Format der Sprungbefehle
![image_336.png](image_336.png)
## APCS (ARM Procedure Calling Standard)
- Standard definiert wie Funktionen geschrieben werden sollen
- können unabhängig geschrieben, compiliert, assembliert uns später gelinkt werden
- Umfasst auch andere Programmiersprachen wie C
- Definiert sind
- Anforderungen an aufrufende/aufgerufene Funktionen
- Einschränkungen bei der Nutzung von Registern durch Funktionen
- Daten- und Stacklayout und Konventionen
- C/C++ Language Bindings, shared libs, reentrant code, etc.
### Parameterübergabe an Funktionen
- Funktionsaufruf:
- Result = fct(ARG1, ARG2, ARG3, ARG4)
- Parameter 1-4 in Register r0-r3 übergeben
- Rückgabewert von Funktionen steht im Register r0 oder r0/r1
- Verwendung von Registern in der Funktion
- r0-r3 und IP = Scratch Register
- dürfen im Unterprogramm zerstört werden
- Informationen in r4-r10, fp, sp dürfen nicht zerstört werden
- Inhalt von lr wird zur Rückkehr ins aufrufende Programm benötigt
- ![image_337.png](image_337.png)
## [ARM Adressierung](arm_adressierung.md)

View File

@ -0,0 +1,48 @@
# ARM Toolchain
![image_296.png](image_296.png)
## Targets
### Entwicklung auf dem Device
- Native Toolchain
- Benötigt ein OS
### Cross Entwicklung
- Compiler auf dem PC übersetzt für Hardware für die Zielplattform
### Entwicklung im Emulator auf dem PC
- Compiler auf dem PC übersetzt für Hardware, ausgeführt im Simulator
- Wenn Hardware nicht verfügbar oder Entwicklung zeitaufwändig
- Insight, QEmu
### Bare Metal
- Für Mikroprozessor ohe BS
### Betriebssysteme
- Linux
- Embedded Windows
- Realtime OS
## Toolchain für das Praktikum
![image_297.png](image_297.png)
## GNU ARM Assembler
- ![image_298.png](image_298.png)
- rn = Registername
### Assembler-Direktiven
- können Übersetzungsvorgang steuern
- können Speicherbereiche für das Programm reservieren
- ![image_300.png](image_300.png)
- können Datenstrukturen für das Programm anlegen und initialisieren
- ![image_299.png](image_299.png)
### Pseudobefehle
- Befehle, die es in der Maschinensprache nicht gibt, aber häufig gebraucht werden
- Assembler übersetzt diese in eine geeignete Sequenz von "echten" Assemblerbefehlen
- Beispiel:
- ![image_301.png](image_301.png)
-