Sie sind auf Seite 1von 16

1

Levels of Program Code

● High-level language
○ Level of abstraction closer
to problem domain
○ Provides for productivity and
portability

● Assembly language
○ Textual representation of
instructions

● Hardware representation
○ Binary digits (bits)
○ Encoded instructions and
data

❓ For a given function, which programming language likely takes the most lines of code?
Put the three representations below in order.
A. Java
B. C
C. Legv8
Answer : Legv8, C, Java

Instruction Set Architecture (ISA)


● Das Spektrum der Anweisungen, Datentypen und Registern eines Computers
● Die Schnittstelle zwischen Hardware und Software
● Verschiedene Computer haben unterschiedliche Befehlssätze
○ aber mit vielen Gemeinsamkeiten: "regionale Dialekte".
● Frühe Computer hatten sehr einfache Befehlssätze
○ dies vereinfachte ihre Implementierung
● Auch viele moderne Computer begannen häufig mit einfachen Befehlssätzen

Warum Assembler-Programmierung?
- hocheffizienten Code für eine bestimmte Hardware schreiben
- die Ausgabe des Compilers zu analysieren, um Leistungsprobleme zu erkennen
- Zugriff auf und Aktualisierung von hardwarespezifischen Registern
2

- Nutzung neuester Anweisungen, die vom Compiler noch nicht verwendet werden
- Fehlersuche, z. B. Analyse von Core-Dumps
- Reverse-Engineering von unbekanntem Binärcode
- Debugging von Systemcrashs, z. B. mithilfe von Core-Dumps
* Kenntnisse der Assembler Programmierung bzw. des ISA sind wesentlich für das
Verständnis von Computer Architekturen.

Classification of Microprocessors along ISAs:

CISC versus RISC

CISC: RISC:
● Intel x86 ● MIPS (Microprocessor without Interlocked Pipelined Stages)
● IBM Z ● SPARC (Scalable Processor Architecture)
Systems ● ARMv8 (LEGv8)
● RISC-V
● IBM Power Systems
3

The LEGv8* Instruction Set


LEGv8 instructions (RISC):
• arithmetic (8)
• data transfer (12)
• logical (8)
• conditional branch (3)
• unconditional branch (3)
‒ LEGv8 operands:
• registers (32)
• memory bytes (264)

ARMv8 operands:
Programmiersprachen haben einfache Variablen, die einzelne Datenelemente enthalten, wie
in diesen Beispielen, aber sie haben auch komplexere Datenstrukturen - Arrays und
Strukturen. Diese zusammengesetzten Datenstrukturen können viel mehr Datenelemente
enthalten als es Register in einem Computer gibt. Wie kann ein Computer solche großen
Strukturen darstellen und darauf zugreifen?

Erinnern Sie sich an die fünf Komponenten eines Computers, die in Kapitel 1 eingeführt
wurden. Der Prozessor kann nur eine kleine Menge von Daten in Registern speichern, aber
der Computermemory enthält Milliarden von Datenelementen. Daher werden
Datenstrukturen (Arrays und Strukturen) im Memory aufbewahrt .
4

Arithmetic operations:

Logical operations:
5

Data transfer:
Wie oben erläutert, finden arithmetische Operationen nur auf Registern in LEGv8
Anweisungen; daher muss LEGv8 Anweisungen enthalten, die Daten zwischen Speicher
und Registern übertragen. Solche Befehle werden als Datentransfer-Befehle bezeichnet.

Um auf ein Wort oder Doppelwort im memory zuzugreifen, muss der Befehl die memory
adresse liefern. Der memory ist ein großes, eindimensionales Feld, wobei die Adresse als
Index für dieses Array dient, beginnend bei 0. Zum Beispiel ist in Abbildung unten, ist die
Adresse des dritten Datenelements 2, und der Wert des Speichers [2] ist 10.

Der Datentransfer-Befehl, der Daten aus dem Speicher in ein Register kopiert, wird
traditionell als Load bezeichnet. Das Format des Ladebefehls ist der Name der Operation,
gefolgt von dem zu ladenden Register, dann das Register und eine Konstante, die für den
Speicherzugriff verwendet wird. Die Summe aus dem konstanten Teil des Befehls und dem
Inhalt des zweiten Registers bildet die Speicheradresse. Der eigentliche LEGv8-Name für
diesen Befehl lautet LDUR und steht für Register laden.

