# 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 - \{\}{S} -> Rd, Rn, #\<32-Bit-Immidiate\> - \{\}{S} -> Rd, Rn, Rm, {\} - 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)