All pastes #249075 Raw Edit

Someone

public text v1 · immutable
#249075 ·published 2006-11-15 11:40 UTC
rendered paste body
Άσκηση 1 - Σύνδεση & επικοινωνία ρουτίνων σε διάφορες γλώσσες.
Θεωρητικό μέρος :
Διασύνδεση της γλώσσας Assembly με τη γλώσσα C
Πολλές φορές είναι χρήσιμη η διασύνδεση προγραμμάτων ή ρουτινών Assembly, με προγράμματα «υψηλού επιπέδου» τα οποία μπορεί να περιέχουν πόρους που δεν είναι διαθέσιμοι προγραμματίζοντας μόνο σε Assembly. Ένα παράδειγμα αποτελούν οι έτοιμες συναρτήσεις γραφικών της C καθώς και οι συναρτήσεις επεξεργασίας συμβολοσειρών. Αντιστρόφως, πολλές φορές είναι αναγκαίο να συμπεριλαμβάνονται μικρές ρουτίνες Assembly σε ένα μεταφρασμένο πρόγραμμα «υψηλού επιπέδου» επωφελούμενοι της ταχύτητας της γλώσσας μηχανής.

Όλες οι γλώσσες «υψηλού επιπέδου» έχουν ειδικές συμβάσεις κλήσης που επιτρέπουν μια γλώσσα να επικοινωνεί με μια άλλη, δηλαδή να στείλει μεταβλητές, τιμές κλπ. Ένα πρόγραμμα Assembly που είναι γραμμένο από κοινού με ένα πρόγραμμα «υψηλού επιπέδου» επίσης πρέπει να έχει ειδικές συμβάσεις επικοινωνίας, εάν θέλουμε η ενοποίησή τους να είναι επιτυχής. 

Συνήθως οι γλώσσες «υψηλού επιπέδου» περνούν παραμέτρους στις διαδικασίες χρησιμοποιώντας τη στοίβα. Αυτή είναι και η περίπτωση της γλώσσας C.

 

Πέρασμα παραμέτρων σε διαδικασίες στη γλώσσα C
Η C περνάει παραμέτρους στις διαδικασίες μέσω της στοίβας. Για παράδειγμα, ας εξετάσουμε τις παρακάτω εντολές από ένα κύριο πρόγραμμα της C.

Extern int Sum();

Int a,bc;

c=Sum(a,b);

 

 Όταν η C εκτελεί την κλήση προς τη συνάρτηση Sum, αποθηκεύει τις παραμέτρους στη στοίβα με αντίστροφη σειρά από αυτή που αναφέρονται και στη συνέχεια μεταφέρει τον έλεγχο στη Sum. Με την είσοδο στη συνάρτηση Sum η στοίβα περιέχει τα εξής:

   

Αφού τα a,b έχουν δηλωθεί ως ακέραιες (int) μεταβλητές, ο χώρος που καταλαμβάνουν στη στοίβα είναι από μια λέξη (2 bytes). Αυτή η μέθοδος περάσματος παραμέτρων στη διαδικασία είναι γνωστή ως πέρασμα με τιμή (passing by value). Στην περίπτωση που θέλουμε να δώσουμε τη δυνατότητα στη  διαδικασία να μεταβάλει τις τιμές των παραμέτρων τότε, το πέρασμα των παραμέτρων γίνεται με αναφορά (by reference), δηλαδή στη στοίβα τοποθετείται όχι η τιμή της παραμέτρου, αλλά η διεύθυνσή της. Για παράδειγμα η κλήση προς τη διαδικασία Sum:

 Sum (&a,&b); 

διαμορφώνει τη στοίβα ως εξής:

   

Σημειώστε ότι η C συνήθως προσθέτει μία υπογραμμή (“_”) πριν το όνομα κάθε διαδικασίας. Έτσι η Sum θα φαίνεται στην Assembly ως “_Sum”. 

Επίσης, η C διατηρεί τον τύπο των γραμμάτων (μικρά, κεφαλαία) και στο εκτελέσιμο κώδικα, αντίθετα με την Assembly και την Pascal, που συνήθως μετατρέπουν τα πάντα σε κεφαλαία. Για το λόγο αυτό, η μεταγλώττιση της Assembly απαιτεί την παράμετρο «/Ml» που διατηρεί τα μικρά στις εττικέτες (labels, procedures κλπ).