Beispiel1:
Kompilieren einer Zuweisung, wenn sich ein Operand im Speicher befindet. Nehmen wir an,
dass A ein Array von 100 doublewords ist und dass der Compiler die Variablen g und h wie
zuvor mit den Registern X20 und X21 verbunden hat.
6

Nehmen wir außerdem an, dass die Startadresse oder Basisadresse des Arrays in X22 liegt.
Kompilieren Sie diese C-Zuweisungsanweisung:

g = h + A[8];

Obwohl diese Zuweisungsanweisung eine einzige Operation enthält, befindet sich einer
der Operanden im Speicher, also müssen wir zuerst A[8] in ein Register übertragen. Die
Adresse dieses Array-Elements ist die Summe aus der Basis des Arrays A, die sich im
Register X22 befindet, plus der Zahl zur Auswahl von Element 8. Die Daten sollten in
einem temporären Register Register abgelegt werden, um im nächsten Befehl verwendet
zu werden.
→ Die erste kompilierte Anweisung lautet:

LDUR X9,[X22,#8] // Temporäres Register X9 erhält A[8]

Die folgende Anweisung kann mit dem Wert in X9 (der A[8] entspricht) arbeiten, da er sich
in einem Register befindet. Die Anweisung muss h (enthalten in X21) zu A[8] (enthalten in
X9) addieren und die Summe in das Register das g entspricht (das mit X20 verbunden
ist):

ADD X20,X21,X9 // g = h + A[8]

Das Register, das zur Bildung der Adresse addiert wird (X22), wird als Basisregister
bezeichnet, und die Konstante in einem Datentransfer-Befehl (8) wird als Offset
bezeichnet.

Beispiel2:
Angenommen, die Variable h ist dem Register X21 zugeordnet und die Basisadresse des
Arrays A befindet sich in X22. Wie lautet der LEGv8-Assemblercode für die folgende
C-Zuweisungsannweisung unten?

A[12] = h + A[8];

Obwohl die C-Anweisung eine einzige Operation enthält, befinden sich nun zwei der
Operanden im Speicher, so dass wir noch mehr LEGv8-Anweisungen benötigen. Die
ersten Die ersten beiden Anweisungen sind die gleichen wie im vorherigen Beispiel, nur
dass wir diesmal den richtigen Offset für die Byte-Adressierung in der
Load-Register-Anweisung verwenden, damit wir A[8], und der ADD-Befehl setzt die
Summe in X9:

LDUR X9, [X22,#64] // Die temporäre Variable X9 erhält A[8]

ADD X9,X21,X9 // Temporäres Register X9 erhält h + A[8]

Der letzte Befehl speichert die Summe in A[12], wobei 96 (8 × 12) als Offset und das
Register X22 als Basisregister verwendet werden.

STUR X9, [X22,#96] // Speichert h + A[8] zurück in A[12]


7

Conditional branch:
8

Unconditional branch:

Constant or Immediate Operands


In vielen Fällen wird ein Programm eine Konstante in einer Operation verwenden - zum
Beispiel, Inkrementieren eines Indexes, um auf das nächste Element eines Arrays zu
verweisen. Tatsächlich haben mehr als die Hälfte der arithmetischen LEGv8-Anweisungen
eine Konstante als Operand.
Wenn wir nur die Anweisungen verwenden, die wir bisher gesehen haben, müssten wir eine
Konstante aus dem Speicher laden, um eine zu verwenden. (Die Konstanten wären beim
Laden des Programms im Speicher abgelegt worden.) Um zum Beispiel die Konstante 4
zum Register X22 hinzuzufügen, könnten wir folgenden Code verwenden:

LDUR X9, [X20, AddrConstant4] // X9 = constant 4


ADD X22,X22,X9 // X22 = X22 + X9 (X9 == 4)

unter der Annahme, dass X20 + AddrConstant4 die Speicheradresse der Konstante 4 ist.
Eine Alternative, die den Ladebefehl vermeidet, ist die Bereitstellung von Versionen der
arithmetischen Anweisungen anzubieten, bei denen ein Operand eine Konstante ist. Diese
schnelle Additionsanweisung mit einem konstanten Operanden wird add immediate oder
ADDI genannt. Um 4 zum Register X22 zu addieren, schreiben wir einfach

ADDI X22,X22,#4 // X22 = X22 + 4

Konstante Operanden kommen häufig vor, und durch die Aufnahme von Konstanten in
arithmetischen Anweisungen sind die Operationen viel schneller und verbrauchen weniger
Energie, als wenn Konstanten aus dem Speicher geladen würden.

Die konstante Null hat eine weitere Funktion, nämlich die Vereinfachung des Befehlssatzes
durch nützliche Variationen anbietet. So ist beispielsweise die Operation Move nur ein
Additionsbefehl, bei dem ein Operand Null ist. Daher widmet LEGv8 ein Register XZR, das
fest mit dem Wert Null verdrahtet wird. (Es entspricht der Registernummer 31.) Die
Verwendung der Frequenz zur Rechtfertigung der Einbeziehung von Konstanten ist ein
weiteres Beispiel für die großartige Idee aus Kapitel 1, den Normalfall schnell zu
machen.ARMv8 Register Details
Im Gegensatz zu Programmen in Hochsprachen sind die Operanden von arithmetischen
Anweisungen eingeschränkt; sie müssen aus einer begrenzten Anzahl spezieller
Speicherplätze stammen, die direkt in die Hardware eingebaut sind und Register genannt
werden. Register sind Primitive, die bei der Konstruktion von Hardware verwendet werden
9

und auch für den Programmierer sichtbar sind, wenn der Computer fertiggestellt ist, so dass
man sich die Register als die Bausteine der Computerkonstruktion vorstellen kann.
Die Größe eines Registers in der LEGv8-Architektur beträgt 64 Bit; Gruppen von 64 Bit
kommen so häufig vor, dass sie in der LEGv8-Architektur als Doppelwort
“doubleword” bezeichnet werden. (Eine andere gängige Größe ist eine Gruppe von 32
Bits, die in der LEGv8-Architektur als Wort bezeichnet wird.)

doubleword Another natural unit of access in a computer, usually a group of 64 bits;


corresponds to the size of a register in the LEGv8 architecture.
word A natural unit of access in a computer, usually a group of 32 bits.

❖ Ein wesentlicher Unterschied zwischen den Variablen einer Programmiersprache und


Registern ist die begrenzte Anzahl von Registern, typischerweise 32 auf aktuellen
Computern, wie LEGv8.
❖ Der Grund für die Begrenzung auf 32 Register liegt im ersten ISA Design Principles
Design Principle 1: Smaller is faster.

- 31 x 64-Bit* General Purpose Register X0 bis X30


- jedes Register hat eine 32-Bit- (W0-W30) und eine 64-Bit-Form (X0-X30)
- das Schreiben in ein W-Register löscht die obersten 32 Bits des entsprechenden
X-Registers

ISA Design Principles


1. Smaller is faster → use only 32 register
a. compare to main memory: billions of locations, but much slower
2. Regularity enables performance*
a. Regelmäßigkeit macht die Implementierung einfacher → ermöglicht höhere
Leistung bei geringeren Kosten
b. Einfachheit hilft, Regelmäßigkeit zu erreichen
3. Make the common case fast
a. Small constants are common
b. Immediate operand avoids a load instructioN
4. Good design demands good compromises
a. Different formats* complicate decoding
i. but tradeoffs between simplicity, performance and functionality
b. Keep formats as similar as possible
i. e.g., keep same length (32 bits)
10

General-purpose registers use in the ARMv8 Architecture ABI:

● Argument registers (X0 X7)


○ pass parameters to a function and to return a result
● Caller saved temporary registers (X9 X15)
○ if the caller requires the values in any of these registers to be preserved
across a call to another function, the caller must save the affected registers in
its own stack frame
○ can be modified by the called subroutine without the need to save and restore
them before returning to the caller.
● Callee saved registers (X19 X28)
● these registers are saved in the callee stack frame
● they can be modified by the called subroutine as long as they are saved and restored
before returning

Registers with a special purpose:


● X8: indirect result register
○ e.g., pass the address location where a function returns a large structure
● X16, X17 (IP0, IP1): intra procedure call temporary registers
● X18: the platform register and is reserved for the use of platform ABIs
● X29: the frame pointer register (FP)
○ holds the stack pointer’s value before a function is called or points to the
previous frame pointer saved on stack (not strictly required)
● X30: the link register (LR)
○ holds the address to return to when a function call completes
● X31: either the constant 0 (XZR) or the stack pointer (SP) depending on the
instruction context:
○ for instructions dealing with the stack, it is the stack pointer
○ for all other instructions, it is a “zero” register, which returns 0 when read and
discards data when written
Special registers:
● Zero Register (XZR, X31)
● Stack Pointer (SP, X31)
● Program Counter (PC)
● Processor State (PSTATE)
11

Darstellung von Anweisungen im Computer


Wir sind nun bereit, den Unterschied zwischen der Art und Weise, wie Menschen
Anweisungen an Computern und der Art und Weise, wie Computer Anweisungen sehen.

Anweisungen werden im Computer als eine Reihe von hohen und niedrigen elektronischen
Signalen gespeichert und können als Zahlen dargestellt werden. In der Tat kann jeder Teil
einer Anweisung einer Anweisung als eine einzelne Zahl betrachtet werden, und die
Aneinanderreihung dieser Zahlen Aneinanderreihung bildet die Anweisung. Die 32 Register
der LEGv8 werden einfach durch ihre Nummer bezeichnet, von 0 bis 31.

LEGv8-Felder
Die Instrucktion sind binär kodiert,als Maschinencode bezeichnet
ARMv8/LEGv8-Befehle:
● Kodiert als 32-Bit-Befehlsworte
● Geringe Anzahl von kodierten Formaten
● Operationscode (Opcode), Registernummern, …
● Design principle: regularity!

LEGv8-Felder erhalten Namen, damit sie leichter zu diskutieren sind:

● Opcode: Grundlegende Operation des Befehls, und diese Abkürzung ist seine
traditionelle Bezeichnung.
● Rm: Der zweite Register-Quelloperand.
● shamt: Verschiebungsbetrag. (In Abschnitt 2.6 werden Schiebebefehle und dieser
Begriff erklärt; er wird bis dahin nicht verwendet, daher enthält das Feld in diesem
Abschnitt Null). - : shift amount
● Rn: Der erste Register-Quelloperand.
● Rd: Der Zieloperand des Registers. Er erhält das Ergebnis der Operation.

Übersetzen eines LEGv8-Befehls in eine Maschine Anweisung mit einem Bsp


Wir zeigen die echte LEGv8-Sprachversion der Anweisung, die symbolisch als

ADD X9,X20,X21

zunächst als Kombination von Dezimalzahlen und dann von Binärzahlen.


Die dezimalDarstellung lautet:

Jedes dieser Segmente einer Anweisung wird als Feld bezeichnet.


12

1. Das erste Feld (das in diesem Fall 1112 enthält) teilt dem LEGv8-Computer mit,
dass dieser Befehl eine Addition durchgeführt.
2. Das zweite Feld gibt die Nummer des Registers an, das der zweite Quelloperand
der Additionsoperation ist (21 für X21),
3. (Das dritte Feld ist bei dieser Anweisung unbenutzt und wird daher auf 0 gesetzt.)
4. und das vierte Feld gibt den anderen Quelloperanden für die Addition an (20 für
X20).
5. Das fünfte Feld enthält die Nummer des Registers, das die Summe erhalten soll (9
für X9).
Diese Anweisung addiert also Register X20 zu Register X21 und legt die Summe in
Register X9 ab. Diese Anweisung kann auch als Felder mit Binärzahlen statt mit
Dezimalzahlen dargestellt werden statt dezimal:

This layout of the instruction is called the instruction format. As you can see from
counting the number of bits, this LEGv8 instruction takes exactly 32 bits—a word, or one
half of a doubleword. In keeping with our design principle that simplicity favors regularity,
all LEGv8 instructions are 32 bits long.

LEGv8-Felder von I-format Instructions (Immediate instruction)

● Rn: source register number


● Rd: destination register number
● Immediate field is zero extended
● Remember Design Principle 3 and 4…

Example:
13

Assembly Pseudo Instructions


Pseudo Instructions: Eine häufige Variante von Assembler-Befehlen, die oft wie ein
eigenständiger Befehl behandelt wird. (Siehe Seite 168 im Buch.)

Ein Bespiel aus dem Buch:


14

Vorlesungsbeispiele:
15

ARMv8/GNU Arithmetic Operations : Example

Check Yourself:

True
False

Der erste Code : die Inhalte werden addiert.


Zweiter Code: Die Adressen werden addiert!
16

True
False

Das könnte Ihnen auch gefallen