ΠΑΝΕΠΙΣΤΗΜΙΟ ΚΥΠΡΟΥ Τμήμα Ηλεκτρολόγων Μηχανικών και Μηχανικών Υπολογιστών (ΗΜΜΥ) Λύσεις 2 ης Ενδιάμεσης Εξέτασης στο ΗΜΥ213 Εαρινό Εξάμηνο, 2012 Διδάσκων: Γιώργος Ζάγγουλος Ημερομηνία εξέτασης: 01/03/2012 Α 1. Δίνονται τα περιεχόμενα των καταχωρητών και της μνήμης ως ακολούθως: $t0 = 0x50000005 $t1=0x50000003 $t2=0x784411ff $t3 = 0x0234ABCD 0x50000005: 0x50 0x50000006: 0x60 0x50000007: 0x70 0x50000008: 0x80 0x50000009: 0x90 0x5000000A: 0x1A 0x5000000B: 0x2B 0x5000000C: 0x3C Δείξτε ποιοι καταχωρητές/ θέσεις μνήμης θα αλλάξουν, και δώστε τα νέα τους περιεχόμενα μετά από κάθε εντολή αν η κάθε εντολή είναι ανεξάρτητη από τις προηγούμενες: (24 μονάδες) lb $t3, 5($t0) $t3 = 1A lb $t4, 0x5000000A $t4 = 1A lw $t5, 1($t0) $t5 = 0x 90 80 70 60 sb $t0, ($t1) Θέση μνήμης 0x 50 00 00 03 = 0x 05 sw $t1, 0x50000007 Θέσεις μνήμης 0x 50 00 00 07 / 8 / 9 / A = 0x 05 / 00 / 00 / 50 and $t6, $t1, $t2 $t6 = $t1 and $t2 = 0x 50 00 00 03 xor $t7, $t1, $t3 mtc0 $t3, $11 $t7 = $t1 xor $t3 = 0x 02 34 AB CE $11 = $t3 = 0x 0234ABCD 2. Γράψτε τις απαραίτητες εντολές (λιγότερες από 6) με τις οποίες ο προγραμματιστής μπορεί να ενεργοποιήσει μόνο τα σήματα διακοπής από το πληκτρολόγιο έτσι ώστε μετά από σήμα διακοπής να επιτρέπεται το διάβασμα του πλήκτρου (όλα τα υπόλοιπα σήματα διακοπής θα πρέπει να είναι απενεργοποιημένα). (6 μονάδες) li $t0, x # x = 2^0 + 2^11 mct0 $t0, $12 li $t0, 2 sb $t0, 0x ffff0000 1
3. Γράψτε τις απαραίτητες εντολές (λιγότερες από 8) με τις οποίες ο προγραμματιστής μπορεί να ενεργοποιήσει μόνο τα σήματα διακοπής από το ρολόι έτσι ώστε το πρόγραμμα μετά την ενεργοποίηση του timer, να αναμένει σε κάποιο βρόχο (loop) για χρόνο 15 δευτερολέπτων και μετά να συνεχίζει την εκτέλεση του υπόλοιπου κώδικα (το αρχείο exceptions.s είναι έτοιμο και αυξάνει πριν την έξοδο του τον EPC κατά 4). (8 μονάδες) li $t0, x # x = 2^0 + 2^15 mct0 $t0, $12 li $t0, 1500 # 15 / 10ms = 1500 mct0 $t0, $11 mct0 $0, $9 wait : b wait 4. Γράψτε ένα μικρό πρόγραμμα (παρόμοιο με τον κώδικα που προσθέσατε στο αρχείο exceptions.s) με το οποίο μπορείτε να ελέγξετε το είδος του interrupt (είναι ήδη ενεργοποιημένα τα σήματα διακοπής από το πληκτρολόγιο και το ρολόι) και στη συνέχεια αν έχει γίνει keyboard interrupt να αποθηκεύετε στη θέση μνήμης 0x10000050 τoν αντίστοιχο ascii χαρακτήρα που το προκάλεσε (το πλήκτρο που πατήθηκε) ή αν έχει γίνει timer interrupt να αποθηκεύετε στη θέση μνήμης 0x10000060 την τιμή του χρόνου σε δευτερόλεπτα (μόνο το ακέραιο μέρος) (22 μονάδες) mfc0 $s5, $13 andi $s6, $s5, 32768 #2^15 bne $s6, $0, timming_inter andi $s6, $s5, 2048 #2^11 bne $s6, $0, keyboard_inter keyboard_inter: lb $s4, 0xffff0004 sb $s4, 0x10000050 b here timming_inter: mfc0 $s4, $9 li $t1, 100 div $s4, $s4, $t1 # div by 100 to get seconds! sb $s4, 0x10000060 here: 5. Εάν ο EPC αυξάνεται κατά 4 (μέσα στο exceptions.s) μετά από keyboard interrupt αλλά όχι μετά από timing interrupt, περιγράψτε πως θα λειτουργούσε ο πιο κάτω κώδικας αν είναι ενεργοποιημένα τα keyboard και timer interrupts πριν το βρόχο και ο $11 έχει την τιμή 1000. (10 μονάδες) mtc0 $0, $9 wait_here: b wait_here mtc0 $0, $9 wait1_here: b wait1_here Με τον EPC να αυξάνεται κατά 4 (μέσα στο exceptions.s) μετά από keyboard interrupt αλλά όχι μετά από timing interrupt, ο πιο πάνω κώδικας θα εισέλθει στο πρώτο βρόχο (wait_here) και θα περιμένει εκεί μέχρι να συμβεί κάποιο interrupt. Μετά θα τρέξει το exceptions και θα επιστρέψει πίσω. Να σημειωθεί όμως ότι μόνο με το πάτημα κάποιου πλήκτρου, το πρόγραμμα θα συνεχίσει κάτω από το βρόχο, άσχετα με το χρόνο που έχει περάσει. Το ίδιο θα συμβεί και με το 2 ο βρόχο (wait1_here). 2
6. Από τις 2 επιλογές που υπάρχουν στο 6, επιλέξτε ΜΟΝΟ τη 1 και δώστε τη λύση σας. Επιλογή 1: Ένα πρόγραμμα αρχικά ανοίγει κάποιο αρχείο (text file) και αποθηκεύει το περιεχόμενο του στη μνήμη αρχίζοντας από την διεύθυνση με ετικέτα file_content και προχωρώντας προς τα κάτω (-1). Μετά την αποθήκευση του στη μνήμη το αρχείο κλείνει με κλήση συστήματος 16. Καλείστε λοιπόν να γράψετε ένα πρόγραμμα, το οποίο να καλεί την συνάρτηση push με μία εντολή jal και να αποθηκεύει τους πρώτους 16 χαρακτήρες από το περιεχόμενο του text file (που βρίσκεται τώρα στη μνήμη) σε μια στοίβα (την οποία θα δημιουργήσετε). Στην συνέχεια, με κλήση της συνάρτησης pop (πάλι με μια εντολή jal) να αδειάσετε την στοίβα εκτυπώνοντας τους 16 χαρακτήρες στην οθόνη. Οδηγίες: Η βάση της στοίβας πρέπει να είναι στη διεύθυνση 0x10000010. $t1 πρέπει να χρησιμοποιηθεί ως stack pointer και ο $t2 ως base pointer. Πριν από κάθε εκτέλεση της push ή της pop, θα πρέπει να γίνονται και οι απαραίτητοι ελέγχοι! Οι συνεχιζόμενες εκτελέσεις της συνάρτησης push και pop μπορούν να γίνουν είτε με κανονικό βρόχο είτε ως αναδρομική κλήση. Η μετακίνηση των δεικτών της μνήμης, η εκτύπωση, κ.τ.λ. μπορούν να υλοποιηθούν μέσα στις ίδιες τις συναρτήσεις για λόγους ευκολίας (30 μονάδες) la $t1, 0x10000010 la $t2, 0x10000010 la $t0, file_content la $t6, 0x10000000 jal push move $a0, $t2 jal push jal pop # used as $sp # used as $bp # last address for stack! exit_now: li $v0, 10 push: pop: beq $t1, $t6, stack_full lb $t4, ($t0) addi $t1, $t1, -1 sb $t4, ($t1) addi $t0, $t0, -1 b push beq $t1, $t2, stack_empty lb $a0, 0($t1) addi $t1, $t1, 1 li $v0, 11 stack_full: li $v0, 4 la $a0, full_stack # prints stack is full # goes back under jal push b exit_now stack_empty:li $v0, 4 la $a0, empty_stack # goes back under jal pop b exit_now 3
Επιλογή 2: Γράψετε ένα πρόγραμμα, το οποίο να ανοίγει το αρχείο input.txt και να αποθηκεύει το περιεχόμενο του σε δύο λίστες στη μνήμη. Η πρώτη λίστα να ονομαστεί kwh και η δεύτερη price_per_kwh. Μετά από τη δημιουργία των 2 λιστών, το κάθε στοιχείο από την 1 η λίστα πρέπει να πολλαπλασιαστεί με το αντίστοιχο της 2 ης λίστας και όλα τα γινόμενα να προστεθούν για να υπολογιστεί το κόστος του ηλεκτρικού ρεύματος το οποίο πρέπει να εκτυπωθεί στην οθόνη. Οδηγίες: Ως δείκτες στη μνήμη, πρέπει να χρησιμοποιηθούν μόνο οι $s0, $s1, $s2, και $s3 (αν χρειαστούν). Τα flags και το mode για το άνοιγμα δίνονται ως ακολούθως: li $a1, 0 και li $a2,0770 Το κόστος του ηλεκτρικού ρεύματος μπορεί να υπολογιστεί με άθροισμα γινομένων ως kwh(1)x price_per_kwh(1) + kwh(2)x price_per_kwh(2) + kwh(3)x price_per_kwh(3) + Το περιεχόμενο του αρχείου input.txt έχει την ακόλουθη μορφή χωρίς οποιαδήποτε κενά 300,150,75,;26,25,22,/ όπου οι πρώτοι 4 «αριθμοί» είναι οι kwh (κιλοβατ-ώρες) ενώ μετά το ερωτηματικό ακολουθούν οι αντίστοιχες τιμές που προορίζονται για τη λίστα price_per_kwh Ο κώδικάς σας θα πρέπει να γραφτεί με τρόπο που να τρέχει σωστά εάν αλλάξουν, προστεθούν ή αφαιρεθούν στοιχεία από το αρχείο, χωρίς να αλλάξει η μορφή του αρχείου. Ο μέγιστος αριθμός στοιχείων (αριθμών) για την κάθε λίστα πρέπει να είναι 8 Απαιτείται χρήση της ΑΤΟΙ για μετατροπή του περιεχομένου του αρχείου σε ακέραιους αριθμούς. (30 μονάδες) # Παράδειγμα λύσης επιλογής 2.data static_memory:.space 40 filename:.asciiz"input.txt" kwh:.word 0,0,0,0,0,0,0,0 price_per_kwh:.word 0,0,0,0,0,0,0,0 empty:.asciiz"\n\n".text main: # ===========# OPEN.txt FILE ================ li $v0, 13 la $a0, filename li $a1, 0 li $a2,0770 beq $v0, -1, no_file # READ.txt FILE and SAVE it in memory starting at static_memory move $a0, $v0 # a0 = file descriptor la $a1, static_memory # a1 = buffer (memory) li $s2, 0 # a2 = number of bytes to be read li $a2, 1# a2 = 1 in order to read character by charac next_charac: li $v0, 14 beq $v0, 0, read_error lb $s2, 0($a1) beq $s2, 47, close_file addi $a1, $a1, -1 b next_charac close_file: li $v0, 16 # ========= ATOI =========== li $t4, 10 li $t5, 0 li $t8, 0 la $s0, static_memory 4
la $s1, kwh atoi: lb $t0, ($s0) addi $s0, $s0, -1 beq $t0, 44, save_num beq $t0, 47, exit_atoi beq $t0, 59, change_list sub $t0, $t0, 0x30 mul $t5, $t5, $t4 add $t5, $t5, $t0 save_num: addi $t8, $t8, 1 #counter sw $t5, ($s1) addi $s1, $s1, 4 li $t5, 0 change_list: la $s1, price_per_kwh move $t9, $t8 exit_atoi: la $s1, kwh la $s2, price_per_kwh li $t4, 0 #=============== calculations 7 monades ============================= cost: lw $t0, ($s1) lw $t1, ($s2) mul $t3, $t0, $t1 add $t4, $t4, $t3 addi $t9, $t9, -1 addi $s1, $s1, 4 addi $s2, $s2, 4 bnez $t9, cost next_print: li $v0, 1 move $a0, $t4 no_file: read_error: exit_now: li $v0, 10 # system call code for exit = 10 5