• Keine Ergebnisse gefunden

Grundlagen der Rechnerarchitektur

N/A
N/A
Protected

Academic year: 2022

Aktie "Grundlagen der Rechnerarchitektur"

Copied!
151
0
0

Wird geladen.... (Jetzt Volltext ansehen)

Volltext

(1)

Grundlagen der Rechnerarchitektur

MIPS‐Assembler

MIPS Assembler

(2)

Übersicht

• Arithmetik, Register und Speicherzugriff

• Darstellung von Instruktionen g

• Logische Operationen W it A ith tik

• Weitere Arithmetik

• Branches und Jumps

• Prozeduren

• 32‐Bit‐Konstanten und Adressierung

• 32‐Bit‐Konstanten und Adressierung

• Synchronisation

• Exceptions

• Pseudoinstruktionen, Direktiven und Makros ,

(3)

Motivation

(4)

Warum ein Assembler‐Kurs?

• Wir wollen etwas über Rechnerarchitektur lernen. 

Assembler ist ein Teil davon.

• Nach dem Erlernen von Assembler eines Systems, 

l t A bl d R h ki d l i ht

lernt man Assembler anderer Rechner kinderleicht

• Während wir uns mit Assembler beschäftigen  g

lernen wir auch generelle Konzepte kennen, wie 

die Hardware in Computern und eingebetteten

die Hardware in Computern und eingebetteten 

Systemen organisiert ist

(5)

Vor‐ und Nachteile von Assembler

ll bl i ?

• Wann sollte man Assembler programmieren?

Code‐Größe oder Geschwindigkeit sollen bis auf das äußerste  ausgereizt werdeng

Verwendung  spezieller Maschineninstruktionen, die ein Compiler  nicht nutzt  (in der Regel bei CISC) 

Es gibt für die Computer‐Hardware keine höhere SpracheEs gibt für die Computer Hardware keine höhere Sprache

• Meist wird ein hybrider Ansatz gewählt

Man programmiert das meiste in einer High‐Level‐Sprache

Nur kleine Teile des gesamten Codes werden direkt in Assembler  optimiert

• Nachteil von AssemblerNachteil von Assembler

Programme laufen nur für den Hardwaretyp für den diese  programmiert sind

Assembler Code ist im Vergleich zu High Level Sprachen deutlich Assembler‐Code ist im Vergleich zu High‐Level‐Sprachen deutlich 

länger

Programmieren dauert deutlich länger

Programmieren ist fehleranfälliger (insbesondere wegen fehlender Struktur)

Programmieren ist fehleranfälliger (insbesondere wegen fehlender Struktur)

(6)

Assembler am Beispiel der MIPS‐Architektur

h i bi

• Frühere Einsatzgebiete MIPS

– Silicon Graphics Unix‐Workstations (z. B. SGI Indigo2)  Silicon Graphics Unix Server (z B SGI Origin2000)

– Silicon Graphics Unix‐Server (z. B. SGI Origin2000) 

– DEC Workstations (z.B. DECstation‐Familie und DECsystem) – Siemens bzw. SNI Server der RM‐Serie

– Control Data Corporation Computer des Typs CDC 4680 

• Heutiger Einsatz von MIPS in eingebetteten Systemen

– Cobalt‐Server bis RaQ/Qube2 – BMW‐Navigationssysteme

die Fritz!Box – die Fritz!Box

– Satellitenreceiver – DreamboxDreambox

– Konica Minolta DSLRs 

– Sony‐ und Nintendo‐Spielkonsolen

Quelle der Liste: de.wikipedia.org/wiki/MIPS‐Architektur

(7)

Warum gerade MIPS (und nicht Intel x86)?

k i i kl d i f h ( )

• MIPS‐Instruktionssatz ist klar und einfach (RISC)

• Sehr gut in Lehrbüchern beschrieben

• Sehr ähnlich zu vielen modernen Prozessoren (z.B. ARM; schauen  wir uns eventuell auch noch kurz an)

MIPS i t i k i ll l t I t kti t hit kt

• MIPS ist eine kommerziell relevante Instruktionssatzarchitektur. 

(z.B. 2002 wurden fast 100 Millionen MIPS Prozessoren  hergestellt)

hergestellt)

(8)

Begleitend: SPIM‐ und MARS‐Simulator

Programmieren lernt man nicht durch zuschauen!

Programmieren lernt man nicht durch zuschauen!

Alle Konzepte sollte man hier selber ausprobieren!

(9)

Arithmetik, Register und Speicherzugriff

(10)

Arithmetik und Zuweisungen

Ei f h A ith tik it Z i C Programm:

a = b + c;

MIPS Instruktionen:

Einfache Arithmetik mit Zuweisung

a = b + c;

d = a – e;

K l A ith tik it Z i

C Programm: MIPS Instruktionen (verwende temporäre 

Variablen t0 und t1):

Komplexere Arithmetik mit Zuweisung

f = (g + h) – (i + j);

(11)

Die Operanden sind Register

V i B i i l K l A ith tik it Z i C Programm:

f = (g + h) (i + j);

MIPS Instruktionen (verwende temporäre  Register $t0 und $t1):

Voriges Beispiel: Komplexere Arithmetik mit Zuweisung

f = (g + h) – (i + j);

Sei hierbei:

in Re ister $s1 espei hert

add $t0, $s1, $s2 # t0=g+h add $t1, $s3, $s4 # t1=i+j g in Register $s1 gespeichert

h in Register $s2 gespeichert i in Register $s3 gespeichert j in Register $s4 gespeichert

sub $s0, $t0, $t1 # f=t0-t1 j in Register $s4 gespeichert

f in Register $s0 gespeichert

MIPS Registergröße = 32 Bit

Assembler‐Syntax:

Das Zeichen # leitet für den Rest der Zeile einen Kommentar ein. 

(12)

Speicher‐Operanden

C Programm:

g = h + A[8];

MIPS Instruktionen (verwende temporäres  Register $t0):

Sei hierbei:

g in Register $s1 gespeichert h in Register $s2 gespeichertg $ g p

Basisadresse von A in Register $s3

Bildquelle: David A. Patterson und John L. Hennessy, „Computer Organization and Design“, Fourth Edition, 2012