Αν μία συνάρτηση έχει τύπο επιστροφής μέχρι δύο bytes -όπως λ.χ. int length()- τότε η επιστρεφόμενη τιμή βρίσκεται στον AX.

 


--------------------------------------------------------------------------------

Ζητούμενα της Άσκησης :
 Γράψτε ένα κύριο πρόγραμμα σε Assembly που θα καλεί μία διαδικασία (function) σε C, η οποία με τη σειρά της θα καλεί μία διαδικασία Assembly. Το κυρίως πρόγραμμα θα πρέπει να δηλώνει δύο strings, να διαβάζει στο ένα string με τη λειτουργία 0Ah, int 21h και μετά να καλεί τη διαδικασία περνώντας ως παραμέτρους με αναφορά τα δύο strings. Η διαδικασία στη C είναι έτοιμη και δίνεται. Πρώτα μετρά το μήκος του πρώτου string (char* str) καλώντας τη διαδικασία (function) length Μετά μεταφέρει από το ένα string στο άλλο τους χαρακτήρες, μετατοπίζοντάς τους  

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

Εννοείται πως το κύριο πρόγραμμα και η διαδικασία θα γραφούν σε ανεξάρτητα αρχεία και θα μεταφραστούν χωριστά, από τον compiler της C και από τον Assembler, όπου χρειάζεται (υπάρχει έτοιμο OBJ για το τμήμα C). Παρακάτω  περιέχονται οι απαραίτητες εντολές και ρυθμίσεις, για την Turbo C 2.01, τον MASM και τον LINK. 

Tο φύλλο έργου θα περιλαμβάνει επαρκή τεκμηρίωση (εισαγωγή, διαδικασία υλοποίησης, αλγόριθμο, σχολιασμό του προγράμματος και αποτελέσματα).

Προσοχή:

1. Η υλοποίηση της διαδικασίας πρέπει να ακολουθήσει τις συμβάσεις της γλώσσας, από την οποία γίνεται η κλήση. Κάθε γλώσσα έχει τις ιδιαιτερότητές της. Στη συγκεκριμένη περίπτωση που το κυρίως πρόγραμμα είναι γραμμένο σε C πρέπει να προσέξετε τα εξής:

Το όνομα της διαδικασίας να αρχίζει με υπογραμμή "_". 
Μπορούν να χρησιμοποιηθούν όλα τα μοντέλα μνήμης, αλλά θα πρέπει τότε να μεταγλωττιστεί ξανά το πρόγραμμα της C. Προτείνουμε "model small" στα πλαίσια της άσκησης. 
Για να μπορεί το κυρίως πρόγραμμα να δει τη διαδικασία πρέπει να δηλωθεί στο αρχείο της Assembly ως εξωτερικό "EXTRN _asm2pas:PROC", μέσα στο τμήμα κώδικα αλλά πριν την ετικέτα start -αν υπάρχει- και οποιοδήποτε άλλο κώδικα. 
Για να μπορεί η C να δει τη διαδικασία "length", πρέπει να δηλωθεί ως καθολική μεταβλητή με τη δήλωση "PUBLIC _length". Η διαδικασία δε χρειάζεται να έχει τμήμα στοίβας, γιατί χρησιμοποιεί αυτό του κυρίως προγράμματος. Τέλος η δήλωση "END" στο τέλος του αρχείου δεν πρέπει να έχει ετικέτα. 
Η C περιμένει το αποτέλεσμα μίας συνάρτησης στον AX, εφόσον είναι 2 bytes, όπως της length. Η ίδια επίσης επιστρέφει το αποτέλεσμά της στον AX. 
Η διαδικασία πρέπει να επαναφέρει τις τιμές των καταχωρητών που χρησιμοποιεί  (με PUSH και POP). 
  

2. Τρέξτε το πρόγραμμά σας μέσα από το CodeView (εντολή-εντολή) και σημειώστε τα εξής (θα τα αναφέρετε στο φύλλο έργου):

Πως γίνεται το πέρασμα των παραμέτρων από και προς τη C. Δείτε το τμήμα C μεταφρασμένο (View Mixed ή Assembly), εντοπίστε τις εντολές στις οποίες μεταφράζεται η κλήση της διαδικασίας length και εξηγήστε τι κάνει η καθεμιά. 
Τα περιεχόμενα της στοίβας και του δείκτη στοίβας πριν και αμέσως μετά την είσοδο στη διαδικασία length, καθώς και αμέσως μετά την εντολή RET. Εξηγήστε τι σημαίνουν αυτές οι τιμές. 
Τον τρόπο (εντολές σε Assembly) με τον οποίο η διαδικασία asm2pas (σε C) ορίζει τις τοπικές μεταβλητές της (len). 
Τα περιεχόμενα της μνήμης αμέσως πριν το τέλος του προγράμματος, για τα δύο strings που δηλώσατε. 
 

