| ΗΥ-225: Οργάνωση Υπολογιστών
Άνοιξη 2026 |
Τμ. Επ. Υπολογιστών © Πανεπιστήμιο Κρήτης |
|
[Up: Table of Contents] [Prev: 2. Loops, I/O] |
[printer version, in PDF] [Next: 4. Instruction Formats] |
Βιβλίο: Υπόλοιπη §2.3: σελίδες 109-115.
Αντιγραφή μιας 32-μπιτης λέξης από τη μνήμη σ' ένα καταχωρητή ("φόρτωμα στον καταχωρητή") γίνεται με την εντολή "lw rd, offset(rs1)" (load word), όπου rd είναι ο καταχωρητής προορισμού (destination register), και rs1 είναι ένας καταχωρητής πηγής (source/index/base register) που περιέχει μια διεύθυνση μνήμης (pointer) στην οποία προστίθεται ο σταθερός αριθμός offset (απόσταση/απόκλιση), και το αποτέλεσμα της πρόσθεσης είναι η τελική διεύθυνση μνήμης απ' όπου γίνεται η ανάγνωση και αντιγραφή στον rd. Συχνά, συμβολίζουμε τη μνήμη σαν έναν πίνακα (array) M[ ], και γράφουμε M[A] γιά να συμβολίσουμε το περιεχόμενο της θέσης μνήμης με διεύθυνση A. Έτσι, η παραπάνω εντολή lw rd, offset(rs1) προκαλεί ανάγνωση από τη διεύθυνση μνήμης (offset + rs1), δηλαδή διαβάζει το M[offset + rs1], και το γράφει στον καταχωρητή rd. Ο σταθερός αριθμός offset χρησιμοποιείται σαν προσημασμένος από το υλικό του RISC-V, επομένως η "κίνηση" που αυτός επιβάλει σε σχέση με το πού "δείχνει" ο καταχωρητής rs1 μπορεί να είναι προς τα "εμπρός" ή προς τα "πίσω".
Αντίστροφα, αντιγραφή μιας 32-μπιτης λέξης από έναν καταχωρητή στη μνήμη ("αποθήκευση του καταχωρητή") γίνεται με την εντολή "sw rs2, offset(rs1)" (store word), η οποία γράφει στη θέση μνήμης με διεύθυνση (offset + rs1), δηλαδή προκαλεί την αντιγραφή M[offset + rs1] ← rs2. Εδώ, ο rs2 είναι καταχωρητής πηγής (source register)· προσέξτε ότι σε αυτή την περίπτωση, ο τελεστέος πηγής (source operand) γράφεται αριστερά και ο τελεστέος προορισμού δεξιά μέσα στην εντολή Assembly, αντίθετα δηλαδή από τις εντολές αριθμητικών πράξεων και από την εντολή load.
Υπάρχουν και οι παρόμοιες εντολές lb" (load byte) και lh" (load half) που διαβάζουν αντίστοιχα 1 ή 2 Bytes από τη μνήμη, τα μετατρέπουν σε 32 bits θεωρώντας τα προσημασμένα (signed), και τα γράφουν στον καταχωρητή rd. Επίσης οι εντολές lbu" (load byte unsigned) και lhu" (load half unsigned) κάνουν την ίδια δουλειά εκτός ότι στη μετατροπή σε 32 bits θεωρούν τα 8 ή 16 bits που διάβασαν από τη μνήμη σαν μη προσημασμένα. Αντίστοιχα οι εντολές sb" (store byte) και sh" (store half) γράφουν στη μνήμη τα 8 ή 16 δεξιά (λιγότερο σημαντικά - least significant) bits του καταχωρητή rs2.
Στον 64-μπιτο RISC-V (όπως στο βιβλίο), οι καταχωρητές είναι 64-μπιτοι, οπότε η lw διαβάζει πάλι 32 bits από τη μνήμη, όπως και πριν, αλλά τα μετατρέπει σε 64 bits θεωρώντας τα προσημασμένα (signed) γιά να τα γράψει στο 64-μπιτο καταχωρητή rd, ενώ η lwu (load word unsigned) κάνει το ίδιο αλλά στη μετατροπή θεωρεί τα 32 bits που διάβασε σαν unsigned. Αντίστοιχα, η εντολή sw γράφει τα 32 δεξιά (least significant) bits του καταχωρητή rs2 στη μνήμη. Επίσης στον 64-μπιτο RISC-V υπάρχει η ld (load double) που διαβάζει 64 bits (8 bytes) από τη μνήμη, και η sd (store double) που γράφει 64 bits (8 bytes) στη μνήμη. Στους σημερινούς 64-μπιτους υπολογιστές, οι compilers της C θεωρούν τις μεταβλητές τύπου pointer πάντα σαν 64-μπιτες ποσότητες (προφανώς), ενώ τις μεταβλητές τύπου int σαν 32-μπιτους ακεραίους και τις μεταβλητές τύπου long long int σαν 64-μπιτους ακεραίους· τον τύπο long int, τα μεν Windows τον θεωρούν 32 bits, το δε Linux τον θεωρεί 64 bits.
Οι συνήθεις τρόποι χρήσης του παραπάνω τρόπου "διευθυνσιοδότησης" (addressing mode), δηλαδή "καταχωρητής + σταθερά", θα γίνουν κατανοητοί καθώς το μάθημα θα προχωρά. Ας σημειώσουμε όμως εδώ, γιά μελλοντική αναφορά, ότι η πιό συνηθισμένη χρήση είναι με τον καταχωρητή να περιέχει έναν pointer, και τη σταθερή ποσότητα να είναι μιά "απόκλιση" (offset) από εκεί που δείχνει ο pointer. Αυτό χρησιμοποιείται εξαιρετικά συχνά: (α) όταν ο pointer δείχνει σε μιά δομή δεδομένων και η απόκλιση ορίζει ποιό από τα πεδία αυτής της δομής θέλουμε να προσπελάσουμε (π.χ. p->next)· (β) όταν ο καταχωρητής είναι ο stack pointer (sp = x2) και η απόκλιση ορίζει ποιάν από τις τοπικές μεταβλητές της διαδικασίας ζητάμε· και (γ) όταν ο καταχωρητής είναι ο global pointer (gp = x3) και η απόκλιση ορίζει μία από τις καθολικές βαθμωτές μεταβλητές. Μιά άλλη χρήση του τρόπου διευθυνσιοδότησης "σταθερά + καταχωρητής" θα μπορούσε να ήταν με τη σταθερά να είναι η διεύθυνση βάσης ενός (στατικά allocated) πίνακα (array) και ο καταχωρητής να είναι το index του στοιχείου του πίνακα πολλαπλασιασμένο (ήδη) επί το μέγεθος του στοιχείου του πίνακα, οπότε προσπελάζουμε το στοιχείο με εκείνο το index. Όμως στην πράξη, στον RISC-V, αυτό είναι σχεδόν αδύνατο διότι θα έπρεπε ο πίνακας να ξεκινά στα πρώτα 2 KBytes του χώρου διευθύνσεων, ώστε η διεύθυνση βάση του να χωρά στα μόλις 12 bits που έχει η (προσημασμένη) σταθερά. Ευτυχώς, η χρήση αυτή δεν είναι απαραίτητη, διότι συνήθως οι compilers αλλάζουν την αριθμητική με array indexes σε αριθμητική με array element pointers μέσα στους βρόχους που επεξεργάζονται στοιχεία πινάκων.
Για ποσότητες αποτελούμενες από δύο ή περισσότερα Bytes η καθεμία, τα Bytes που τις αποτελούν έχουν διευθύνσεις που είναι συνεχόμενοι αριθμοί. Διεύθυνση της ποσότητας συνολικά είναι πάντα η διεύθυνση του "πρώτου" από τα Bytes που την αποτελούν, δηλαδή εκείνου από τα Bytes της που έχει την μικρότερη διεύθυνση ανάμεσα σε όλα τα Bytes της ποσότητας. Έτσι π.χ. η half-word στη διεύθυνση H αποτελείται από τα Bytes στις διευθύνσεις H και H+1· η word στη διεύθυνση W αποτελείται από τα Bytes στις διευθύνσεις W, W+1, W+2, και W+3· και η double-word στη διεύθυνση D αποτελείται από τα Bytes στις διευθύνσεις D, D+1, D+2, D+3, D+4, D+5, D+6, και D+7.
Όταν αποθηκεύεται στη μνήμη ενός υπολογιστή
μια ποσότητα αποτελούμενη από πολλαπλά bytes (π.χ. ένας ακέραιος),
πρέπει να καθοριστεί με ποια σειρά αριθμούνται (διευθυνσιοδοτούνται)
τα επιμέρους Bytes μέσα στην ποσότητα αυτή.
Δυστυχώς στο παρελθόν δεν είχε υπάρξει συμφωνία
μεταξύ των κατασκευαστών επεξεργαστών για τη σειρά αυτή,
με συνέπεια να υπάρχουν δύο διαφορετικοί τύποι επεξεργαστών
– οι επονομαζόμενοι "Little-Endian" και
οι επονομαζόμενοι "Big-Endian".
Σήμερα πάντως, μοιάζει να επικρατούν οι Little-Endian,
και γι' αυτό ο RISC-V είναι Little-Endian:
Ας ξεκινήσουμε με μια σύμβαση που αφορά τον τρόπο σχεδιασμού στο χαρτί των ποσοτήτων που αποτελούνται από πολλαπλά bytes: Μέσα σ' έναν ακέραιο αριθμό, τα bits εκείνα που πολλαπλασιάζονται επί τις μεγαλύτερες δυνάμεις του 2 για να μας δώσουν την αριθμητική τιμή του ακεραίου λέγονται "περισσότερο σημαντικά" (MS - most significant) bits, και αυτά που πολλαπλασιάζονται επί τις μικρότερες δυνάμεις του 2 λέγονται "λιγότερο σημαντικά" (LS - least significant) bits. Το Byte που περιέχει τα MS bits λέγεται MS Byte, και εκείνο που περιέχει τα LS bits λέγεται LS Byte. Όποτε σχεδιάζουμε έναν ακέραιο στο χαρτί, οριζόντια, θα βάζουμε πάντα τα MS bits και Byte αριστερά, και τα LS bits και Byte δεξιά, δηλαδή όπως και στους δεκαδικούς αριθμούς (φυσικά, η σύμβαση αυτή αφορά μόνο τους ανθρώπους –μέσα στον υπολογιστή δεν έχει νόημα να μιλάμε για "αριστερά transistors" και "δεξιά transistors"...). Ακολουθώντας τη σύμβαση αυτή, το σχήμα δείχνει ένα παράδειγμα τεσσάρων (4) λέξεων μνήμης (16 Bytes) ενός 32-μπιτου υπολογιστή σε μία μηχανή "Big-Endian" και σε μία μηχανή "little-Endian". Η πρώτη λέξη περιέχει τον ακέραιο αριθμό 2003 (δεκαδικό) = 7D3 (δεκαεξαδικό), ενώ στις επόμενες 3 λέξεις υπάρχει ένας πίνακας χαρακτήρων (array of char) μεγέθους 10 στοιχείων, και περισσεύουν και δύο ελεύθερα bytes· ο πίνακας χαρακτήρων περιέχει το (null-terminated) string "katevenis" (κάθε Byte θα περιέχει το δυαδικό κώδικα ASCII ενός χαρακτήρα –π.χ. το πρώτο byte θα περιέχει 01101011, που είναι ο κώδικας του 'k'– αλλά εμείς, για ευκολία, δείχνουμε το συμβολιζόμενο χαρακτήρα).
Το "endian-ness" του υπολογιστή, δηλαδή το αν είναι little-endian ή big-endian, δεν μας επηρεάζει όταν εργαζόμαστε σε ένα και μόνο μηχάνημα, και πάντα γράφουμε και διαβάζουμε την κάθε ποσότητα με τον ίδιο τύπο –πράγμα που είναι και το σωστό να κάνει κανείς– δηλαδή όπου στη μνήμη γράφουμε string διαβάζουμε πάντα string, και όπου γράφουμε integer διαβάζουμε πάντα integer. Το "endian-ness" μας επηρεάζει όταν αλλάζουμε τύπο μεταξύ εγγραφής και ανάγνωσης –πράγμα ανορθόδοξο– π.χ. γράφουμε κάπου ένα string και μετά το διαβάζουμε σαν integer, ή γράφουμε integer και διαβάζουμε string. Το σημαντικότερο όλων όμως είναι ότι το endian-ness του υπολογιστή πρέπει να λαμβάνεται υπ' όψη όταν μεταφέρονται δεδομένα μέσω δικτύου μεταξύ υπολογιστών. Συνήθως, τα προγράμματα μεταφοράς δεδομένων (π.χ. ftp) θεωρούν ότι μεταφέρουμε κείμενο (ASCII strings), και τοποθετούν τα bytes με την αντίστοιχη σειρά. Αν όμως μεταφέρουμε άλλες μορφές δεδομένων (π.χ. 32-μπιτους ακεραίους) μεταξύ υπολογιστών με διαφορετικό endian-ness, η σειρά αυτή θα ήταν λάθος: όπως οι χαρακτήρες k, a, t, e μεταφέρονται σαν e, t, a, k στο παραπάνω σχήμα από big-endian σε little-endian, έτσι και ο ακέραιος 2003 θα ερμηνεύονταν σαν 00, 00, 07, D3 (δεκαεξαδικό), και θα μεταφέρονταν σαν D3, 07, 00, 00, δηλαδή 11010011.00000111.00000000.00000000 (δυαδικό), που είναι ο αριθμός -754,515,968 (δεκαδικό, συμπλήρωμα ως προς 2). Για να γίνει σωστά η μεταφορά, πρέπει να δηλωθεί στο πρόγραμμα μεταφοράς ο τύπος των δεδομένων που μεταφέρονται (π.χ. ftp: εντολή "type").
Επίσης, οι μνήμες κατασκευάζονται πάντοτε με τρόπο ώστε τα Bytes που προσπελάζονται μαζί κατά την κάθε μία προσπέλαση είναι πάντοτε ευθυγραμμισμένα (aligned) στα "φυσικά όρια" των ποσοτήτων μεγέθους όσο το πλάτος της μνήμης. Αυτό σημαίνει ότι οι "ομάδες" των Bytes που προσπελάζονται μαζί αντιστοιχούν στο πώς "γεμίζεται" η μνήμη με τέτοιες "ομάδες" ξεκινώντας από το Byte με διεύθυνση μηδέν (0), και προχωρώντας συνεχώς κατ' αύξουσα διεύθυνση. Όπως είπαμε στην §6.1 της Ψηφιακής Σχεδίασης, όταν μετράμε ξεκινώντας από το μηδέν (0) και ομαδοποιούμε στοιχεία σε ομάδες μεγέθους Π, τότε το στοιχείο με διεύθυνση Ν βρίσκεται στην ομάδα Πηλίκο(Ν/Π), και στη θέση Υπόλοιπο(Ν/Π) μέσα στην ομάδα αυτή. Ανάμεσα σε όλα τα στοιχεία της ίδιας ομάδας, δηλαδή με το ίδιο Πηλίκο, εκείνο με την μικρότερη διεύθυνση είναι προφανώς εκείνο με Υπόλοιπο μηδέν στη διαίρεση (Ν/Π), δηλαδή εκείνο στη θέση μηδέν (0) της ομάδας. Όταν οι ομάδες είναι τα Bytes εκείνα που προσπελάζονται μαζί σε μια μνήμη, δηλαδή Π είναι το πλάτος της μνήμης, αφού διεύθυνση της ομάδας (ποσότητας από Bytes) είναι πάντα η διεύθυνση εκείνου από τα στοιχεία (Bytes) με τη μικρότερη διεύθυνση, προκύπτει ότι η διεύθυνση των ομάδων αυτών στις μνήμες είναι πάντα ακέραιο πολλαπλάσιο του μεγέθους Π της ομάδας, δηλαδή ακέραιο πολλαπλάσιο του πλάτους Π της μνήμης. Αφού το πλάτος των μνημών είναι πάντα δύναμη του 2, Π = 2π, και αφού διαίρεση δια δύναμη του 2 αντιστοιχεί σε επιλογή bits στο δυαδικό, προκύπτει ότι οι ποσότητες μεγέθους όσο το πλάτος μιας μνήμης που είναι ευθυγραμμισμένες (aligned) στα όρια αυτής της μνήμης, δηλαδή που προσπελάζονται όλες ταυτόχρονα στη μνήμη, έχουν πάντα διεύθυνση ακέραιο πολλαπλάσιο του πλάτους της μνήμης, δηλαδή έχουν διεύθυνση με τα π λιγότερο σημαντικά (LS) bits της όλα μηδέν.
Σε τι "είδους" διευθύνσεις μνήμης πρέπει λοιπόν ο μεταφραστής (compiler) να τοποθετεί τις διάφορες μεταβλητές του προγράμματος (και τα πεδία των δομών δεδομένων) προκειμένου αυτές να προσπελάζονται με τον εκάστοτε ελάχιστο δυνατό αριθμό προσπελάσεων στις διάφορες μνήμες, με διάφορα πλάτη, στα διάφορα μοντέλα υπολογιστών όπου το μεταφραζόμενο πρόγραμμα ενδέχεται να τρέχει στο μέλλον; Ας ξεκινήσουμε παρατηρώντας ότι για μια ποσότητα μεγέθους Π = 2π, όταν αυτή προσπελάζεται σε μία μνήμη του ιδίου πλάτους Π, το ελάχιστο δυνατό πλήθος προσπελάσεων είναι μία, και αυτό επιτυγχάνεται τότε και μόνο τότε όταν η ποσότητα μεγέθους Π ταυτίζεται με μια από τις ομάδες των Π Bytes που στη μνήμη προσπελάζονται μαζί, άρα τότε και μόνο τότε όταν η διεύθυνση της ποσότητας είναι ακέραιο πολλαπλάσιο του Π = 2π, δηλαδή τα π LS bits της διεύθυνσης είναι όλα μηδέν, Όταν αυτή η συνθήκη ικανοποιείται, λέμε ότι η ποσότητα αυτή είναι "ευθυγραμμισμένη στα φυσικά της όρια.
Στη συνέχεια παρατηρήστε ότι μια ποσότητα μεγέθους Π = 2π που προσπελάζεται σε μια μνήμη πλάτους Π/2 απαιτεί ένα ελάχιστο δύο (2) προσπελάσεων, και εάν η ποσότητα είναι ευθυγραμμισμένη στα φυσικά της όρια –δηλαδή διεύθυνση ακέραιο πολλαπλάσιο του Π– τότε το ελάχιστο αυτό πλήθος προσπελάσεων εξασφαλίζεται. Το ίδιο ελάχιστο πλήθος προσπελάσεων, δύο, θα ίσχυε και εάν η διεύθυνση της ποσότητας ήταν ακέραιο πολλαπλάσιο του Π/2 αλλά όχι του Π, τότε όμως δεν θα εξασφαλίζονταν το ελάχιστο πλήθος της μίας προσπέλασης σε μνήμες πλάτους Π. Ομοίως, σε μια μνήμη πλάτους Π/4, η ποσότητα μεγέθους Π απαιτεί το λιγότερο τέσσερεις (4) προσπελάσεις, και αυτό το ελάχιστο εξασφαλίζεται εάν η ποσότητα είναι ευθυγραμμισμένη στα φυσικά της όρια. Και πάλι ο ελάχιστος αριθμός 4 θα ίσχυε και για ευθυγραμμίσεις Π/2 ή και Π/4, αλλά τότε δεν θα εξασφαλίζονταν το ελάχιστο πλήθος της μίας προσπέλασης σε μνήμες πλάτους Π. Και ούτω καθ' εξής για ακόμα μικρότερα πλάτη μνημών. Εάν τώρα μια ποσότητα μεγέθους Π = 2π προσπελάζεται σε μνήμη πλάτους 2Π, τότε το ελάχιστο απαιτούμενο πλήθος προσπελάσεων είναι μία (1), και αυτό εξασφαλίζεται εάν η ποσότητα είναι ευθυγραμμισμένη στα φυσικά της όρια –δηλαδή διεύθυνση ακέραιο πολλαπλάσιο του Π– και αντίστοιχα και για ακόμα πλατύτερες μνήμες.
Συνολικά επομένως, μια ποσότητα μεγέθους Π = 2π σε διεύθυνση ακέραιο πολλαπλάσιο του Π –δηλαδή αυτό που λέμε ευθυγραμμισμένη στα φυσικά της όρια– θα προσπελάζεται πάντα με το ελάχιστο δυνατό πλήθος προσπελάσεων σε κάθε μνήμη, οιουδήποτε πλάτους δύναμης του 2. Έτσι, σε όλους τους υπολογιστές, είναι έντονα επιθυμητή μιά τέτοια ευθυγράμμιση γιά λόγους ταχύτητας. Στον RISC-V, η ευθυγράμμιση είναι και πάλι επιθυμητή, πλην όμως προαιρετική, ώστε να εξυπηρετούνται και παλαιά προγράμματα που τυχαίνει να μην την έχουν (ενώ π.χ. στον MIPS η ευθυγράμμιση στα φυσικά όρια είναι υποχρεωτική).
Για να μπορεί ο προγραμματιστής Assembly να ζητήσει την ευθυγράμμιση που θέλει για τις μεταβλητές ή χώρο μνήμης που κρατούν στο data segment, οι Assemblers του RISC-V δέχονται την οδηγία (directive) ".align <num>" η οποία σημαίνει: Προχώρα τη διεύθυνση μνήμης στην οποία θα τοποθετήσεις τον επόμενο χώρο που ζητώ μέχρι το επόμενο ακέραιο πολλαπλάσιο του 2<num>. Έτσι, η οδηγία ".align 2" σημαίνει Προχώρα μέχρι την επόμενη θέση στο data segment που να είναι ακέραιο πολλαπλάσιο του 4", ενώ ".align 3" σημαίνει αντίστοιχα [...] ακέραιο πολλαπλάσιο του 8.
(α) Έστω ότι ο επεξεργαστής αυτός είναι RV32 (δηλαδή 32-μπιτος RISC-V), και ότι σε αυτόν εκτελούνται οι εξής 5 εντολές:
lb x5, 395(x0) lbu x5, 395(x0)
lh x5, 395(x0) lhu x5, 395(x0)
lw x5, 393(x0) [η διεύθυνση αλλάζει λίγο εδώ]
Μετά από κάθε μιαν από αυτές,
γράψτε το περιεχόμενο του καταχωρητή x5 στο δεκαεξαδικό·
το περιεχόμενο του καταχωρητή που θα δώσετε πρέπει να είναι πλήρες,
δηλαδή να έχει τόσα δεκαεξαδικά ψηφία
όσα αντιστοιχούν στο σύνολο των bits του καταχωρητή.
Εξηγήστε εν συντομία.
Αν θέλετε (προαιρετικά), μπορείτε εκ των υστέρων
να επιβεβαιώσετε αυτό που βρήκατε μέσω του RARS
(σε κάποιες παρόμοιες διευθύνσεις του data segment
–όχι τις ίδιες, αφού τόσο μικρές διευθύνσεις
πέφτουν στην "απαγορευμένη" σελίδα και όχι στο data segment)·
όμως, εάν το ψάξετε όντως στον RARS,
να έχετε απαντήσει ήδη από πριν, μόνοι σας την ερώτηση,
ώστε να ξέρετε ήδη εσείς τι περιμένετε να δείτε και γιατί.
(β) Έστω τώρα ότι ο επεξεργαστής είναι RV64 (δηλαδή 64-μπιτος RISC-V), και ότι σε αυτόν εκτελούνται οι 3 παρακάτω εντολές (προσέξτε ότι η διεύθυνση αλλάζει λίγο). Απαντήστε ομοίως όπως στην (α).
lw x5, 396(x0) lwu x5, 396(x0) ld x5, 396(x0)
(γ) Ποιες από τις προσπελάσεις (α) και (β) έχουν την κατάλληλη ευθυγράμμιση ("στα φυσικά τους όρια", όπως λέμε) ώστε να επιτρέπουν την μέγιστη δυαντή ταχύτητα πρόσβασης στις μνήμες όλων των διαφόρων πλατών (δυνάμεις του 2, πάντα), και γιατί;
(δ) Για καθεμιά από τις εντολές (α) και (β), πείτε πόσες προσπελάσεις μνήμης θα χρειαστούν, και ποια ακριβώς Bytes (από ποιες διευθύνσεις) θα διαβάζει η κάθε προσπέλαση, (δ1) σε μνήμη πλάτους 16 bits, (δ2) σε μνήμη πλάτους 32 bits, και (δ3) σε μνήμη πλάτους 64 bits. Ποιες από αυτές πετυχάινουν το ελάχιστο δυνατό πλήθος προσπελάσεων για τον εκάστοτε τελεστέο και την εκάστοτε μνήμη, και ποιές όχι; Συσχετίστε με την απάντηση (γ).
Τρόπος Παράδοσης:
Παραδώστε μέσω του λογαριασμού σας στο elearn,
επιλέγοντας ΗΥ-225 – Ασκήσεις 3, τα εξής:
Θα εξεταστείτε και προφορικά για την Άσκηση 3,
από βοηθούς του μαθήματος,
με διαδικασία γιά την οποία θα ενημερωθείτε
μέσω ηλτά (email) στη λίστα του μαθήματος.
(1)
τον πηγαίο κώδικά σας της άσκησης 3.4, "ex03_4.asm"
(2)
τον πηγαίο κώδικά σας της άσκησης 3.5, "ex03_5.asm"
(3)
ένα στιγμιότυπο (screen-dump) του τρεξίματος της άσκησης 3.4, "ex03_4.jpg"
(4)
ένα στιγμιότυπο (screen-dump) του τρεξίματος της άσκησης 3.5,
"ex03_5.jpg"
(5)
τις απαντήσεις σας της άσκησης 3.6, "ex03_6.pdf",
σε μορφή κειμένου PDF·
μπορεί να είναι κείμενο μηχανογραφημένο ή/και "σκαναρισμένο" χειρόγραφο,
αλλά μόνον σε μορφή PDF.