(13)

Alignment‐Restriction

Zugriff auf A[8], wenn Basisadresse von A in Register $s3 gespeichert?g [ ], g $ g p

(14)

Laden und Speichern

C Programm:

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

MIPS Instruktionen (verwende temporäre  Register $t0):

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

Sei hierbei:

Basisadresse on A in in Re ister $s3 Basisadresse von A in in Register $s3  h in Register $s2 gespeichert

(15)

Laden und Speichern von Bytes

C Programm:

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

MIPS Instruktionen (verwende temporäre  Register $t0):

Sei hierbei:

Basisadresse von A in in Register $s3  h in Register $s2 gespeichert

h in Register $s2 gespeichert

Sei A[8] = 01110010. Was passiert im obigen Beispiel bei lb mit $t0 genau?

LSB

$t0 MSB

Sei A[8] = 11110010. Was passiert im obigen Beispiel bei lb mit $t0 genau?

$t0

(16)

Weitere Befehle zum Laden und Speichern

Laden von Byte ohne Sign‐Extension:

lbu { Beispiel: lbu $t0, 27($s3) }

Was passiert im obigen Beispiel mit $t0, wenn 27($s3) = 11001000?

$t0

LSB

$t0 MSB

Laden von Halfword mit Sign‐Extension:

lh { Beispiel: lh $t0, 22($s3) } Laden von Halfword ohne Sign‐Extension:

lhu { Beispiel: lhu $t0, 22($s3) } Speichern von Halfword:

sh { Beispiel: sh $t0, 22($s3) }

(17)

Addieren und Laden von Konstanten

C Programm:

x = x + 4;

MIPS Instruktion:

Sei hierbei:

x in Register $s3 gespeichert

MIPS erlaubt negative Konstanten und braucht damit kein ‚subi‘.

MIPS hat ein spezielles Register $zero, welches 0 ‘hart verdrahtet‘ speichert.

C Programm:

x = 42;

MIPS Instruktion:

Sei hierbei:

x in Register $s3 gespeichert

(18)

Zwischenbilanz der MIPS Architektur

CPU

Memory

Name Nummer Verwendung

$0 . Registers

g

$zero 0 Konstante 0

$at 1

. . .

$31

$v0‐$v1 2‐3

$a0‐$a3 4‐7

$t0 $t7 8 15 T ä R i t

$ Arithmetic

Unit

$t0‐$t7 8‐15 Temporäre Register

$s0‐$s7 16‐23 „saved“ temporäre Reg.

$t8‐$t9 24‐25 Temporäre Register

Unit $t8 $t9 24 25 Temporäre Register

$k0‐$k1 26‐27

$gp 28

$sp 29

$fp 30

$

$ra 31

(19)

Zusammenfassung der behandelten Instruktionen

Instruktion Bedeutung Instruktion Bedeutung

hmetik add rd, rs, rt Register rd = Register rs + Register rt

addi rt, rs, imm Register rt = Register rs + Konstante imm Arith addi rt, rs, imm Register rt  Register rs  Konstante imm

sub rd, rs, rt Register rd = Register rs –Register rt

lb rt, address Lade Byte an der Adresse address in Register rt.

en

Das Byte ist sign‐extended.

lbu rt, address Lade Byte an der Adresse address in Register rt.

Lade

lh rt, address Lade Half‐Word an der Adresse address in Register rt.

Das Half‐Word ist sign‐extended.

lhu rt address Lade Half‐Word an der Adresse address in Register rt lhu rt, address Lade Half Word an der Adresse address in Register rt.

lw rt, address Lade Word an der Adresse address in Register rt.

n sb rt, address Speichere unterstes Byte des Registers rt an Adresse address

Speichern , p y g

sh rt, address Speichere unteres Half‐Word des Registers rt an Adresse  address

S

(20)

Quiz

addi $s0, $zero, 4 # lw $s1, 0($s0) # l $ 2 4($ 0) # lw $s2, 4($s0) # add $s1, $s1, $s1 # add $s1, $s1, $s2 # add $s1, $s1, $s2 # addi $s1, $s1, 1 # sw $s1, 0($s0) #

Inhalt (Word)

Inhalt (Word)

8 4

12 33

dresse

8 12

dresse

0 421

4 12

8 4

A

0 4

A 8

Speicher zu Beginn Speicher nach Instruktionsdurchlauf

(21)

Darstellung von Instruktionen

(22)

Übersetzung aus Assembler in Maschinensprache

add $t0, $s1, $s2 Assembler‐

Instruktion

Name Nr

$s0 16

$s1 17

$s2 18

$s3 19

$s4 20

0 17 18 8 0 32

$s5 21

$s6 22

$s7 23

0 17 18 8 0 32

6 Bit Opcode

5 Bit Source1

5 Bit Source2

5 Bit Dest

5 Bit Shamt

6 Bit

Funct Name Nr

$t0 8

$s 23

$t1 9

$t2 10

$t3 11

00000010001100100100000000100000

Maschinen‐

$ 11

$t4 12

$t5 13

$t6 14

00000010001100100100000000100000

Instruktion $t6 14

$t7 15

(23)

Notwendigkeit für andere Instruktionsformate

add $t0, $s1, $s2

op rs rt rd shamt funct R‐Typ

6 Bit 5 Bit 5 Bit 5 Bit 5 Bit 6 Bit

?

lw $t0, 32($s3)

I Typ

Opcode 6 Bit

Source 5 Bit

Dest 5 Bit

Konstante oder Adresse 16 Bit

I‐Typ

(24)

Zwischenbilanz

Instruktion Format op rs rt rd shamt funct

add R 0 reg reg reg 0 32

sub R 0 reg reg reg 0 34

addi (immediate) I 8 reg reg constant

lw (load word) I 35 reg reg offset

lw (load word) I 35 reg reg offset

sw (store word) I 43 reg reg offset

6 Bit 5 Bit 5 Bit 5 Bit 5 Bit 6 Bit

16 Bit

(25)

Beispiel: A[300] = h + A[300]

$t1 sei Basisadresse von A und h in $s2 gespeichert. Assembler‐Code? Name Nr

$s0 16

$s1 17

$s2 18

$s3 19

$s4 20

