Μαθηματικά Γ΄. Επανάληψη 6ης ενότητας: ΄΄ Εισαγωγή στους δεκαδικούς αριθμούς, κεφ. 33-38΄΄
ΠΛΕ$027(Μικροεπεξεργαστέςple027/03_assembly.pdfαριθμό!πράξης!(operaon!code!...
-
Upload
phungnguyet -
Category
Documents
-
view
218 -
download
2
Transcript of ΠΛΕ$027(Μικροεπεξεργαστέςple027/03_assembly.pdfαριθμό!πράξης!(operaon!code!...
ΠΛΕ-‐027 Μικροεπεξεργαστές 3ο μάθημα: γλώσσα μηχανής MIPS, προγραμματισμός assembly
Αρης Ευθυμίου
Πηγές διαφανειών: συνοδευτικές διαφάνειες αγγλικης εκδοσης του βιβλιου
Stored Program Computers
Αναπαράσταση εντολών ως δυαδικοί αριθμοί, όπως τα δεδομένα
Εντολές και δεδομένα αποθηκεύονται στη μνήμη – Τα προγράμματα αλλάζουν εύκολα όπως
και τα δεδομένα
Προγράμματα μπορούν να επεξεργάζονται προγράμματα – e.g., compilers, linkers, …
ΠΛΕ 027 Μικροεπεξεργαστές 2011-‐2012 45
Aναπαράσταση εντολών
Εντολές MIPS – Κωδικοποιούνται ως 32-‐bit λέξεις – Μικρός αριθμός από μορφότυπα κωδικοποιούν αριθμό πράξης (operajon code -‐ opcode), αριθμούς καταχωρητών, …
Αριθμοί καταχωρητών – $t0 – $t7 κωδικοποιούνται 8 – 15 – $t8 – $t9 κωδικοποιούνται 24 – 25 – $s0 – $s7 κωδικοποιούνται 16 – 23 – ...
ΠΛΕ 027 Μικροεπεξεργαστές 2011-‐2012 46
Μορφότυπο εντολών R
Πεδία: – op: κωδικός πράξης (opcode) – rs: πρώτος καταχωρητής πηγής (source) – rt: δεύτερος καταχωρητής πηγής – rd: καταχωρητής προορισμού/αποτελέσματος (desjnajon) – shamt: ποσότητα ολίσθησης -‐ για εντολές shiv μόνο, αλλιώς 000002 – funct:επέκταση κωδικού πράξης (funcjon code)
– Οι εντολές ολίσθησης δεν χρησιμοποιούν το πεδίο rs
op rs rt rd shamt funct
6 bits 6 bits 5 bits 5 bits 5 bits 5 bits
ΠΛΕ 027 Μικροεπεξεργαστές 2011-‐2012 47
R-‐format, παράδειγμα
add $t0, $s1, $s2
special $s1 $s2 $t0 0 add
0 17 18 8 0 32
000000 10001 10010 01000 00000 100000
000000100011001001000000001000002 = 0232402016
op rs rt rd shamt funct
6 bits 6 bits 5 bits 5 bits 5 bits 5 bits
ΠΛΕ 027 Μικροεπεξεργαστές 2011-‐2012 48
Μορφότυπο εντολών I
Αριθμητικές πράξεις με σταθερά, εντολές load/store, διακλαδώσεις (υπό συνθήκη) – rs: πρώτος καταχωρητής πηγής – rt: καταχωρητής προορισμού για load, αριθμητικές πράξεις, 2ος καταχωρητής πηγής για store
– Σταθερά με πρόσημο: –215 to +215 – 1 – Διεύθυνση: offset (απόκλιση;) προστίθεται στην διευθυνση βάσης που περιέχει ο καταχωρητής rs
op rs rt constant or address
6 bits 5 bits 5 bits 16 bits
ΠΛΕ 027 Μικροεπεξεργαστές 2011-‐2012 49
Διευθυνσιοδότηση διακλαδώσεων Οι διακλαδώσεις χρησιμοποιούν το μορφότυπο Ι
– Opcode, δύο καταχωρητές, δεύθυνση στόχου διακλάδωσης Οι περισσότεροι στόχοι δεν απέχουν πολύ
– Μπροστά ή πίσω (επαναλλήψεις)
Η διεύθυνση δίνεται (υπολογίζεται) σχετικά με το PC PC-‐relajve addressing
Target address = PC + 4 + offset offset = address * 4, αφού όλες οι εντολές είναι ευθυγραμισμένες
Το PC έχει ήδη αυξηθεί κατά 4
λεπτομέρεια υλοποίησης που περνάει στην αρχιτεκτονική
Πλεονέκτημα;
ΠΛΕ 027 Μικροεπεξεργαστές 2011-‐2012 50
Μορφότυπο J
Διευθυνσιοδότηση αλμάτων Οι στόχοι αλμάτων (j and jal) μπορούν να είναι
οπουδήποτε στο τμήμα κώδικα (text segment) – Η πλήρης διεύθυνση κωδικοποιείται στην εντολή
op address
6 bits 26 bits
Ψεύτο-‐απευθείας διεύθυνση ((Pseudo)Direct addressing) Στόχος = PC31…28 : (address × 4)
ΠΛΕ 027 Μικροεπεξεργαστές 2011-‐2012 51
Παράδειγμα στόχων διακλαδώσεων Βρόγχος από προηγούμενο παράδειγμα: while (save[i] == k) i += 1;
– Εστω ότι ξεκινάει από τη θέση 80000
Loop: sll $t1, $s3, 2 80000 0 0 19 9 2 0
add $t1, $t1, $s6 80004 0 9 22 9 0 32
lw $t0, 0($t1) 80008 35 9 8 0
bne $t0, $s5, Exit 80012 5 8 21 2
addi $s3, $s3, 1 80016 8 19 19 1
j Loop 80020 2 20000
Exit: … 80024
ΠΛΕ 027 Μικροεπεξεργαστές 2011-‐2012 52
Μακρινή διακλάδωση
Αν ο στόχος διακλάδωσης είναι πολύ μακριά για να κωδικοποιηθεί σε 16-‐bit απόκλιση, ο assembler μετατρέπει τον κώδικα
Παράδειγμα beq $s0,$s1, L1
↓
bne $s0,$s1, L2 j L1
L2: …
ΠΛΕ 027 Μικροεπεξεργαστές 2011-‐2012 53
Περίληψη τρόπων διευθυνσιοδότησης
ΠΛΕ 027 Μικροεπεξεργαστές 2011-‐2012 54
addressing mode
Αντιγραφή string στη C
Copy x[] to y[] char *p, *q; p = &x[0]; /* p = x */
/* set p to address of 1st char of x */ q = &y[0]; /* q = y also OK */
/* set q to address of 1st char of y */
while((*q++ = *p++) != ‘\0’) ; Σωστό ή λάθος;
ΠΛΕ 027 Μικροεπεξεργαστές 2011-‐2012 55
Αντιγραφή String σε MIPS Διευθύνσεις των x και y στη μνήμη
p, q στους καταχωρητές: $s1, $s2 lw $t1, Base Address (e.g., BA) lw $s1,0($t1) # $s1 = p lw $s2,4($t1) # $s2 = q Loop: lb $t2,0($s1) # $t2 = *p sb $t2,0($s2) # *q = $t2 addi $s1,$s1,1 # p = p + 1 addi $s2,$s2,1 # q = q + 1 beq $t2,$zero,Exit # if *p == 0, Exit j Loop # go to Loop Exit: # N characters => N*6 + 3 instrucjons
ΠΛΕ 027 Μικροεπεξεργαστές 2011-‐2012 56
Πίνακες και δείκτες Χρήση πίνακα απαιτεί
– Υπολογισμός απόστασης (offset): πολλαπλασιασμός με το μέγεθος στοιχείου
– Πρόσθεση στη διεύθυνση βάσης του πίνακα Δείκτες αντιστοιχούν κατευθείαν στις διευθύνσεις μνήμης
– Μπορούν να αποφύγουν τους περισσότερους υπολογισμούς
Παράδειγμα: μηδενισμός πίνακα
clear1(int array[], int size) { int i; for (i = 0; i < size; i += 1) array[i] = 0; }
clear2(int *array, int size) { int *p; for (p = &array[0]; p < &array[size]; p = p + 1) *p = 0; }
move $t0,$zero # i = 0
loop1: sll $t1,$t0,2 # $t1 = i * 4
add $t2,$a0,$t1 # $t2 =
# &array[i]
sw $zero, 0($t2) # array[i] = 0
addi $t0,$t0,1 # i = i + 1
slt $t3,$t0,$a1 # $t3 =
# (i < size)
bne $t3,$zero,loop1 # if (…) # goto loop1
move $t0,$a0 # p = & array[0]
sll $t1,$a1,2 # $t1 = size * 4
add $t2,$a0,$t1 # $t2 =
# &array[size]
loop2: sw $zero,0($t0) # Memory[p] = 0
addi $t0,$t0,4 # p = p + 4
slt $t3,$t0,$t2 # $t3 =
#(p<&array[size])
bne $t3,$zero,loop2 # if (…)
# goto loop2
Σύγκριση πίνακα -‐ δείκτη
Ο πολλαπλασιασμός μετατρέπεται (“strength reduced”) σε ολίσθηση
Ο κώδικας με πίνακα χρειάζεται την ολίσθηση μέσα στο βρόγχο – αντίθετα, ο δείκτης απλά αυξάνεται
Ο μεταφραστής μπορεί να κάνει την μετατροπή – Καλύτερα το πρόγραμμα να είναι εύκολο στην κατανόηση και
ασφαλές
Υπορουτίνες
Οι υπορουτίνες είναι η βάση της εφαρμογής της ιδέας της αφαιρετικότητας στο λογισμικό
Οι επεξεργαστές (και οι μεταφραστές, ...) συνεργάζονται για να γίνονται οι κλήσεις και οι επιστροφές πιο γρήγορα – και το πέρασμα παραμέτρων και επιστροφή τιμών
ΠΛΕ 027 Μικροεπεξεργαστές 2011-‐2012 60
Κλήση υπορουτινας: 6 βήματα
1. Τοποθέτηση παραμέτρων σε θέση προσπελάσιμη από την υπορουτίνα
2. Μεταφορά ελέγχου εκτέλεσης στην υπορουτίνα 3. Απόκτηση αποθηκευτικού χώρου για ότι χρειάζεται η
υπορουτίνα
4. Εκτέλεση εργασίας της υπορουτίνας 5. Τοποθέτηση αποτελέσματος σε θέση προσπελάσιμη από το
πρόγραμμα που κάλεσε την υπορουτίνα και αποκατάσταση καταχωρητών που χρησιμοποιήθηκαν
6. Επιστροφή στη κατάλληλη εντολή (μια υπορουτίνα μπορεί να κληθεί από πολλά σημεία του προγράμματος)
ΠΛΕ 027 Μικροεπεξεργαστές 2011-‐2012 61
Συμβάσεις κλήσης υπορουτίνας MIPS
Χρησιμοποίησε καταχωρητές όσο γίνεται περισσότερο – είναι πολύ ταχύτερο από προσπέλαση μνήμης
Σύμβαση (convenjon) χρήσης καταχωρητών: $a0–$a3: 4 καταχωρητές για μεταφορά παραμέτρων
(argument)
$v0–$v1: 2 καταχωρητές για επιστροφή τιμών (value) $ra: καταχωρητής διεύθυνσης επιστροφής (return
address) – jal sub κλήση υπορουτίνας – jr $ra επιστροφή
Αποκατάσταση τιμών καταχωρητών
Χρειάζεται μια κατάληλη δομή μνήμης για να κρατάει προηγούμενες τιμές καταχωρητών ώστε να μπορούμε να τις επαναφέρουμε στην επιστροφή – και να διαγράφουμε τις τιμές (τοπικές μεταβλητές – automajc)
Χρησιμοποιούμε τη δομή στοίβας (stack: last-‐in-‐first-‐out queue) – Push: βάλε τα δεδομένα στη στοίβα – Pop: αφαίρεσε τα δεδομένα από τη στοίβα
Η στοίβα είναι στη μνήμη. Γιατί; Χρειάζεται ένας δείκτης:
– $sp (stack pointer) Η σύμβαση στο MIPS είναι ότι η στοίβα μεγαλώνει από
μεγάλες προς μικρές διευθύνσεις – Push μειώνει $sp, Pop αυξάνει $sp
Παράδειγμα τελικής υπορουτίνας
Τελικές υπορουτίνες (leaf φύλλα) – δεν καλούν άλλες υπορουτίνες – αυτό ισχύει και για υπορουτίνες βιβλιοθηκών (π.χ. prin�) – ούτε είναι αναδρομικές
C κώδικας: int leaf_example (int g, h, i, j) { int f; f = (g + h) - (i + j); return f; } – παράμετροι g, …, j στους καταχωρητές $a0, …, $a3 – f στον $s0 (πρέπει να σώσουμε το $s0 στη στοίβα) – Αποτέλεσμα στο $v0
Παράδειγμα σε MIPS κώδικας MIPS:
leaf_example: addi $sp, $sp, -4 sw $s0, 0($sp) add $t0, $a0, $a1 add $t1, $a2, $a3 sub $s0, $t0, $t1 add $v0, $s0, $zero lw $s0, 0($sp) addi $sp, $sp, 4 jr $ra
Save $s0 on stack
Procedure body
Restore $s0
Result
Return
Μη τελικές υπορουτίνες
Οι περισσότερες υπορουτίνες καλούν άλλες Αν ακολουθούσαμε τα παραπάνω η διεύθυνση
επιστροφής και οι παράμετροι της καλούσας (caller) υπορουτίνας θα χανόταν
Πρέπει λοιπόν να σώσουμε στη στοίβα: – Τη διεύθυνση επιστροφής ($ra) – Ο,τι παραμέτρους ή προσωρινούς καταχωρητές ($t) θα
χρειαστούν αργότερα
και να τις επαναφέρουμε μετά την επιστροφή Γιατί χαλάσαμε την ομοιομορφία;
– είναι λογισμικό, δεν έχει τόση σημασία η ομοιομορφία! – είναι πιο γρήγορες οι κλήσεις/επιστροφές
Παράδειγμα μή-‐τελικής ρουτίνας
Κώδικας C (παραγοντικό – factorial): int fact (int n) { if (n < 1) return f; else return n * fact(n - 1); } – Παράμετρος n στο καταχωρητή $a0 – Αποτέλεσμα στο $v0
Παράδειμα, ΜIPS MIPS code: fact: addi $sp, $sp, -8 # adjust stack for 2 items sw $ra, 4($sp) # save return address sw $a0, 0($sp) # save argument slti $t0, $a0, 1 # test for n < 1 beq $t0, $zero, L1 addi $v0, $zero, 1 # if so, result is 1 addi $sp, $sp, 8 # pop 2 items from stack jr $ra # and return L1: addi $a0, $a0, -1 # else decrement n jal fact # recursive call lw $a0, 0($sp) # restore original n lw $ra, 4($sp) # and return address addi $sp, $sp, 8 # pop 2 items from stack mul $v0, $a0, $v0 # multiply to get result jr $ra # and return
Τοπικά δεδομένα στη στοίβα
Κατανομή χώρου για τοπικά δεδομένα γίνεται από την καλούμενη υποροτίνα (callee) – π.χ., «αυτόματες» (τοπικές εκτός από stajc) μεταβλητές C
Πλάισιο υπορουτίνας (frame / acjvajon record) – Χρησιμοποιείται από μερικούς μεταφραστές
Σύμβαση χρήσης καταχωρητών
$a0 – $a3: παράμετροι (reg’s 4 – 7) $v0, $v1: επιστροφή τιμών (reg’s 2 and 3) $t0 – $t9: προσωρινές μεταβλητές
– Δεν διατηρούνται από την καλούμενη υπορουτίνα $s0 – $s7: διατηρούμενες μεταβλητές (saved)
– Πρέπει να αποθηκεύονται/επαναφέρονται από την καλούμενη υπορουτίνα
$gp: δείκτης καθολικών δεοδομένων (reg 28) $sp: stack pointer (reg 29) $fp: frame pointer (reg 30) $ra: return address (reg 31)
Διάταξη μνήμης Text: κώδικας Stajc data: καθολικές μεταβλητές – συμπ. stajc στη C – Ο $gp αρχικοποιείται στη μέση του χώρου και με ±offsets γίνεται προσπέλαση
Dynamic data: σωρός – malloc in C, new in Java
Stack: automajc storage
Παράδειγμα: ταξινόμηση σε C Ταξινόμηση bubble sort σε C Swap procedure (leaf)
void swap(int v[], int k) { int temp; temp = v[k]; v[k] = v[k+1]; v[k+1] = temp; }
– v in $a0, k in $a1, temp in $t0
The Procedure Swap swap: sll $t1, $a1, 2 # $t1 = k * 4
add $t1, $a0, $t1 # $t1 = v+(k*4)
# (address of v[k])
lw $t0, 0($t1) # $t0 (temp) = v[k]
lw $t2, 4($t1) # $t2 = v[k+1]
sw $t2, 0($t1) # v[k] = $t2 (v[k+1])
sw $t0, 4($t1) # v[k+1] = $t0 (temp)
jr $ra # return to calling routine
The Sort Procedure in C
Μή-‐τελική (καλεί τη swap) void sort (int v[], int n) { int i, j; for (i = 0; i < n; i += 1) { for (j = i – 1; j >= 0 && v[j] > v[j + 1]; j -= 1) { swap(v,j); } } } – v: $a0, k: $a1, i: $s0, j: $s1
Κορμός (body) της υπορουτίνας move $s2, $a0 # save $a0 into $s2
move $s3, $a1 # save $a1 into $s3
move $s0, $zero # i = 0
for1tst: slt $t0, $s0, $s3 # $t0 = 0 if $s0 ≥ $s3 (i ≥ n)
beq $t0, $zero, exit1 # go to exit1 if $s0 ≥ $s3 (i ≥ n)
addi $s1, $s0, –1 # j = i – 1
for2tst: slti $t0, $s1, 0 # $t0 = 1 if $s1 < 0 (j < 0)
bne $t0, $zero, exit2 # go to exit2 if $s1 < 0 (j < 0)
sll $t1, $s1, 2 # $t1 = j * 4
add $t2, $s2, $t1 # $t2 = v + (j * 4)
lw $t3, 0($t2) # $t3 = v[j]
lw $t4, 4($t2) # $t4 = v[j + 1]
slt $t0, $t4, $t3 # $t0 = 0 if $t4 ≥ $t3
beq $t0, $zero, exit2 # go to exit2 if $t4 ≥ $t3
move $a0, $s2 # 1st param of swap is v (old $a0)
move $a1, $s1 # 2nd param of swap is j
jal swap # call swap procedure
addi $s1, $s1, –1 # j –= 1
j for2tst # jump to test of inner loop
exit2: addi $s0, $s0, 1 # i += 1
j for1tst # jump to test of outer loop
Pass params & call
Move params
Inner loop
Outer loop
Inner loop
Outer loop
sort: addi $sp,$sp, –20 # make room on stack for 5 registers
sw $ra, 16($sp) # save $ra on stack
sw $s3,12($sp) # save $s3 on stack
sw $s2, 8($sp) # save $s2 on stack
sw $s1, 4($sp) # save $s1 on stack
sw $s0, 0($sp) # save $s0 on stack
… # procedure body
…
exit1: lw $s0, 0($sp) # restore $s0 from stack
lw $s1, 4($sp) # restore $s1 from stack
lw $s2, 8($sp) # restore $s2 from stack
lw $s3,12($sp) # restore $s3 from stack
lw $ra,16($sp) # restore $ra from stack
addi $sp,$sp, 20 # restore stack pointer
jr $ra # return to calling routine
Πλήρης ρουτίνα
Συνχρονισμός
Δύο πυρήνες μοιράζονται μέρος της μνήμης – P1 γράφει, μετά ο P2 διαβάζει – Πρόβλημα αν δεν συνχρονιστούν
Το αποτέλεσμα εξαρτάται από τη σειρά εκτέλεσης Χρειάζεται βοήθεια από το υλικό
– αδιαίρετη (atomic) read/write στη μνήμη – κανείς άλλος δεν πρέπει να αλλάξει την τιμή πριν ολοκληρωθεί η αδιαίρετη προσπέλαση
Συνήθως είναι μία εντολή – Π.χ., αδιαίρετη ανταλλαγή (atomic swap) μεταξύ καταχωρητή και θέσης μνήμης
Συνχρονισμός στο MIPS
Load linked: ll rt, offset(rs) Store condijonal: sc rt, offset(rs)
– Πετυχαίνει αν η θέση δεν έχει αλλαχθεί από τότε που εκτελέστηκε η ll Επιστρέφει 1 στον rt
– Αποτυγχάνει αν η θέση έχει αλλάξει Returns 0 in rt
Παράδειγμα
Υλοποίηση αδιαίρετης ανταλλαγής
try: add $t0,$zero,$s4 #copy exchange value
ll $t1,0($s1) #load linked
sc $t0,0($s1) #store conditional
beq $t0,$zero,try #branch store fails
add $s4,$zero,$t1 #put load value in $s4
Στο τέλος η $s4 και η τιμή στη θέση μνήμης που δείχνει η $S1 έχουν ανταλαχθεί αδιαίρετα
Πλάνες
Ισχυρές εντολές ⇒ μεγαλύτερη απόδοση – πράγματι θέλουμε εκτέλεση λιγότερων εντολών – αλλά πολύπλοκες εντολές υλοποιούνται δύσκολα
Μπορεί να αυξήσουν τον χρόνο εκτέλεσης όλων των εντολών
– Οι μεταφραστές μπορούν να παράγουν καλό κώδικα από απλές εντολές
Χρησιμοποίηση assembly για μεγαλύτερη απόδοση – οι σύγχρονοι μεταφραστές είναι καλοί! – περισσοτερος κώδικας ⇒ περισσότερα λάθη και χαμηλή παραγωγικότητα
Πλάνες Συμβατότητα προς τα πίσω ⇒ το σέτ εντολών δεν αλλάζει
– αλλά νέες εντολές προστίθενται
x86 instrucjon set
Παγίδες
Διαδοχικές λέξεις δεν αντιστοιχούν σε διαδοχικές διευθύνσεις – Η μνήμη θέλει διευθύνσεις σε byte
Χρήση δείκτη σε αυτόματη μεταβλητή (στοίβας) μετά από την επιστροφή από την υπορουτίνα – π.χ. περνώντας δείκτη πίσω σε μια παράμετρο
Περίληψη
Βασικές εντολές MIPS Προγραμματισμός σε assembly
– μετάφραση από C – κλήση υπορουτινών
Κωδικοποίηση εντολών
Επόμενο μάθημα: γλώσσα περιγραφής υλικού Verilog