ΗΥ-225: Οργάνωση Υπολογιστών
Άνοιξη 2020 |
Τμ. Επ. Υπολογιστών © Πανεπιστήμιο Κρήτης |
[Up: Table of Contents] [Prev - 1. Assembly Introduction] |
[printer version - PDF] [3. Memory Accesses - Next] |
Γιά να φτιάξουμε έναν κανονικό (όχι άπειρο) βρόχο
χρειαζόμαστε μια εντολή
διακλάδωσης υπό συνθήκη (conditional branch),
δηλαδή μια εντολή που μερικές φορές προκαλεί διακλάδωση
και μερικές φορές όχι,
ανάλογα με το αν ισχύει ή δεν ισχύει κάποια κατάλληλη συνθήκη.
Η βασική τέτοια εντολή είναι η
beq (branch if equal):
Η εντολή "beq x26, x27, label"
διαβάζει τους καταχωρητές 26 και 27, και τους συγκρίνει.
Εάν τους βρει ίσους (equal) διακλαδίζεται στη θέση label,
δηλαδή κάνει τον επεξεργαστή να διαβάσει και εκτελέσει την εντολή
από εκείνη τη διεύθυνση σαν επόμενη εντολή.
Αλλιώς, δεν κάνει τίποτα το ξεχωριστό,
οπότε σαν επόμενη εντολή θα διαβαστεί και εκτελεστεί η "από κάτω" εντολή.
Η εντολή bne (branch if not equal) κάνει τα ανάποδα,
δηλαδή διακλαδίζεται εάν βρει τους καταχωρητές άνισους (not equal),
αλλιώς συνεχίζει "από κάτω".
Τρόπος Παράδοσης:
Γιά να παραδώσετε τις ασκήσεις σας γενικά και αυτήν εδώ ειδικά,
συνδεθείτε σε ένα μηχάνημα Linux του Τμήματος.
Ετοιμάστε ένα directory με το(α) αρχείο(α) που σας ζητάει η άσκηση.
Ας υποθέσουμε ότι το όνομα του directory είναι
[somepath]/mydir.
Μετακινηθείτε στο directory [somepath], και εκτελέστε την εντολή:
2.2 Κώδικας Βρόχου και Εισόδου/Εξόδου Κονσόλας
Για να επικοινωνούν τα προγράμματα που τρέχουμε στον RARS
με τον έξω κόσμο, ο RARS προσομοιώνει
μερικές υποτυπώδεις υπηρεσίες λειτουργικού συστήματος
για είσοδο/έξοδο (I/O) στην "κονσόλα" (ένα απλό τερματικό ASCII).
Οι κλήσεις στο λειτουργικό σύστημα λέγονταν παραδοσιακά "system call",
αλλά ο RISC-V υιοθετεί το γενικότερο όνομα "environment call (ecall)"
διότι μπορούν να χρησιμοποιηθούν και γιά την κλήση
άλλων περιβαλλόντων ελέγχου (π.χ. hypervisor κλπ).
Δεν είναι ανάγκη προς στιγμήν να καταλάβετε όλες τις λεπτομέρειες
του πώς γίνονται αυτές οι κλήσεις
–αρκεί να μιμηθείτε το παρακάτω παράδειγμα
και να καταλάβετε τις εξηγήσεις που δίνονται κάτω από αυτό.
Μελετήστε και αντιγράψτε
σε ένα αρχείο (π.χ. "ex02.asm")
τον παρακάτω κώδικα
–ή διάφορες παραλλαγές του που προτιμάτε–
και τρέξτε τον στον RARS:
# compute s = 1+2+3+...+(n-1), for n>=2
# register x26: n
# register x27: s
# register x28: i
.data # init. data memory with the strings needed:
str_n: .asciz "n = "
str_s: .asciz " s = "
str_nl: .asciz "\n"
.text # program memory:
main: # (1) PRINT A PROMPT:
addi x17, x0, 4 # environment call code for print_string
la x10, str_n # pseudo-instruction: address of string
ecall # print the string from str_n
# (2) READ n (MUST be n>=2 --not checked!):
addi x17, x0, 5 # environment call code for read_int
ecall # read a line containing an integer
add x26, x10, x0 # copy returned int from x10 to n
# (3) INITIALIZE s and i:
add x27, x0, x0 # s=0;
addi x28, x0, 1 # i=1;
loop: # (4) LOOP starts here
add x27, x27, x28 # s=s+i;
addi x28, x28, 1 # i=i+1;
bne x28, x26, loop # repeat while (i!=n)
# LOOP ENDS HERE
# (5) PRINT THE RESULT:
addi x17, x0, 4 # environment call code for print_string
la x10, str_s # pseudo-instruction: address of string
ecall # print the string from str_s
addi x17, x0, 1 # environment call code for print_int
add x10, x27, x0 # copy argument s to x10
ecall # print the integer in x10 (s)
addi x17, x0, 4 # environment call code for print_string
la x10, str_nl # pseudo-instruction: address of string
ecall # print a new-line
# (6) START ALL OVER AGAIN (infinite loop)
j main # unconditionally jump back to main
Ο κώδικας αυτός υπολογίζει το άθροισμα s=1+2+3+...+(n-1),
για n μεγαλύτερο ή ίσο του 2
--προσοχή: αν δοθεί n μικρότερο του 2,
ο κώδικας θα μπει σε (σχεδόν) άπειρο βρόγχο!
Η "καρδιά" του κωδικά είναι τα κομμάτια (3) --αρχικοποιήσεις--
και (4) --βρόγχος υπολογισμού.
Προσέξτε τις παρακάτω εξηγήσεις:
Άσκηση 2.3: Τρέξιμο στον RARS
Εάν δεν σας δουλεύει ο RARS
και πρέπει να χρησιμοποιήστε τον Venus:
Εάν δεν καταφέρατε να εγκαταστήσετε την Java και τον RARS,
και θέλετε να κάνετε αυτή την άσκηση με τον
www.kvakil.me/venus/
που λέγαμε στην §1.5,
θα πρέπει να κάνετε τρείς αλλαγές στο πρόγραμμα σας:
Πρώτον, η οδηγία ".asciz" του RARS
γράφεται με δύο "i" στον Venus: ".asciiz".
Δεύτερον, ο κωδικός του ecall περνιέται μέσω του καταχωρητή x10 στον Venus
(αντί μέσω του x17 στον RARS),
και το όρισμα (argument) του ecall περνιέται μέσω του x11 στον Venus
(αντί μέσω του x10 στον RARS)
–δείτε τις οδηγίες στο
github.com/kvakil/venus/wiki (item: Environmental Calls).
Και τρίτον, ο Venus δεν έχει ecall γιά ανάγνωση εισόδου (user input),
άρα στη θέση του read_int ecall θα πρέπει να γράψετε μιάν εντολή
π.χ. addi x26, x0, 77
που να αρχικοποιεί π.χ. n=77,
και κάθε φορά που θέλετε να τρέξετε το πρόγραμμά σας με άλλη τιμή του n
να αλλάζετε με τον Editor το "77" μέσα στο πρόγραμμα
στη νέα τιμή που θέλετε.
Θα παραδώσετε ηλεκτρονικά ένα στιγμιότυπο της οθόνης
καθώς τρέχετε το πρόγραμμα "RARS"
και αυτό βρίσκεται σ' ένα "ενδιαφέρον" ενδιάμεσο breakpoint
της επιλογής σας (όχι στην αρχή και όχι στο τέλος του προγράμματος).
Το στιγμιότυπο μπορείτε να το πάρετε π.χ. όπως παρακάτω,
θα το ονομάσετε ex02.jpg, και
θα το παραδώσετε ως εξής:
turnin ex02@hy225 mydir
Η διαδικασία turnin θα σας ζητήσει να επιβεβαιώσετε
την αποστολή των αρχείων.
Περισσότερες πληροφορίες και αναλυτικές οδηγίες
για τη διαδικασία turnin είναι διαθέσιμες στην ιστοσελίδα
https://www.csd.uoc.gr/index.jsp?custom=use_the_turnin
ή εκτελώντας man turnin
σε κάποιο από τα μηχανήματα Linux του Τμήματος.
Γιά επαλήθευση της υποβολής μπορείτε να εκτελέσετε:
verify-turnin ex02@hy225