Maschinen‐Code (der Einfachheit halber mit Dezimalzahlen)?

$s5 21

$s6 22

$s7 23

op rs rt rd adr/shamt funct Name Nr

$t0 8

$s 23

$t1 9

$t2 10

$t3 11

$ 11

$t4 12

$t5 13

$t6 14

Instruktion Format op rs rt rd shamt funct

add R 0 reg reg reg 0 32

lw (load word) I 35 reg reg offset $t6 14

lw (load word) I 35 reg reg offset

(26)

Logische Operationen

(27)

Logischer Links‐ und Rechts‐Shift

Erinnerung: Logischer Shift. Beispiel:

Links‐Shift um 4 Stellen Rechts‐Shift um 4 Stellen MIPS‐Shift‐Instruktionen sll und srl, sllv, srlv:, ,

sll $t2,$s0,4 # $t2 = $s0 << 4 Bits srl $t2,$s0,7 # $t2 = $s0 >> 7 Bits sllv $t2,$s0,$s1 # $t2 = $s0 << $s1 Bits srlv $t2,$s0,$s1 # $t2 = $s0 >> $s1 Bits

Beispiel: Maschineninstruktion für obige sll Assembler‐Instruktion:

R‐Typ

0 0 16 10 4 0

6 Bit

O d

5 Bit

S 1

5 Bit

S 2

5 Bit D t

5 Bit Sh t

5 Bit

F t

Opcode Source1 Source2 Dest Shamt Funct

(28)

Arithmetischer Rechts‐Shift

Erinnerung: Arithmetischer Rechts‐Shift. Beispiel mit 8‐Bit:

0011 0000 1101 0111

Rechts‐Shift um 4 Stellen Rechts‐Shift um 3 Stellen

Arithmetischer Rechts‐Shift in MIPS:

sra $t2,$s0,4 # $t2 = $s0 arithmetisch

# um 4 Bits geshiftet srav $t2,$s0,$s1 # $t2 = $s0 arithmetisch

# um $s1 Bits geshiftetg

(29)

E i AND

AND, OR, NOR und XOR

E i OR E i NOR E i XOR

Erinnerung: AND. Erinnerung: OR. Erinnerung NOR. Erinnerung XOR.

MIPS‐Instruktionen (R‐Typ), Beispiel:

d $t0 $t1 $t2 # $t0 $t1 AND $t2 and $t0,$t1,$t2 # $t0 = $t1 AND $t2 or $t0,$t1,$t2 # $t0 = $t1 OR $t2 nor $t0,$t1,$t2 # $t0 = $t1 NOR $t2 nor $t0,$t1,$t2 # $t0 $t1 NOR $t2 xor $t0,$t1,$t2 # $t0 = $t1 XOR $t2 MIPS Instruktionen (I Typ) Beispiel:

MIPS‐Instruktionen (I‐Typ), Beispiel:

andi $t0,$t1,0111 # $t0 = $t1 AND 0111 ori $t0,$t1,1100 # $t0 = $t1 OR 1100$ ,$ , # $ $

(30)

Es gibt gar kein NOT?!

Erinnerung NOT (auf Folie zu Zweierkomplement kurz eingeführt):

Beobachtung:

Wie kann man also „NOT($t0)“ in MIPS realisieren?

(31)

Zusammenfassung der behandelten Instruktionen

Instruktion Bedeutung

sll rd, rs, shamt Register rd = Register rs logisch links um den Wert shamt geshiftet.

sllvrd rt rs Register rd = Register rs logisch links um den in Register rs gespeicherten Wert

hift

sllvrd, rt, rs Register rd Register rs logisch links um den in Register rs gespeicherten Wert  geshiftet.

srl rd, rs, shamt Register rd = Register rs logisch rechts um den Wert shamt geshiftet.

srlv rd rt rs Register rd Register rs logisch rechts um den in Register rs gespeicherten Wert Sh srlv rd, rt, rs Register rd = Register rs logisch rechts um den in Register rs gespeicherten Wert 

geshiftet.

srard, rs, shamt Register rd = Register rs arithmetisch rechts um den Wert shamt geshiftet.

sravrd, rt, rs Register rd = Register rs arithmetisch rechts um den in Register rs gespeicherten Wert geshiftet.

ng andrd, rs, rt Register rd = Register rs AND Register rt.

Verknüpfun

or rd, rs, rt Register rd = Register rs AND Register rt.

nor rd, rs, rt Register rd = Register rs AND Register rt.

xor rd, rs, rt Register rd = Register rsAND Register rt.

Logische V xor rd, rs, rt Register rd Register rsAND Register rt.

andirt, rs, imm Register rt = Register rs AND Konstante imm ori rt, rs, imm Register rt = Register rs AND Konstante imm

L

(32)

Schwieriges Quiz

MIPS‐Assemblercode um folgende Funktion zu berechnen:

$ 1 di t 8 Bit 4 * NOT($ 1 AND $ 2)

$s1 = die ersten 8 Bits von 4 * NOT($s1 AND $s2)

Tipp: wir brauchen 

d d ll

and, nor und sll

(33)

Weitere Arithmetik

(34)

Die speziellen Register lo und hi

Erinnerung: ganzzahliges Produkt von zwei n‐Bit‐Zahlen benötigt bis  zu 2n Bits.

Eine MIPS‐Instruktion zur ganzzahligen Multiplikation von zwei  Registern der Länge 32‐Bits benötigt damit ein Register der Länge g g g g g 64 Bit, um das Ergebnis abzuspeichern.

MIPS hat für die ganzzahlige Multiplikation zwei spezielle Register lo MIPS hat für die ganzzahlige Multiplikation zwei spezielle Register, lo und hi, in denen das Ergebnis abgespeichert wird:

lo : Low‐Order‐Word des Produkts hi : Hi‐Order‐Word des Produkts.

Zugriff auf lo und hi erfolgt mittels mflo und mfhi. Beispiel:

mflo $s1 # lade Inhalt von lo nach $s1 mfhi $s2 # lade Inhalt von hi nach $s2

(35)

Ganzzahlige Multiplikation und Division

Ganzzahlige Multiplikation. Beispiel:

