ΗΥ-225: Οργάνωση Υπολογιστών
Άνοιξη 2018 |
Τμ. Επ. Υπολογιστών © Πανεπιστήμιο Κρήτης |
[Up: Table of Contents] [Prev - 1. SPIM Introduction] |
[printer version - PDF] [3. Memory Accesses - Next] |
Γιά να φτιάξουμε ένα κανονικό (όχι άπειρο) βρόχο χρειαζόμαστε μια εντολή διακλάδωσης υπό συνθήκη (conditional branch), δηλαδή μια εντολή που μερικές φορές προκαλεί διακλάδωση και μερικές φορές όχι, ανάλογα με το αν ισχύει ή δεν ισχύει κάποια κατάλληλη συνθήκη. Η βασική τέτοια εντολή είναι η beq (branch if equal): Η εντολή "beq $16, $17, label" διαβάζει τους καταχωρητές 16 και 17, και τους συγκρίνει. Εάν τους βρει ίσους (equal) διακλαδίζεται στη θέση label, δηλαδή κάνει τον επεξεργαστή να διαβάσει και εκτελέσει την εντολή από εκείνη τη διεύθυνση σαν επόμενη εντολή. Αλλιώς, δεν κάνει τίποτα το ξεχωριστό, οπότε επόμενη εντολή θα διαβαστεί και εκτελεστεί η "από κάτω" εντολή. Η εντολή bne (branch if not equal) κάνει τα ανάποδα, δηλαδή διακλαδίζεται εάν βρει τους καταχωρητές άνισους (not equal), αλλιώς συνεχίζει "από κάτω".
# compute s = 1+2+3+...+(n-1), for n>=2 # register $16: n # register $17: s # register $18: i .data # init. data memory with the strings needed: str_n: .asciiz "n = " str_s: .asciiz " s = " str_nl: .asciiz "\n" .text # program memory: .globl main # label "main" must be global; # default trap.handler calls main. .globl loop # global symbols can be specified # symbolically as breakpoints. main: # (1) PRINT A PROMPT: addi $2, $0, 4 # system call code for print_string la $4, str_n # pseudo-instruction: address of string syscall # print the string from str_n # (2) READ n (MUST be n>=2 --not checked!): addi $2, $0, 5 # system call code for read_int syscall # read a line containing an integer add $16, $2, $0 # copy returned int from $2 to n # (3) INITIALIZE s and i: add $17, $0, $0 # s=0; addi $18, $0, 1 # i=1; loop: # (4) LOOP starts here add $17, $17, $18 # s=s+i; addi $18, $18, 1 # i=i+1; bne $18, $16, loop # repeat while (i!=n) # LOOP ENDS HERE # (5) PRINT THE ANSWER: addi $2, $0, 4 # system call code for print_string la $4, str_s # pseudo-instruction: address of string syscall # print the string from str_s addi $2, $0, 1 # system call code for print_int add $4, $17, $0 # copy argument s to $4 syscall # print the integer in $4 (s) addi $2, $0, 4 # system call code for print_string la $4, str_nl # pseudo-instruction: address of string syscall # 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) --βρόγχος υπολογισμού. Προσέξτε τις παρακάτω εξηγήσεις:
Γιά να παραδώσετε τις ασκήσεις σας γενικά και αυτήν εδώ ειδικά,
συνδεθείτε σε ένα μηχάνημα Linux του τμήματος.
Ετοιμάστε ένα directory με το(α) αρχείο(α) που σας ζητάει η άσκηση.
Ας υποθέσουμε ότι το όνομα του directory είναι
[somepath]/mydir.
Μετακινηθείτε στο directory [somepath], και εκτελέστε την εντολή:
turnin ex02@hy225 mydir
Η διαδικασία turnin θα σας ζητήσει να επιβεβαιώσετε
την αποστολή των αρχείων.
Περισσότερες πληροφορίες και αναλυτικές οδηγίες
για τη διαδικασία turnin είναι διαθέσιμες στην ιστοσελίδα
https://www.csd.uoc.gr/index.jsp?custom=use_the_turnin
ή εκτελώντας man turnin
σε κάποιο από τα μηχανήματα Linux του Τμήματος.
Γιά επαλήθευση της υποβολής μπορείτε να εκτελέσετε:
verify-turnin ex02@hy225