Μπορείτε από εδώ να πάρετε : 

1. το τμήμα του κώδικα σε πηγαίο κώδικα C (Micro1c.C).

2. το ίδιο τμήμα κώδικα μεταγλωττισμένο (Micro1c.OBJ).

 

Σημειώσεις για τη μεταγλώττιση κ.λ.π. :

Η μεταγλώττιση του προγράμματος (ή των τμημάτων) σε Assembly μπορεί να γίνει με τον γνωστό MASM. Πρέπει όμως να χρησιμοποιήσετε επιπλέον παραμέτρους. Επειδή η C διατηρεί τα μικρά ονόματα στις μεταβλητές και τις ρουτίνες, πρέπει ο MASM να κάνει το ίδιο (/Mx). Για παράδειγμα, αν το αρχείο μας λέγεται TEST θα πρέπει να δώσουμε την ακόλουθη εντολή :

	MASM /ZI /Z /W2 /v /Mx test;
Μπορούμε να χρησιμοποιήσουμε εναλλακτικά την παράμετρο /Ml αντί για /Mx προσέχοντας όμως να χρησιμοποιούμε παντού ονόματα με μικρά γράμματα, όπως λχ  MOV AX,@data.

Η σύνδεση των αρχείων γίνεται με το γνωστό LINK, κατά τα γνωστά. Όλα τα αρχεία δηλώνονται στη σειρά, με πρώτο αυτό που αποτελεί το κυρίως πρόγραμμα (στη C αυτό που περιέχει την main(), στην Assembly αυτό που έχει την ετικέτα start, κ.ο.κ.). Για παράδειγμα, αν έχουμε το τμήμα C και 2 ακόμη αρχεία, με κυρίως το main, η εντολή θα είναι ως εξής :

	LINK /CO main micro1 teleytaio;
Η μεταγλώττιση του τμήματος σε C έγινε με το περιβάλλον ανάπτυξης Borland Turbo 2.01, από τη δεκαετία του '80. Το περιβάλλον αυτό μπορείτε να το βρείτε από τις σχετικές ιστοσελίδες της Borland, απ'όπου θα κατεβάσετε ένα αρχείο ZIP. Το τμήμα αυτό είναι ήδη μεταγλωττισμένο κι έτοιμο στο Micro1c.OBJ. Αν θελήσετε να το ξαναμεταγλωττίσετε, ακολουθούν οι ρυθμίσεις που χρησιμοποιήσαμε  από τα μενού του Turbo C.

 Options Debug Break/watch
-------------------¬
¦ Compiler ¦
¦ ------------------¬
¦ ¦ Model Small     ¦
¦ ¦ Defines         ¦
¦ ¦ Code generation ¦  <---
¦ ¦ Optimization    ¦  <---
¦ ¦ Source          ¦
| ¦ Errors          ¦
¦ Names    ¦           <---
------------


Code generation
------------------------------¬
¦ Calling convention C        ¦
¦ Instruction set 8088/8086   ¦
¦ Floating point 8087/80287   ¦
¦ Default char type Unsigned  ¦
¦ Alignment Word              ¦
¦ Generate underbars On       ¦
¦ Merge duplicate strings Off ¦
¦ Standard stack frame On     ¦
¦ Test stack overflow Off     ¦
¦ Line numbers On             ¦
¦ OBJ debug information On    ¦
-------------------------------

Optimization
----------------------------¬
¦ Optimize for Speed        ¦
¦ Use register variables On ¦
¦ Register optimization On  ¦
¦ Jump optimization Off     ¦
-----------------------------


Names 
-----------------------------
¦ Code names ¦
¦ -----------------¬
¦ ¦ Segment name * ¦
| ¦ Group name   * ¦
¦ | Class name   * ¦
--------------------

-----------------------------------------------

... Compile ...
----------------------------------¬
-->¦ Compile to OBJ C:MICRO1C.OBJ ¦<<--
   ¦ Make EXE file C:MICRO1C.EXE  ¦
   ¦ Link EXE file                ¦
   ¦ Build all                    ¦
   ¦ Primary C file:              ¦
   ¦ Get info                     ¦
   -------------------------------