mult $s1, $s2 # (hi,lo) = $s1 * $s2 Ganzzahlige Division. Beispiel:

div $s1, $s2 # berechnet $s2 / $s1 div $s1, $s2 # berechnet $s2 / $s1

# lo speichert den Quotienten

# hi speichert den Rest

Register hi und lo können auch beschrieben werden. Beispiel:

tl $ 1 # L d I h lt $ 1 h l mtlo $s1 # Lade Inhalt von $s1 nach lo mthi $s2 # Lade Inhalt von $s2 nach hi Das ist sinnvoll für madd und msub. Beispiele:

madd $s1,$s2 # (hi,lo)=(hi,lo)+$s1*$s2

(36)

Ganzzahlige Multiplikation ohne hi und lo

Es gibt eine weitere Instruktion, zur Multiplikaiton, die kein hi und lo verwendet:

mul $s1 $s2 $s3 # $s1 die low order 32 mul $s1, $s2, $s3 # $s1 = die low-order 32

# Bits des Produkts von

# $s2 und $s3.

# $s2 und $s3.

(37)

Zwischenbilanz der MIPS‐Architektur

CPU

Memory

$0 . Registers

. . .

$31 Neu

$ Arithmetic

Unit

Multiply Divide

Unit Divide

Lo Hi

(38)

Die speziellen Register $f01 bis $f31

MIPS unterstützt mit einem separaten FPU‐Coprozessor 

Gleitkommaarithmetik auf Zahlen im IEEE 754‐Single‐Precision (32‐

Bi ) d D bl P i i F (64 Bi ) Bit) und Double‐Precision‐Format (64 Bit).

Die MIPS‐Floating‐Point‐Befehle nutzen die speziellen 32‐Bit‐

Die MIPS Floating Point Befehle nutzen die speziellen 32 Bit Floating‐Point‐Register (die Register des FPU‐Coprozessors):

$f0, $f1, $f3, ..., $f31

Single‐Precision‐Zahlen können in jedem der Register gespeichert  d ( l $f0 $f1 $f31)

werden (also $f0, $f1, ..., $f31).

Double‐Precision‐Zahlen können nur in Paaren von aufeinander Double Precision Zahlen können nur in Paaren von aufeinander  folgenden Registern ($f0,$f1), ($f2,$3), ..., ($f30,$f31) gespeichert  werden. Zugriff erfolgt immer über die geradzahligen Register (also 

$f0, $f2, ..., $f30).

(39)

Floating‐Point‐Befehle

Laden/speichern von Daten in die Register $f0,...,$f31 am Beispiel:

mtc1 $s1,$f3 # $f3 = $s1 f 1 $ 1 $f3 # $ 1 $f3 mfc1 $s1,$f3 # $s1 = $f3

lwc1 $f3,8($s1) # $f3 = Memory[8+$s1]

ldc1 $f2,8($s1) # ($f2,$f3) = Memory[8+$s1]

ldc1 $f2,8($s1) # ($f2,$f3) Memory[8+$s1]

swc1 $f3,8($s1) # Memory[8+$s1] = $f3

sdc1 $f2,8($s1) # Memory[8+$s1] = ($f2,$f3) Verschieben von Registerinhalten von $f0,...,$f31 am Beispiel:

$f6 $f3 # $f6 $f3 mov.s $f6,$f3 # $f6 = $f3

mov.d $s4,$f6 # ($f4,$f5) = ($f6,$f7)

(40)

Floating‐Point‐Befehle

Die MIPS‐Single‐Precision‐Operationen am Beispiel:

add.s $f1,$f2,$f3 # $f1 = $f2 + $f3 b $f1 $f2 $f3 # $f1 $f2 $f3 sub.s $f1,$f2,$f3 # $f1 = $f2 - $f3 mul.s $f1,$f2,$f3 # $f1 = $f2 * $f3 div s $f1,$f2,$f3 # $f1 = $f2 / $f3 div.s $f1,$f2,$f3 # $f1 $f2 / $f3 Die MIPS‐Double‐Precision‐Operationen am Beispiel:

add.d $f2,$f4,$f6 # ($f2,$f3) = ($f4,$f5) + ($f6,$f7) b d $f2 $f4 $f6 # ($f2 $f3) ($f4 $f5) sub.d $f2,$f4,$f6 # ($f2,$f3) = ($f4,$f5) - ($f6,$f7) mul.d $f2,$f4,$f6 # ($f2,$f3) = ($f4,$f5) mul.d $f2,$f4,$f6 # ($f2,$f3) ($f4,$f5)

* ($f6,$f7) div.d $f2,$f4,$f6 # ($f2,$f3) = ($f4,$f5) / ($f6,$f7)

(41)

Zwischenbilanz der MIPS‐Architektur

CPU Coprocessor 1 (FPU)

Memory

p ( )

$0 .

$f0 . Registers Registers

. . .

$31

. . .

$f31

$ Arithmetic

Unit

Multiply Divide

$

Arithmetic

Unit Divide

Unit

Lo Hi

Neu

(42)

Arithmetische Operationen zusammengefasst

Instruktion Beispiel Bemerkung Instruktion Beispiel Bemerkung mult, div,

madd, msub

mult $s1, $s2 Ergebnis wir in den speziellen Registern lo und hi  abgelegt.

nzzahlig

add , sub add $s1, $s2, $s3 Operieren auf den 32 standard CPU‐Registern addi addi $s1, $s2, 42 Ein Parameter ist eine Konstante

Gan $ , $ ,

mflo, mfhi, mtlo, mthi

mflo $s1 ZumLaden und Speichern der Inhalte von lo‐ und  hi‐Register

l l $ 1 $ 2 $ 3 $ 1 32 L d Bi $ 2 * $ 3

mul mul $s1, $s2, $s3 $s1 = 32 Low‐order Bits von $s2 * $s3 add.s, sub.s, 

mul.s, div.s, 

add.s $f0, $f1, $f2 Instruktionen arbeiten auf den speziellen Registern 

$f0,...,$f31. Single‐Precision.

omma

add.d, sub.d,  mul.d, div.d

add.d $f0, $f1, $f2 Instruktionen arbeiten auf den speziellen Registern  ($f0,$f1),...,($f30,$f31). Double‐Precision.

