Addieren und Laden von Konstanten
C Programm:
x = x + 4;
Sei hierbei:
x in Register $s3 gespeichert
MIPS Instruktion:
MIPS erlaubt negative Konstanten und braucht damit kein ‚subi‘.
MIPS hat ein spezielles Register $zero, welches 0 ‘hart verdrahtet‘ speichert.
C Programm:
x = 42;
Sei hierbei:
x in Register $s3 gespeichert
MIPS Instruktion:
Zwischenbilanz der MIPS Architektur
Grundlagen der Rechnerarchitektur ‐Assembler 18
CPU
$0 . . .
$31 Arithmetic
Unit
Registers
Memory
Name Nummer Verwendung
$zero 0 Konstante 0
$at 1
$v0‐$v1 2‐3
$a0‐$a3 4‐7
$t0‐$t7 8‐15 Temporäre Register
$s0‐$s7 16‐23 „saved“ temporäre Reg.
$t8‐$t9 24‐25 Temporäre Register
$k0‐$k1 26‐27
$gp 28
$sp 29
$fp 30
$ra 31
Zusammenfassung der behandelten Instruktionen
Instruktion Bedeutung
Arithmetik add rd, rs, rt Register rd = Register rs + Register rt
addi rt, rs, imm Register rt = Register rs + Konstante imm sub rd, rs, rt Register rd = Register rs –Register rt
Laden
lb rt, address Lade Byte an der Adresse address in Register rt.
Das Byte ist sign‐extended.
lbu rt, address Lade Byte an der Adresse address in Register rt.
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.
lw rt, address Lade Word an der Adresse address in Register rt.
Speichern
sb rt, address Speichere unterstes Byte des Registers rt an Adresse address sh rt, address Speichere unteres Half‐Word des Registers rt an Adresse
address
sw rt, address Speichere Inhalt des Registers rt an Adresse address.
Quiz
Grundlagen der Rechnerarchitektur ‐Assembler 20
addi $s0, $zero, 4 # lw $s1, 0($s0) # lw $s2, 4($s0) # add $s1, $s1, $s1 # add $s1, $s1, $s2 # addi $s1, $s1, 1 # sw $s1, 0($s0) #
0 421
4 12
8 4
12 33
…
Adresse
Inhalt (Word)
Speicher zu Beginn
0 4 8 12
…
Adresse
Inhalt (Word)
Speicher nach Instruktionsdurchlauf
Darstellung von Instruktionen
Übersetzung aus Assembler in Maschinensprache
Grundlagen der Rechnerarchitektur ‐Assembler 22
add $t0, $s1, $s2
0 17 18 8 0 32
6 Bit Opcode
5 Bit Source1
5 Bit Source2
5 Bit Dest
5 Bit Shamt
6 Bit Funct
00000010001100100100000000100000
Assembler‐
Instruktion
Maschinen‐
Instruktion
Name Nr
$t0 8
$t1 9
$t2 10
$t3 11
$t4 12
$t5 13
$t6 14
$t7 15 Name Nr
$s0 16
$s1 17
$s2 18
$s3 19
$s4 20
$s5 21
$s6 22
$s7 23
Notwendigkeit für andere Instruktionsformate
op rs rt rd shamt funct
6 Bit 5 Bit 5 Bit 5 Bit 5 Bit 6 Bit
add $t0, $s1, $s2
lw $t0, 32($s3)
?
R‐Typ
Opcode 6 Bit
Source 5 Bit
Dest 5 Bit
Konstante oder Adresse 16 Bit
I‐Typ
Zwischenbilanz
Grundlagen der Rechnerarchitektur ‐Assembler 24
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
sw (store word) I 43 reg reg offset
6 Bit 5 Bit 5 Bit 5 Bit 5 Bit 6 Bit
16 Bit
Beispiel: A[300] = h + A[300]
$t1 sei Basisadresse von A und h in $s2 gespeichert. Assembler‐Code?
Maschinen‐Code (der Einfachheit halber mit Dezimalzahlen)?
op rs rt rd adr/shamt funct Name Nr
$t0 8
$t1 9
$t2 10
$t3 11
$t4 12
$t5 13
$t6 14
$t7 15 Name Nr
$s0 16
$s1 17
$s2 18
$s3 19
$s4 20
$s5 21
$s6 22
$s7 23
Instruktion Format op rs rt rd shamt funct
add R 0 reg reg reg 0 32
lw (load word) I 35 reg reg offset
sw (store word) I 43 reg reg offset
Logische Operationen
Grundlagen der Rechnerarchitektur ‐Assembler 26
Erinnerung: Logischer Shift. Beispiel:
Logischer Links‐ und Rechts‐Shift
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 Opcode
5 Bit Source1
5 Bit Source2
5 Bit Dest
5 Bit Shamt
5 Bit Funct
Erinnerung: Arithmetischer Rechts‐Shift. Beispiel mit 8‐Bit:
0011 0000 1101 0111
Arithmetischer Rechts‐Shift
Grundlagen der Rechnerarchitektur ‐Assembler 28
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 geshiftet
Erinnerung: AND.
AND, OR, NOR und XOR
MIPS‐Instruktionen (R‐Typ), Beispiel:
and $t0,$t1,$t2 # $t0 = $t1 AND $t2 or $t0,$t1,$t2 # $t0 = $t1 OR $t2 nor $t0,$t1,$t2 # $t0 = $t1 NOR $t2 xor $t0,$t1,$t2 # $t0 = $t1 XOR $t2 MIPS‐Instruktionen (I‐Typ), Beispiel:
andi $t0,$t1,0111 # $t0 = $t1 AND 0111 ori $t0,$t1,1100 # $t0 = $t1 OR 1100 xori $t0,$t1,1100 # $t0 = $t1 XOR 1100
Erinnerung: OR. Erinnerung NOR. Erinnerung XOR.
Es gibt gar kein NOT?!
Grundlagen der Rechnerarchitektur ‐Assembler 30
Erinnerung NOT (auf Folie zu Zweierkomplement kurz eingeführt):
Beobachtung:
Wie kann man also „NOT($t0)“ in MIPS realisieren?
Zusammenfassung der behandelten Instruktionen
Instruktion Bedeutung
Shift
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 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 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.
Logische Verknüpfung
andrd, rs, rt Register rd = Register rs AND Register rt.
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.
andirt, rs, imm Register rt = Register rs AND Konstante imm ori rt, rs, imm Register rt = Register rs AND Konstante imm xori rt, rs, imm Register rt = Register rs AND Konstante imm
MIPS‐Assemblercode um folgende Funktion zu berechnen:
$s1 = die ersten 8 Bits von 4 * NOT($s1 AND $s2)
Schwieriges Quiz
Grundlagen der Rechnerarchitektur ‐Assembler 32
Tipp: wir brauchen and, nor und sll
Weitere Arithmetik
Die speziellen Register lo und hi
Grundlagen der Rechnerarchitektur ‐Assembler 34
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 64 Bit, um das Ergebnis abzuspeichern.
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
Ganzzahlige Multiplikation und Division
Ganzzahlige Multiplikation. Beispiel:
mult $s1, $s2 # (hi,lo) = $s1 * $s2
Ganzzahlige Division. Beispiel:
div $s1, $s2 # berechnet $s2 / $s1
# lo speichert den Quotienten
# hi speichert den Rest
Register hi und lo können auch beschrieben werden. Beispiel:
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 msub $s1,$s2 # (hi,lo)=(hi,lo)-$s1*$s2
Ganzzahlige Multiplikation ohne hi und lo
Grundlagen der Rechnerarchitektur ‐Assembler 36
Es gibt eine weitere Instruktion, zur Multiplikation, die kein hi und lo verwendet:
mul $s1, $s2, $s3 # $s1 = die low-order 32
# Bits des Produkts von
# $s2 und $s3.
Zwischenbilanz der MIPS‐Architektur
CPU
$0 . . .
$31 Arithmetic
Unit
Multiply Divide Registers
Lo Hi
Memory
Neu
Die speziellen Register $f01 bis $f31
Grundlagen der Rechnerarchitektur ‐Assembler 38
MIPS unterstützt mit einem separaten FPU‐Coprozessor
Gleitkommaarithmetik auf Zahlen im IEEE 754‐Single‐Precision (32‐
Bit) und Double‐Precision‐Format (64 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 werden (also $f0, $f1, ..., $f31).
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).
Floating‐Point‐Befehle
Laden/speichern von Daten in die Register $f0,...,$f31 am Beispiel:
mtc1 $s1,$f3 # $f3 = $s1 mfc1 $s1,$f3 # $s1 = $f3
lwc1 $f3,8($s1) # $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:
mov.s $f6,$f3 # $f6 = $f3
mov.d $s4,$f6 # ($f4,$f5) = ($f6,$f7)
Floating‐Point‐Befehle
Grundlagen der Rechnerarchitektur ‐Assembler 40
Die MIPS‐Single‐Precision‐Operationen am Beispiel:
add.s $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
Die MIPS‐Double‐Precision‐Operationen am Beispiel:
add.d $f2,$f4,$f6 # ($f2,$f3) = ($f4,$f5) + ($f6,$f7) sub.d $f2,$f4,$f6 # ($f2,$f3) = ($f4,$f5) - ($f6,$f7) mul.d $f2,$f4,$f6 # ($f2,$f3) = ($f4,$f5)
* ($f6,$f7) div.d $f2,$f4,$f6 # ($f2,$f3) = ($f4,$f5) / ($f6,$f7)
Zwischenbilanz der MIPS‐Architektur
CPU Coprocessor 1 (FPU)
$0 . . .
$31 Arithmetic
Unit
Multiply Divide
$f0 . . .
$f31
Arithmetic Unit Registers Registers
Lo Hi
Memory
Neu
Arithmetische Operationen zusammengefasst
Grundlagen der Rechnerarchitektur ‐Assembler 42
Instruktion Beispiel Bemerkung
Ganzzahlig
mult, div, madd, msub
mult $s1, $s2 Ergebnis wird in den speziellen Registern lo und hi abgelegt.
add , sub add $s1, $s2, $s3 Operieren auf den 32 standard CPU‐Registern addi addi $s1, $s2, 42 Ein Parameter ist eine Konstante
mflo, mfhi, mtlo, mthi
mflo $s1 ZumLaden und Speichern der Inhalte von lo‐ und hi‐Register
mul mul $s1, $s2, $s3 $s1 = 32 Low‐order Bits von $s2 * $s3
Gleitkomma
add.s, sub.s, mul.s, div.s,
add.s $f0, $f1, $f2 Instruktionen arbeiten auf den speziellen Registern
$f0,...,$f31. Single‐Precision.
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, 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 über die standard CPU‐Register.
mov.s, mov.d mov.s $f1, $f2 Verschieben der Inhalte von $f0,...,$f31
Einfaches Quiz
MIPS‐Assemblercode, um die Eingabe in Single‐Precision aus Fahrenheit in Celsius umzurechnen:
$f0 = (5.0 / 9.0) * (Eingabe – 32.0)
0 Eingabe
4 5.0
8 9.0
12 32.0
…
Adresse
Inhalt (Word)
Speicher
Tipp: wir brauchen:
lwc1 zum laden und div.s, sub.s, mul.s
Branches und Jumps
Grundlagen der Rechnerarchitektur ‐Assembler 44
Der Program‐Counter
CPU Coprocessor 1 (FPU)
$0 . . .
$31 Arithmetic
Unit
Multiply Divide Registers
Lo Hi
Memory
PC
Unsere bisherigen Assemblerprogramme waren rein sequentiell. Beispiel:
0x4000000 : addi $s0, $zero, 4 0x4000004 : lw $s1, 0($s0)
0x4000008 : lw $s2, 4($s0) 0x400000c : add $s1, $s1, $s1 0x4000010 : ...
Welche nächste Instruktion abgearbeitet 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.
Zur Abarbeitung einer Instruktion zeigt der $pc schon auf die nachfolgende Instruktion.
Der Program‐Counter ist ein weiteres Register, genannt $pc.
Aus der Sequentiellen Abarbeitung springen
Grundlagen der Rechnerarchitektur ‐Assembler 46
0x4000100 : addi $s0, $zero, 4 0x4000104 : lw $s1, 0($s0)
0x4000108 : lw $s2, 4($s0) 0x400010c : add $s1, $s1, $s1 0x4000110 : add $s1, $s1, $s2 0x4000114 : addi $s1, $zero, 1 0x4000118 : sw $s1, 0($s0)
0x40000204 : mult $s1, $s2 0x40000208 : div $s1, $s2 0x4000020c : mtlo $s1
0x40000210 : mthi $s2
0x40000214 : madd $s1,$s2 Gilt $s1 < $s2? ja
nein
Program‐Counter $pc
0x40000004 : addi $s1, $s1, 42 0x40000008 : addi $s2, $s2, 24
Start: ...
beq register1, register2, Label3 ...
bne register1, register2, Label1 ...
j Label2 ...
Label1: ...
...
Label2: ...
...
Label3: ...
Bedingte Sprünge und unbedingte Sprünge
Ein Label (oder Sprungmarke zu deutsch) ist eine mit einem Namen markierte
Stelle im Code, an die man per Branch bzw. Jump hin springen möchte.
Assembler‐Syntax: „Name des Labels“
gefolgt von einem „:“.