Uoc LogoΕΛΛΗΝΙΚΗ ΔΗΜΟΚΡΑΤΙΑ
ΠΑΝΕΠΙΣΤΗΜΙΟ ΚΡΗΤΗΣ

CS255 - Programming Lab
Ενότητα: 5 
Άγγελος Μπίλας
Τμήμα Επιστήμης Υπολογιστών



Σκοπός

Ο στόχος της άσκησης αυτής είναι να βοηθήσει στην εισαγωγή (1) σε assembly των επεξεργαστών της αρχιτεκτονικής x86, (2) στην αναπαράσταση της γλώσσας assembly σε κώδικα μηχανής στη μνήμη του συστήματος, και (3) στην χρήση του gdb.

Background

Η άσκηση αυτή θα γίνει στα μηχανήματα, αρχιτεκτονικής x86, του τμήματος με λειτουργικό σύστημα GNU/Linux (portokali, milo, rodakino, etc.). Για θέματα της αρχιτεκτονικής του x86 και της γλώσσας assembly που χρησιμοποιεί μπορείτε να συμβουλευτείτε την online έκδοση του βιβλίου: Programming from the Ground Up, Jonathan Bartlett 2004. (Τοπικό αντίγραφο του βιβλίου για ευκολία). Ιδιαίτερα χρήσιμα θα βρείτε τα Chapter 3 και Appendix B. Ακόμη για αντιστοίχηση εντολών σε opcode μπορείτε να συμβουλευτείτε αυτόν τον πίνακα (προσοχή τα ονόματα κάποιον εντολών διαφέρουν λίγο, π.χ. RET/RETN)

Η άσκηση

1. Δίνεται το πρόγραμμα x86asm.s.

(a) Κάντε compile και εκτελέστε το πρόγραμμα με την εντολή:

gcc -o x86asm x86asm.s

Τι τυπώνει το πρόγραμμα; Δώστε την απάντησή σας στο readme αρχείο της άσκησης σας.

(b) Αντιγράψτε το αρχείο σε ένα x86asm_comments.s αρχείο και συμπληρώστε σχόλια που δείχνουν τι κάνει το πρόγραμμα σε κάθε βήμα του. Είναι αρκετό να συμπληρώσετε σύντομα σχόλια δίπλα σε κάθε σύμβολο "#" που δεν περιέχει ήδη κάποιο σχόλιο.

(c) Εκτελέστε το πρόγραμμα σας μέσα από τον gdb.

Κάντε compile το x86asm.s με την εντολή

gcc -g -o x86asm x86asm.s

Καλέστε τον gdb και εκτελέστε το πρόγραμμα x86asm.

$ gdb x86asm
(gdb) run

(d) Εξετάστε το πρόγραμμα σας μέσα από τον gdb.

Χρησιμοποιήστε την εντολή list "l" (help list) για να δείτε τον source κώδικα του προγράμματος από το source αρχείο x86asm.s.

(gdb) l main

Χρησιμοποιήστε την εντολή examine "x" (help examine) για να δείτε τα περιεχόμενα της μνήμης του προγράμματος ως εντολές assembly.

(gdb) x/??i *main

όπου ?? είναι ο κατάλληλος αριθμός εντολών. Συμπληρώστε στο readme αρχείο σας ποιος είναι ο αριθμός εντολών της main.

Χρησιμοποιήστε την εντολή examine "x" (help examine) για να δείτε τα περιεχόμενα της μνήμης του προγράμματος ως bytes.

(gdb) x/??b *main

όπου ?? είναι ο κατάλληλος αριθμός bytes. Συμπληρώστε στο readme αρχείο σας ποιος είναι ο αριθμός bytes που καταλαμβάνουν οι εντολές της main.

Βάλτε ένα breakpoint μετά το τέλος του loop στη main:

(gdb) b *main+?? # (όπου ?? το κατάλληλο offset)
(gdb) run