lwc1 swc1 lwc1 $f0 4($s1) Zum Laden und Speichern der Inhalte von

Gleitko lwc1, swc1,

ldc1, sdc1

lwc1 $f0, 4($s1) Zum Laden und Speichern der Inhalte von 

$f0,...,$f31 über den Speicher.

mfc1, mtc2 mtc1 $s1, $f0 Zum Laden und Speichern der Inhalte von 

$f0 $f31 üb di t d d CPU R i t

$f0,...,$f31 über die standard CPU‐Register.

mov.s, mov.d mov.s $f1, $f2 Verschieben der Inhalte von $f0,...,$f31

(43)

Einfaches Quiz

MIPS‐Assemblercode, um die Eingabe in Single‐Precision aus  Fahrenheit in Celsius umzurechnen:

$f0 = (5.0 / 9.0) * (Eingabe – 32.0)

Ti i b h

Tipp: wir brauchen:

lwc1 zum laden und div.s, sub.s, mul.s

Inhalt (Word)

8 9 0

12 32.0

Adresse

0 Eingabe

4 5.0

8 9.0

A

(44)

Branches und Jumps

(45)

Der Program‐Counter

CPU Coprocessor 1 (FPU)

Memory

p ( )

$0 .

Registers Unsere bisherigen Assemblerprogramme waren rein sequentiell. Beispiel:

0x4000000 : addi $s0, $zero, 4 .

. .

$31

0x4000000 : addi $s0, $zero, 4 0x4000004 : lw $s1, 0($s0)

0x4000008 : lw $s2, 4($s0) 0x400000c : add $s1, $s1, $s1

$ Arithmetic

Unit

Multiply Divide

$ , $ , $ 0x4000010 : ...

Welche nächste Instruktion abgearbeitet

Unit Divide

Lo Hi

PC

werden soll, steht im Program‐Counter. 

Zur Abarbeitung der nächsten Instruktion wird der Program‐Counter von der CPU auf die

nächste Instruktion gesetzt, d.h.  $pc = $pc + 4.

Der Program‐Counter ist ein

(46)

Aus der Sequentiellen Abarbeitung springen

0x40000004 : addi $s1, $s1, 42 0x40000008 : addi $s2, $s2, 24

0x4000100 : addi $s0, $zero, 4 0x4000104 : lw $s1, 0($s0)

0x4000108 : lw $s2, 4($s0) 0x400010c : add $s1, $s1, $s1 ja 0x4000110 : add $s1, $s1, $s2

0x4000114 : addi $s1, $zero, 1 0x4000118 : sw $s1, 0($s0)

Gilt $s1 < $s2? ja i

0x40000204 : mult $s1, $s2 nein

$ 0x40000208 : div $s1, $s2 0x4000020c : mtlo $s1

0x40000210 : mthi $s2

$ $

Program‐Counter $pc

0x40000214 : madd $s1,$s2

(47)

Bedingte Sprünge und unbedingte Sprünge

Start: ...

beq register1 register2 Label3 beq register1, register2, Label3 ...

bne register1, register2, Label1g g ...

j Label2 ...

Label1: ...

Ein Label (oder Sprungmarke zu deutsch)  ist eine mit einem Namen markierte 

Stelle im Code an die man per Branch ...

Label2: ...

...

Stelle im Code, an die man per Branch bzw. Jump hin springen möchte.

Assembler‐Syntax: „Name des Labels“ 

Label3: ...

y

gefolgt von einem „:“.

(48)

Formate für Sprungbefehle

Bedingte Sprünge beq und bne haben das Format I‐Typ (Immediate):

$ $

beq $s1, $s2, Label

4 18 17 Label I‐Typ

4 18 17 Label

Opcode 6 Bit

Source 5 Bit

Dest 5 Bit

Konstante oder Adresse 16 Bit

yp

Unbedingter Sprung hat das Format J‐Typ (Jump‐Format):

j addr # Springe nach Adresse addr

2 addr

Opcode 6 Bit

Adresse 26 Bit

J‐Typ

6 Bit 26 Bit

(49)

Anwendungsbeispiel if‐then‐else

if (i == j) then f = g + h;

f = g + h;

else

f = g - h;g ;

Es sei f,…,j in $s0,…,$s4 gespeichert:

bne $s3,$s4,Else # gehe nach Else wenn i!=j

add $s0,$s1,$s2 # f = g + h (bei i!=j übersprungen) j Exit # gehe nach Exit

Else: sub $s0,$s1,$s2 # f = g – h (bei i==j übersprungen) Exit:

(50)

Anwendungsbeispiel while

while (safe[i] == k) i += 1;

Es sei i und k in $s3 und $s5 gespeichert und die Basis von safe sei $s6: Loop: sll $t1,$s3,2 # Temp-Reg $t1 = i * 4

add $t1,$t1,$s6 # $t1 = Adresse von safe[i]

lw $t0,0($t1) # Temp-Reg $t0 = save[i]

bne $t0,$s5,Exit # gehe nach Exit, wenn save[i]!=k addi $s3,$s3,1 # i = i + 1

#

j Loop # gehe wieder nach Loop Exit:

safe[i]

b0 b1 b2 b3 b4 b5 …

(51)

Test auf Größer und Kleiner?

slt $t0, $s3, $s4 # $t0 = 1 wenn $s3 < $s4 slti $t0, $s2, 10 # $t0 = 1 wenn $s2 < 10

Beispiel: springe nach Exit, wenn $s2 < 42 ...

slti $t0, $s2, 42

bne $t0, $zero, Exit, , ...

Exit:

(52)

Signed und unsigned Vergleiche 

Registerinhalt von $s0 sei:

1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 Registerinhalt von $s1 sei:

0000 0000 0000 0000 0000 0000 0000 0001

W i t d W t $t0 h A füh d f l d Z il

Was ist der Wert von $t0 nach Ausführung der folgenden Zeile:

slt $t0, $s0, $s1 # Signed-Vergleich $s0<$s1

Was ist der Wert von $t1 nach Ausführung der folgenden Zeile:

sltu $t0, $s0, $s1 # Unsigned-Vergleich $s0<$s1

(53)

Beispiel: Test auf 0 <= $s0 < $s1 in einer Code‐Zeile

