ΗΥ-225: Οργάνωση Υπολογιστών
Άνοιξη 2012
Τμ. Επ. Υπολογιστών
© Πανεπιστήμιο Κρήτης

Σειρά Ασκήσεων 2:
Βρόχοι και Επικοινωνία Κονσόλας στον SPIM

Προθεσμία έως Κυριακή 26 Φεβρουαρίου 2012, ώρα 23:59 (βδομάδα 3.0) (από βδ. 1.2)
[Up: Table of Contents]
[Prev - 1. SPIM Introduction]
[printer version - PDF]
[3. Memory Accesses - Next]

2.1   Εντολές Διακλάδωσης υπό Συνθήκη στον MIPS

Όπως λέγαμε και στην §
1.3, για να εκτελεστεί ένα πρόγραμμα, οι εντολές του γράφονται στην κεντρική μνήμη η μία "κάτω" από την άλλη, δηλαδή σε συνεχόμενες θέσεις (διευθύνσεις) μνήμης. Μετά την ανάγνωση και εκτέλεση μιας εντολής, ο επεξεργαστής αυξάνει τον PC κατά το μέγεθος της εντολής που εκτελέστηκε, οπότε αυτός (ο PC) δείχνει στην επόμενη (την "από κάτω") εντολή. Η σειριακή αυτή εκτέλεση εντολών διακόπτεται όταν εκτελείται μιά εντολή μεταφοράς ελέγχου (CTI - control transfer instruction). Είδαμε ήδη μία τέτοια, την εντολή άλματος j label ("jump" to label), που κάνει ώστε η επόμενη εντολή που θα εκτελεστεί να είναι η εντολή στη διεύθυνση μνήμης label, αντί να είναι η "από κάτω" εντολή. Με άλλα λόγια, η εντολή j label φορτώνει τη διεύθυνση label στον καταχωρητή PC. Χρησιμοποιώντας αυτή την εντολή άλματος στην άσκηση 1 φτιάξαμε έναν "άπειρο βρόχο", δηλαδή κάναμε τον υπό προσομοίωση υπολογιστή να εκτελεί συνεχώς το ίδιο "μπλόκ" εντολών.

Γιά να φτιάξουμε ένα κανονικό (όχι άπειρο) βρόχο χρειαζόμαστε μια εντολή διακλάδωσης υπό συνθήκη (conditional branch), δηλαδή μια εντολή που μερικές φορές προκαλεί διακλάδωση και μερικές φορές όχι, ανάλογα με το αν ισχύει ή δεν ισχύει κάποια κατάλληλη συνθήκη. Η βασική τέτοια εντολή είναι η beq (branch if equal): Η εντολή "beq $16, $17, label" διαβάζει τους καταχωρητές 16 και 17, και τους συγκρίνει. Εάν τους βρει ίσους (equal) διακλαδίζεται στη θέση label, δηλαδή κάνει τον επεξεργαστή να διαβάσει και εκτελέσει την εντολή από εκείνη τη διεύθυνση σαν επόμενη εντολή. Αλλιώς, δεν κάνει τίποτα, οπότε επόμενη εντολή θα διαβαστεί και εκτελεστεί η "από κάτω" εντολή. Η εντολή bne (branch if not equal) κάνει τα ανάποδα, δηλαδή διακλαδίζεται εάν βρει τους καταχωρητές άνισους (not equal), αλλιώς συνεχίζει "από κάτω".

2.2   Κώδικας Βρόχου και Εισόδου/Εξόδου Κονσόλας

Για να επικοινωνούν τα προγράμματα που τρέχουμε στον SPIM με τον έξω κόσμο, ο SPIM προσομοιώνει μερικές υποτυπώδεις υπηρεσίες λειτουργικού συστήματος για είσοδο/έξοδο (I/O) στην "κονσόλα" (ένα απλό τερματικό ASCII). Δεν είναι ανάγκη προς στιγμήν να καταλάβετε όλες τις λεπτομέρειες του πώς γίνεται η κλήση αυτών των λειτουργιών (system call) --αρκεί να μιμηθείτε το παρακάτω παράδειγμα και να καταλάβετε τις εξηγήσεις που δίνονται κάτω από αυτό. Μελετήστε και αντιγράψτε σε ένα αρχείο (π.χ. "ask2.s") τον παρακάτω κώδικα --ή διάφορες παραλλαγές του που προτιμάτε-- και τρέξτε τον στον SPIM.

                # 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) --βρόγχος υπολογισμού. Προσέξτε τις παρακάτω εξηγήσεις:

Άσκηση 2.3:   Τρέξιμο στον SPIM

Τρόπος Παράδοσης:
Θα παραδώσετε ηλεκτρονικά ένα στιγμιότυπο της οθόνης καθώς τρέχετε το πρόγραμμα "xspim" και αυτό βρίσκεται σ' ένα "ενδιαφέρον" ενδιάμεσο breakpoint. Το στιγμιότυπο θα το ονομάσετε ex02.jpg, και θα το πάρετε και θα το παραδώσετε κατ' αναλογία προς την παράδοση της άσκησης 1, εκτελώντας την εντολή submit ex02@hy225 [directoryName]


© copyright University of Crete, Greece. Last updated: 14 Feb. 2012 (based on 2009 instructions) by M. Katevenis.