Εκτελέστε την υπόλοιπη συνάρτηση main (μέχρι το τελικό μήνυμα του gdb "Program exited normally.", με διαδοχικές εντολές "ni". (Πατώντας enter στο gdb shell επανεκτελείται η τελευταία εντολή)

(gdb) ni
...
(gdb) ni

Συμπληρώστε στο readme αρχείο σας το offset που χρησιμοποιήσατε.

(e) Εκτελέστε το πρόγραμμα πάλι και σταματήστε στο προηγούμενο breakpoint. Εξετάστε τα περιεχόμενα των θέσεων μνήμης S, Msg με την εντολή print "p".

(gdb) p (int )S
(gdb) p (int *)&S
(gdb) p (char *)&Msg

Γράψτε στο readme file σας τις τιμές τους και τις διευθύνσεις στις οποίες βρίσκονται.

Αλλάξτε την τιμή της διεύθυνσης S σε 99:

(gdb) set *(int *)&S = 99

Εκτελέστε το πρόγραμμα μέχρι το τέλος με διαδοχικές εντολές "ni". Συμπληρώστε στο readme αρχείο το μήνυμα που τυπώνει το πρόγραμμα.

2. Δίνεται το πρόγραμμα sum.c.

(a) Κάντε compile και εκτελέστε το πρόγραμμα με την εντολή:

gcc -Wall -pedantic -ansi -o sum sum.c
./sum

Τι τυπώνει το πρόγραμμα; Δώστε την απάντησή σας στο readme αρχείο της άσκησης σας.

(b) Μεταφράστε το πρόγραμμα σε assembly με τον gcc με την εντολή.

gcc -Wall -pedantic -ansi -O2 -S sum.c

Εξετάστε στο αρχείο sum.s που παράγεται και συμπληρώστε στο readme αρχείο σας από πόσες εντολές assembly αποτελείται η συνάρτηση main.

(c) Εκτελέστε και εξετάστε το πρόγραμμα μέσα από τον gdb.

Κάντε compile το πρόγραμμα με την εντολή:

gcc -Wall -pedantic -ansi -g -O2 -o sum sum.c

Καλέστε τον gdb και εκτελέστε το πρόγραμμα sum.

$ gdb sum
(gdb) run

(d) Χρησιμοποιήστε την εντολή list "l" (help list) για να δείτε τον source κώδικα του προγράμματος από το source αρχείο sum.c.

(gdb) l main

Χρησιμοποιήστε την εντολή examine "x" (help examine) για να δείτε τα περιεχόμενα της μνήμης του προγράμματος ως εντολές assembly.

(gdb) x/??i *main

όπου ?? είναι ο κατάλληλος αριθμός εντολών. Συμπληρώστε στο readme αρχείο σας ποιος είναι ο αριθμός εντολών της main.

Χρησιμοποιήστε την εντολή examine "x" (help examine) για να δείτε τα περιεχόμενα της μνήμης του προγράμματος ως bytes.

(gdb) x/??b *main

όπου ?? είναι ο κατάλληλος αριθμός bytes. Συμπληρώστε στο readme αρχείο σας ποιος είναι ο αριθμός bytes που καταλαμβάνουν οι εντολές της main.

Βάλτε ένα breakpoint μετά το τέλος του loop στη main:

(gdb) b ?? # (όπου ?? το κατάλληλο offset στο source αρχείο)
(gdb) run

Εκτελέστε την υπόλοιπη συνάρτηση main (μέχρι το τελικό μήνυμα του gdb "Program exited normally." με διαδοχικές εντολές "n". (Πατώντας enter στο gdb shell επανεκτελείται η τελευταία εντολή)

(gdb) n
...
(gdb) n

Συμπληρώστε στο readme file σας το offset που χρησιμοποιήσατε για το breakpoint.

(e) Εκτελέστε το πρόγραμμα πάλι και σταματήστε στο προηγούμενο breakpoint. Εξετάστε τα περιεχόμενα των μεταβλητών Sum, n.

(gdb) p Sum
(gdb) p &Sum
(gdb) p n
(gdb) p &n

Γράψτε στο readme file σας τις τιμές τους και τις διευθύνσεις στις οποίες βρίσκονται.

Αλλάξτε την τιμή της μεταβλητής Sum σε 98 και 99 διαδοχικά με δύο διαφορετικούς τρόπους:

(gdb) set Sum = 98
(gdb) set *(int *)?? = 99 # (όπου ?? η διεύθυνση της μεταβλητής Sum στη μνήμη)

Εκτελέστε το πρόγραμμα μέχρι το τέλος με διαδοχικές εντολές "n". Συμπληρώστε στο readme file το μήνυμα που τυπώνει το πρόγραμμα.

(f) Εκτελέστε το πρόγραμμα πάλι και σταματήστε με ένα breakpoint στην αρχή της main. Αλλάξτε την εντολή cmp στη μνήμη ώστε να συγκρίνει τη μεταβλητή "n" με την τιμή 100 αντί για την τιμή 0. Μπορείτε να χρησιμοποιήσετε μια ακολουθία εντολών όπως η παρακάτω:

(gdb) x/??i *main # (όπου ?? ο αριθμός εντολών assembly στη main)
(gdb) x/2i ?? # (όπου ?? η διεύθυνση της εντολής cmp)
(gdb) x/??b ???? # (όπου ?? ο αριθμός bytes που καταλαμβάνει η εντολή cmp και ???? η διεύθυνση της)
(gdb) set *(char *)(?? + ????) = 100 # (όπου ?? η διεύθυνση της εντολής cmp όπως παραπάνω και ???? το offset του byte της εντολής cmp που περιέχει την τιμή 0)
(gdb) x/2i ?? # (όπου ?? η διεύθυνση της εντολής cmp, θα δείτε την εντολή cmp να έχει διαφορετικά operands) 

Σβήστε το breakpoint και εκτελέστε το πρόγραμμα μέχρι το τέλος:

(gdb) d
(gdb) c

Συμπληρώστε στο readme file σας το μήνυμα που τυπώνει το πρόγραμμα.

3. Μας ζητούν να αντικαταστήσουμε στο πρόγραμμα sum.c το while loop με πιο "αποτελεσματικό" κώδικα assembly. Οπότε χρησιμοποιούμε τον κώδικα του x86asm.s. Δίνεται το αρχείο x86sum.c που περιέχει "inline assembly" κώδικα μέσα στο C πρόγραμμα.

(a) Κάντε compile το πρόγραμμα x86sum.c με την εντολή

gcc -Wall -pedantic -ansi -fasm -o x86sum x86sum.c

Εκτελέστε το πρόγραμμα και συμπληρώστε στο readme file σας το μήνυμα που τυπώνει.

(b) Κάντε compile το πρόγραμμα x86sum.c με την εντολή

gcc -Wall -pedantic -ansi -fasm -S x86sum.c

Μετρήστε και συμπληρώστε στο readme file σας τον αριθμό των εντολών assembly που υπάρχουν στην main.

(c) Αλλάξτε το όνομα των μεταβλητών "n, Sum" σε "i, S" αντίστοιχα και ονομάστε το νέο source file x86sum2.c. Κάντε compile το νέο πρόγραμμα όπως παραπάνω, εκτελέστε το, και συμπληρώστε στο readme file το μήνυμα που τυπώνει.

Logistics

  • Χρησιμοποιήστε τα μηχανήματα x86 με λειτουργικό σύστημα GNU/Linux του τμήματος και τα εργαλεία gcc, emacs/vim/nano, gdb.
  • Δημιουργήστε ένα "readme" text file που περιέχει:
    • Το όνομά σας
    • Πράγματα που χειρίζεστε με διαφορετικό τρόπο από ότι ορίζει η άσκηση.
    • Μια περιγραφή της βοήθειας που είχατε από άλλους στη δημιουργία του προγράμματος σας, και σε συμφωνία με το Policies section του web page του μαθήματος.
    • (Προαιρετικά) Μία ένδειξη του πόσο χρόνο αφιερώσατε για την άσκηση.
    • (Προαιρετικά) Οτιδήποτε άλλο θέλετε να αναφέρετε.
  • Παραδώστε τα αρχεία της άσκησης: x86asm_comments.s, x86sum2.c, readme.

Turnin

Υποβάλετε την άσκηση σας όπως αναφέρεται στο section Policies του web page του μαθήματος.

Βαθμολογία

Η βαθμολογία θα βασιστεί στην κατανόηση της άσκησης.


Άδειες Χρήσης
 •Το παρόν εκπαιδευτικό υλικό υπόκειται στην άδεια χρήσης Creative Commons και
ειδικότερα
Αναφορά - Μη εμπορική Χρήση - Όχι Παράγωγο Έργο 3.0 Ελλάδα
(Attribution - Non Commercial - Non-derivatives 3.0 Greece) 

•Εξαιρείται από την ως άνω άδεια υλικό που περιλαμβάνεται στις διαφάνειες
του μαθήματος, και υπόκειται σε άλλου τύπου άδεια χρήσης. Η άδεια χρήσης
στην οποία υπόκειται το υλικό αυτό αναφέρεται ρητώς.

Χρηματοδότηση
•Το παρόν εκπαιδευτικό υλικό έχει αναπτυχθεί στα πλαίσια του εκπαιδευτικού έργου του διδάσκοντα.
•Το έργο «Ανοικτά Ακαδημαϊκά Μαθήματα στο Πανεπιστήμιο Κρήτης» έχει χρηματοδοτήσει μόνο τη αναδιαμόρφωση του εκπαιδευτικού υλικού. 
•Το έργο υλοποιείται στο πλαίσιο του Επιχειρησιακού Προγράμματος «Εκπαίδευση και Δια Βίου Μάθηση» και συγχρηματοδοτείται από την Ευρωπαϊκή Ένωση (Ευρωπαϊκό Κοινωνικό Ταμείο) και από εθνικούς πόρους.


espa

Τελευταία τροποποίηση: Παρασκευή, 10 Ιουλίου 2015, 2:27 PM