Umständlicher Test in zwei Zeilen:

slti $t0, $s0, 0 # $t0=1 wenn $s0<0 sonst $t0=0

bne $t0, $zero, OutOfBound # gehe nach OutOfBound wenn $t0!=0 slt $t0, $s0, $s1 # $t0=1 wenn $s0<$s1 sonst $t0=0 beq $t0, $zero, OutOfBound # gehe nach OutOfBound wenn $t0==0 ...

OutOfBound:

Test in einer Zeile wenn $s1 immer größer oder gleich 0 ist?

(54)

Unterstützung von Jump‐Tables

Assembler‐Code:

Label 1: ...

Nr Label Adresse 0 Label 1 0x05342120

Jump‐Table Maschinen‐Code:

0x05342120: 1011010110...

_ ...

0 Label_1 0x05342120 1 Label_2 0x05443004

...

0x05443004: 0001011101

Label_2: ...

...

... ...

n‐2

0x05443004: 0001011101...

...

Label_n: ... n‐1 Label_n 0x06756900

# Gewünschter Label sei in $s0 gespeichert und 0x06756900: 0000111000...

# Gewünschter Label sei in $s0 gespeichert und

# Startadresse der Jump-Table sei in $s1

# Lade Adresse für gewünschtes Label in $t0 sll $t0 $s0 2

sll $t0, $s0, 2 add $t0, $t0, $s1 lw $t0, 0($t0)

# Springe an die in $t0 gespeicherte Adresse

# Springe an die in $t0 gespeicherte Adresse jr $t0

(55)

Floating‐Point und Branches

MIPS‐Floating‐Point‐Instruktionen erlauben Vergleiche der Form:

c.x.s $f2,$f3 # Vergleiche Single $f2 mit $f3 d $f2 $f4 # V l i h D bl $f2 it $f4 c.x.d $f2,$f4 # Vergleiche Double $f2 mit $f4 Hierbei kann x in c.x.s bzw. c.x.d stehen für:

l eq = equal

lt = less than

le = less or equal le = less or equal Beispiele:

c eq s $f2 $f3 # $f2 = $f3 ? c.eq.s $f2,$f3 # $f2 = $f3 ?

c.lt.d $f2,$f4 # ($f2,$f3) < ($f4,$f5)?

c.le.s $f2,$f3 # $f2 <= $f3?$ ,$ $ $

(56)

Und dann findet der Branch wie statt?

Instruktion bc1t und bc1f nach dem Floating‐Point‐Vergleich:

bc1t Label # springe nach Label, wenn der

# i Fl ti P i t V l i h

# vorige Floating-Point-Vergleich

# erfüllt ist

bc1f Label # springe nach Label, wenn der bc1f Label # springe nach Label, wenn der

# vorige Floating-Point-Vergleich

# nicht erfüllt ist

(Bemerkung c1 steht für Coprozessor 1; Erinnerung: die FPU ist dort) B i i l

Beispiel:

c.lt.d $f2,$f4 # ($f2,$f3) < ($f4,$f5)?

bc1t Label # springe nach Label, wenn bc1t Label # springe nach Label, wenn

# ($f2,$f3) < ($f4,$f5) gilt.

...

Label: ...

(57)

Condition‐Flags

CPU Coprocessor 1 (FPU)

Memory

p ( )

$f0 . Registers Die Floating‐Point‐Vergleichsbefehle c.x.sund 

c.x.d setzen Default‐mäßig das Condition‐Flag 0.

. . .

$f31 Die Floating‐Point‐Sprungbefehle bc1tund bc1f

springen, wenn das Flag 0 gesetzt bzw. nicht gesetzt 

i t $

Arithmetic ist.

Alternativ kann man auch die anderen Flags  verwenden Dann gibt man diese mit den

Unit

Condition‐Flags verwenden. Dann gibt man diese mit den 

Instruktionen an. Beispiel:

c eq s 2 $f2 $f3 # Setze Cond -Flag

0 0 0 1 0 0 1 0 0 1 2 3 4 5 6 7 c.eq.s 2 $f2,$f3 # Setze Cond. Flag

# 2, wenn $f2=$f3.

bc1t 2 Lab # springe nach Lab

# wenn Cond.-Flag

# wenn Cond. Flag

(58)

Zusammenfassung der Sprung‐Instruktionen

Instruktion Beispiel Bedeutung des Beispiels Instruktion Beispiel Bedeutung des Beispiels beq, bne beq $s1, $s2, x Springe nach x wenn $s1 = 

$s2

hlig

$s2

j j label Springe immer nach 

label“

Ganzza „label

jr jr $s1 Springe nach in $s1 

gespeicherte Adresse gespeicherte Adresse slt, slti, sltu, sltiu slt $s1,$s2,$s3 $s1=1 wenn $s2<$s3 

(signed) (signed)

Point bc1t, bc1f bc1t label Springe nach „label“ wenn  letzter Floating‐Point‐

oating‐P g

Vergleich true ergab

c.x.s (x=eq, lt, le),  c.eq.s $f1, $f2 Teste auf $f1=$f2 (single

Flo

c.x.d (x=eq, lt, le) precision)

(59)

Quiz

Im folgenden Codeabschnitt soll nach continue gesprungen werden,  wenn $s1 kleiner gleich $s2 ist:

loop: ...p

j loop

j p

continue: ...

Tipp: wir brauchen b lt d b

beq, slt und bne

(60)

Und noch ein Quiz

Annahme:

$s1 = 0xFFFFFFFF

$s2 = 0x00000001

$s2 = 0x00000001

In welchem der beiden Code‐Abschnitte wird gesprungen?g p g

...

slt $t0,$s1,$s2

...

sltu $t0,$s1,$s2 bne $t0,$zero, lab

...

beq $t0,$zero, lab ...

...

lab: ...

...

lab: ...

... ...

Sprung:

ja nein

Sprung:

ja nein

(61)

Prozeduren

(62)

Das Prinzip von Prozeduren

Hauptprogramm: Randbemerkung: was ist n! ?

. . Programm‐

abarbeitung

Prozeduraufruf .

x = 2*fakultät(10) Prozedur mit dem 

Namen fakultät Prozeduraufruf

mit Parameter n=10

. .

Namen fakultät .

. ..

Berechne n!

. . Prozedurrücksprung

mit Ergebnis n!g

(63)

Programmzähler und Rücksprungadresse

Ad M hi i t kti

0x0040000 : 0011 ... 1001 0x0040004 : 0001 ... 1000

Adresse Maschineninstruktion

0x0040008 : 1001 ... 1111 0x004000c : 1011 ... 0001

Startadresse des Hauptprogramms 0x0040010 : 0011 ... 1000

0x0040014 : 1001 ... 1111 0x0040018 : 0001 0001

Aufruf der Prozedur

0x0040018 : 0001 ... 0001 0x004001c : 1011 ... 0011 0x0040020 : 1011 ... 1100 0x0040024 : 0101 ... 1001 0x0040028 : 1000 ... 0011 0x004002c : 1000 1011 Register $pc

Prozedur Fakultät

0x004002c : 1000 ... 1011 0x0040030 : 0001 ... 1100 0x0040034 : 1001 ... 1111

Rücksprung aus der Prozedur

Register $ra

(64)

Assembler‐Beispiel

Hauptprogramm: ...

0x004000c addi $a0,$zero,10 # setze $a0 auf 10 0x0040010 jal Fakultaet # rufe Prozedur auf 0x0040014 sll $v0,2 # Berechne Rückgabe*2

...

Fakultaet:

# Die Prozedur Fakultaet

# Ü $ 0

# erwartet den Übergabeparameter in $a0

# gibt das Ergebnis in $v0 zurück

0x0040024 ... # Berechnung der Fakultät

# D E b i i i $ 0 ... # Das Ergebnis sei in $a0 0x004002c add $v0,$a0,$zero # speichere Ergebnis in $v0 0x0040030 jr $ra

Register $pc Register $ra Register $a0 Register $v0

(65)

Problem

Hauptprogramm:

. Programm‐ .

abarbeitung .

$s0 = 42 vor Aufruf

. abarbeitung

Prozeduraufruf

mit Parameter n=10 .

x = 2*fakultät(10) .

Prozedur mit dem  Namen fakultät

. .

Annahme immer  noch $s0=42 !?!

.

Berechne n!

Überschreibe dabei 

$ 0 it 114 .

.

$s0 mit 114 .

.

P d ü k

Prozedurrücksprung mit Ergebnis n!

Register $s0

(66)

Lösung

Hauptprogramm:

. .

0x7fffffff : ...

0x7ffffffe : ...

Stack .

$s0 = 42 vor Aufruf

.

0x7ffffffd : ...

0x7ffffffc : ...

0x7ffffffb : ...

0 7ffffffa

x = 2*fakultät(10) .

.

Prozedur mit dem  Namen fakultät

Rette Inhalt von $s0 

f d k

0x7ffffffa : ...

0x7ffffff9 : ...

0x7ffffff8 : ...

0x7ffffff7 : ...

Es gilt immer  noch $s0=42 !!!

.

auf dem Stack .

Berechne n!

($ 0 i d d b i

0x7ffffff6 : ...

0x7ffffff5 : ...

0x7ffffff4 : ...

0x7ffffff3 :

. ($s0 wird dabei 

überschrieben) Restauriere Inhalt  von $s0 mittels Stack

0x7ffffff3 : 0x7ffffff2 : 0x7ffffff1 : 0x7ffffff0 :

von $s0 mittels Stack .

Register $s0 .

0x7fffffef : 0x7fffffee : 0x7fffffec :

Register $sp

. .

(67)

Assembler‐Beispiel

Fakultaet: addi $sp, $sp, -4 # erhöhe Stack-Pointer um ein Word sw $s0, 0($sp) # rette $s0 auf Stack

# berechne Fakultät

# $s0 wird dabei überschrieben

lw $s0, 0($sp) # restauriere $s0 vom Stack addi $sp, $sp, 4 # dekrementiere Stack-Pointer jr $ra # Springe zurück zum Aufrufer

...

0x7ffffff7 : ...

0x7ffffff6 : ...

0x7ffffff5 : ...

Register $sp

0x7ffffff5 : ...

0x7ffffff4 : ...

0x7ffffff3 : 0x7ffffff2 : 0x7ffffff1 :

Register $s0 0x7ffffff1 :

0x7ffffff0 : 0x7fffffef : 0x7fffffee : 0x7fffffec :

Register $s0

0x7fffffec :

(68)

Registerkonvention

Name Nummer Verwendung Wird über Aufrufgrenzen bewahrt?

$zero 0 Konstante 0 n.a.

$at 1 nein

$v0‐$v1 2‐3 Prozedur‐Rückgabe nein

$a0‐$a3 4‐7 Prozedur‐Parameter nein

$t0‐$t7 8‐15 Temporäre nein

$t0‐$t7 8‐15 Temporäre nein

$s0‐$s7 16‐23 Temporär gesicherte ja

$t8‐$t9 24‐25 Temporäre nein

$k0‐$k1 26‐27 nein

$gp 28 ja

$sp 29 Stack‐Pointer ja

$fp 30 ja

$ra 31 Return Adresse ja

$ra 31 Return‐Adresse ja

(69)

Rekursive Prozeduren

Hauptprogramm:

Wenn Rekursionsende noch nicht erreicht, dann erneuter Prozeduraufruf

. .

(„mit kleinerem Parameter“)

.

x = 2*fakultät(10) Prozedur mit dem 

Namen fakultät Prozeduraufruf

. .

Namen fakultät .

. ..

Berechne n!

. . Letzter Rücksprung

mit Gesamtergebnis

(70)

Verwendung des Stacks

Stack

Haupt‐ $sp

programm

Fakultät

Fakultät

F k ltät

Fakultät Fakultät

Rekursionsende

(71)

Assembler‐Beispiel

Auf der nächste Folie wollen wir die Fakultät n! nach folgendem  Algorithmus berechnen

Algorithmus berechnen int fact (int n) {( ) {

if (n < 1) { return 1;

}

else {

return n * fact(n-1);

return n * fact(n-1);

} }

}

(72)

Assembler‐Beispiel

# Berechnung der Fakultät von n (also n!)

# Berechnung der Fakultät von n (also n!)

# Eingabeparameter n ist in $a0 gespeichert

# Rückgabeparameter der Berechnung ist $v0

fact:act: addi $sp, $sp, -8 # push Stack-Pointer um zwei Wordadd $sp, $sp, 8 # pus Stac o te u e o d sw $ra, 4($sp) # rette Rücksprungadresse auf Stack sw $a0, 0($sp) # rette Eingabeparameter auf Stack slti $t0, $a0, 1 # teste n < 1

beq $t0, $zero, L1 # wenn n >= 1 dann gehe nach L1 addi $v0, $zero, 1 # es wird 1 zurückgegeben

addi $sp, $sp, 8 # pop Stack-Pointer um zwei Word jr $ra # Rücksprung zum Prozedur-Aufrufer L1: addi $a0, $a0, -1 # setze Argument auf n-1

jal fact # rufe fact rekursiv mit n-1 auf

lw $a0, 0($sp) # restauriere Eingabeparam vom Stack lw $ra, 4($sp) # restauriere Rücksprungadr vom Stack addi $sp $sp 8 # pop Stack Pointer m ei Word

addi $sp, $sp, 8 # pop Stack-Pointer um zwei Word

mul $v0, $a0, $v0 # es wird n * fact(n-1) zurück gegeben jr $ra

(73)

Procedure‐Frame und Frame‐Pointer

Benutzer

Hohe Adresse Benutzer

Stack‐Speicher Argument 6

Null bis vier Argument‐

Register ($a0‐$a3)

Frame‐Pointer $fp Argument 5

Register ($a0 $a3) Return‐Adresse $ra Null bis acht Saved‐

Register ($s0‐$s7) Möglicher zusätzlicher 

Speicher der während  Procedure‐Frame

der Ausführung der  Prozedur  benötigt 

wird und nach  Prozedurrückkehr nicht 

mehr

Niedrige Adresse Stack‐Pointer $sp

Unbenutzer Unbenutzer

(74)

Speicherbelegungskonvention

Stack 0x7ffffffc

$sp

Der Heap speichert alle p p dynamischen (d.h. 

während der Laufzeit  angelegten) Daten.

0x10008000 Heap

$gp

Statische Daten (z.B. 

Konstanten oder  statische Variablen) 0x10000000

Text (d.h. das Programm  in Form von Maschinen‐

instruktionen) 0x00400000

0x10000000

$pc

Reserviert instruktionen) 0x00400000

0 00000000

$pc

0x00000000

(75)

Die Sprunginstruktionen zusammengefasst

Instruktion Beispiel Beduetung

j j Label $pc = Sprungadresse

jal jal Label $ra = $pc+4, $pc = Sprungadresse

j j p , p p g

jr jr $s1 $pc = Registerinhalt

$pc ist der Program‐Counter

$ra ist das 32te CPU‐Register

$ra ist das 32te CPU Register 

(76)

Schwieriges Quiz

Rekursive Berechnung von n*m in der Form Rmul(n m) = n+Rmul(n m‐1) Rekursive Berechnung von n m in der Form Rmul(n,m)   n+Rmul(n,m 1) Eingabeparameter: $a0 für n und $a1 für m>0

Rückgabeparameter: $v0

$a0, $a1, $v0, $t0 brauchen  nach Registerkonvention alle  nicht über Aufrufgrenzen Rmul: addi $sp, $sp, -4 # rette Rücksprungadresse

sw $ra 0($sp) #

Temporäre Berechnung: $t0 nicht über Aufrufgrenzen  bewahrt zu werden.

sw $ra, 0($sp) #

add $t0, $a0, $zero # $t0 = n

ddi $ 1 $ 1 1 # 1

addi $a1, $a1, -1 # m = m - 1

beq $a1, $zero, End # wenn m=0, dann Ende jal Rmul # $v0 = Rmul(n,m-1) add $t0, $t0, $v0 # $t0 = $t0 + $v0 End: add $v0, $t0, $zero # $v0 = $t0

lw $ra, 0($sp) # springe zurück addi $sp, $sp, 4 #

addi $sp, $sp, 4 #

jr $ra #

(77)

R i t k ti d i R i t üb A f f i ht

Bemerkung zu vorigem Quiz

Registerkonvention, dass ein Register über Aufrufgrenzen nicht  bewahrt wird bedeutet:

R i d f h b li b üb h ib d

• Register darf nach belieben überschreiben werden.

• Register muss vor dem Rücksprung nicht restauriert werden.

• Prozedur muss aber das Register für sich selbst sichern!Prozedur muss aber das Register für sich selbst sichern!

• Beispiel:

Verwendung von $t0 Sichern von $t0

Aufruf einer anderen Prozedur

R t i $t0

Restaurieren von $t0

•Ausnahme: wir wissen genau, dass das Register in keiner der aufgerufenen Prozeduren verwendet wird

aufgerufenen Prozeduren verwendet wird.

• Prozeduren, die keine anderen aufruft muss natürlich temporäre Register nie sichern.

(78)

32‐Bit‐Konstanten und Adressierung

Referenzen

ÄHNLICHE DOKUMENTE

Das diesem Dokument zugrundeliegende Vorhaben wurde mit Mitteln des Bundesministeriums für Bildung und Forschung.. unter dem Förderkennzeichen

© Copyright: Department for Northern European Studies Berlin and authors.. Die Geschichte eines

addi rt, rs, imm Register rt = Register rs + Konstante imm sub rd, rs, rt Register rd = Register rs

sllv rd, rt, rs Register rd = Register rs logisch links um den in Register rs gespeicherten Wert  geshiftet.. srl rd, rs, shamt Register rd = Register rs

addi rt, rs, imm Register rt = Register rs + Konstante imm sub rd, rs, rt Register rd = Register rs

addi rt, rs, imm Register rt = Register rs + Konstante imm sub rd, rs, rt Register rd = Register rs

sllv rd, rt, rs Register rd = Register rs logisch links um den in Register rs gespeicherten Wert  geshiftet.. srl rd, rs, shamt Register rd = Register rs

These included compile-time and link-time schemes for allocating 52 registers, and register window schemes using 128 registers organized into fixed-size or variable-sized