Assembly (γλώσσα προγραμματισμού)

Μια γλώσσα συναρμολόγησης είναι μια γλώσσα προγραμματισμού που μπορεί να χρησιμοποιηθεί για να πει απευθείας στον υπολογιστή τι να κάνει. Μια γλώσσα συναρμολόγησης μοιάζει σχεδόν ακριβώς με τον κώδικα μηχανής που μπορεί να καταλάβει ένας υπολογιστής, με τη διαφορά ότι χρησιμοποιεί λέξεις αντί για αριθμούς. Ένας υπολογιστής δεν μπορεί πραγματικά να κατανοήσει άμεσα ένα πρόγραμμα assembly. Ωστόσο, μπορεί εύκολα να μετατρέψει το πρόγραμμα σε κώδικα μηχανής αντικαθιστώντας τις λέξεις του προγράμματος με τους αριθμούς που αντιπροσωπεύουν. Ένα πρόγραμμα που το κάνει αυτό ονομάζεται assembler.

Τα προγράμματα που είναι γραμμένα σε γλώσσα assembly αποτελούνται συνήθως από εντολές, οι οποίες είναι μικρές εργασίες που εκτελεί ο υπολογιστής κατά την εκτέλεση του προγράμματος. Ονομάζονται εντολές επειδή ο προγραμματιστής τις χρησιμοποιεί για να καθοδηγήσει τον υπολογιστή τι να κάνει. Το τμήμα του υπολογιστή που ακολουθεί τις οδηγίες είναι ο επεξεργαστής.

Η γλώσσα συναρμολόγησης ενός υπολογιστή είναι μια γλώσσα χαμηλού επιπέδου, πράγμα που σημαίνει ότι μπορεί να χρησιμοποιηθεί μόνο για την εκτέλεση απλών εργασιών που μπορεί να κατανοήσει άμεσα ένας υπολογιστής. Για να εκτελέσει κανείς πιο σύνθετες εργασίες, πρέπει να πει στον υπολογιστή κάθε μία από τις απλές εργασίες που αποτελούν μέρος της σύνθετης εργασίας. Για παράδειγμα, ένας υπολογιστής δεν καταλαβαίνει πώς να εκτυπώσει μια πρόταση στην οθόνη του. Αντ' αυτού, ένα πρόγραμμα γραμμένο σε assembly πρέπει να του πει πώς να κάνει όλα τα μικρά βήματα που εμπλέκονται στην εκτύπωση της πρότασης.

Ένα τέτοιο πρόγραμμα συναρμολόγησης θα αποτελείται από πολλές, πάρα πολλές εντολές, οι οποίες μαζί κάνουν κάτι που φαίνεται πολύ απλό και βασικό για έναν άνθρωπο. Αυτό καθιστά δύσκολο για τους ανθρώπους να διαβάσουν ένα πρόγραμμα assembly. Αντίθετα, μια γλώσσα προγραμματισμού υψηλού επιπέδου μπορεί να έχει μια μόνο εντολή, όπως η PRINT "Γεια σου, κόσμε!", η οποία θα πει στον υπολογιστή να εκτελέσει όλες τις μικρές εργασίες για εσάς.

Ανάπτυξη της γλώσσας συναρμολόγησης

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

Προγραμματισμός σε κώδικα μηχανής

Για να προγραμματίσει σε κώδικα μηχανής, ο προγραμματιστής πρέπει να γνωρίζει πώς μοιάζει κάθε εντολή σε δυαδικόδεκαεξαδικό) σύστημα. Αν και είναι εύκολο για έναν υπολογιστή να καταλάβει γρήγορα τι σημαίνει ο κώδικας μηχανής, είναι δύσκολο για έναν προγραμματιστή. Κάθε εντολή μπορεί να έχει διάφορες μορφές, οι οποίες στους ανθρώπους μοιάζουν απλώς με ένα μάτσο αριθμούς. Οποιοδήποτε λάθος κάνει κάποιος γράφοντας κώδικα μηχανής θα γίνει αντιληπτό μόνο όταν ο υπολογιστής κάνει το λάθος πράγμα. Η διαπίστωση του λάθους είναι δύσκολη επειδή οι περισσότεροι άνθρωποι δεν μπορούν να καταλάβουν τι σημαίνει ο κώδικας μηχανής κοιτάζοντάς τον. Ένα παράδειγμα του πώς μοιάζει ο κώδικας μηχανής:

05 2A 00

Αυτός ο δεκαεξαδικός μηχανικός κώδικας λέει σε έναν επεξεργαστή υπολογιστή x86 να προσθέσει 42 στον συσσωρευτή. Είναι πολύ δύσκολο για κάποιον να τον διαβάσει και να τον κατανοήσει, ακόμη και αν γνωρίζει κώδικα μηχανής.

Χρήση της γλώσσας συναρμολόγησης αντί

Με τη γλώσσα συναρμολόγησης, κάθε εντολή μπορεί να γραφτεί ως μια σύντομη λέξη, που ονομάζεται μνημονικό, ακολουθούμενη από άλλα πράγματα όπως αριθμούς ή άλλες σύντομες λέξεις. Το μνημονικό χρησιμοποιείται έτσι ώστε ο προγραμματιστής να μην χρειάζεται να θυμάται τους ακριβείς αριθμούς στον κώδικα μηχανής που απαιτούνται για να πει στον υπολογιστή να κάνει κάτι. Παραδείγματα μνημονικών στη γλώσσα assembly περιλαμβάνουν την add, η οποία προσθέτει δεδομένα, και την mov, η οποία μετακινεί δεδομένα από τη μια θέση στην άλλη. Επειδή η λέξη "μνημονικό" είναι μια ασυνήθιστη λέξη, αντί αυτής χρησιμοποιείται μερικές φορές η φράση τύπος εντολής ή απλώς εντολή, συχνά λανθασμένα. Οι λέξεις και οι αριθμοί μετά την πρώτη λέξη δίνουν περισσότερες πληροφορίες σχετικά με το τι πρέπει να γίνει. Για παράδειγμα, τα πράγματα που ακολουθούν μια πρόσθεση μπορεί να είναι ποια δύο πράγματα πρέπει να προστεθούν μαζί και τα πράγματα που ακολουθούν την κίνηση λένε τι πρέπει να μετακινηθεί και πού να τοποθετηθεί.

Για παράδειγμα, ο κώδικας μηχανής της προηγούμενης ενότητας (05 2A 00) μπορεί να γραφτεί σε assembly ως εξής:

 add ax,42

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

Η γλώσσα συναρμολόγησης παρέχει αυτό που ονομάζεται αφαίρεση του κώδικα μηχανής. Όταν χρησιμοποιούν assembly, οι προγραμματιστές δεν χρειάζεται να γνωρίζουν τις λεπτομέρειες του τι σημαίνουν οι αριθμοί για τον υπολογιστή, ο assembler το υπολογίζει αυτό. Η γλώσσα συναρμολόγησης στην πραγματικότητα εξακολουθεί να επιτρέπει στον προγραμματιστή να χρησιμοποιεί όλα τα χαρακτηριστικά του επεξεργαστή που θα μπορούσε να χρησιμοποιήσει με τον κώδικα μηχανής. Υπό αυτή την έννοια, η γλώσσα συναρμολόγησης έχει ένα πολύ καλό, σπάνιο χαρακτηριστικό: έχει την ίδια ικανότητα να εκφράζει πράγματα με αυτό που αφηγείται (κώδικας μηχανής), ενώ είναι πολύ πιο εύκολη στη χρήση. Εξαιτίας αυτού, ο κώδικας μηχανής δεν χρησιμοποιείται σχεδόν ποτέ ως γλώσσα προγραμματισμού.

Αποσυναρμολόγηση και αποσφαλμάτωση

Όταν τα προγράμματα ολοκληρώνονται, έχουν ήδη μετατραπεί σε κώδικα μηχανής, ώστε ο επεξεργαστής να μπορεί να τα εκτελέσει. Μερικές φορές, όμως, αν το πρόγραμμα έχει κάποιο σφάλμα (λάθος), οι προγραμματιστές θέλουν να μπορούν να καταλάβουν τι κάνει κάθε μέρος του κώδικα μηχανής. Οι disassemblers είναι προγράμματα που βοηθούν τους προγραμματιστές να το κάνουν αυτό, μετατρέποντας τον κώδικα μηχανής του προγράμματος πίσω σε γλώσσα assembly, η οποία είναι πολύ πιο κατανοητή. Οι disassemblers, οι οποίοι μετατρέπουν τον κώδικα μηχανής σε γλώσσα assembly, κάνουν το αντίθετο από τους assemblers, οι οποίοι μετατρέπουν τη γλώσσα assembly σε κώδικα μηχανής.

Οργάνωση υπολογιστών

Η κατανόηση του τρόπου οργάνωσης των υπολογιστών, του τρόπου με τον οποίο φαίνεται να λειτουργούν σε πολύ χαμηλό επίπεδο, είναι απαραίτητη για την κατανόηση του τρόπου λειτουργίας ενός προγράμματος σε γλώσσα assembly. Στο πιο απλοϊκό επίπεδο, οι υπολογιστές έχουν τρία βασικά μέρη:

  1. κύρια μνήμη ή RAM που περιέχει δεδομένα και εντολές,
  2. έναν επεξεργαστή, ο οποίος επεξεργάζεται τα δεδομένα εκτελώντας τις εντολές, και
  3. είσοδος και έξοδος (μερικές φορές συντομεύεται ως I/O), που επιτρέπουν στον υπολογιστή να επικοινωνεί με τον έξω κόσμο και να αποθηκεύει δεδομένα εκτός της κύριας μνήμης, ώστε να μπορεί να τα πάρει πίσω αργότερα.

Κύρια μνήμη

Στους περισσότερους υπολογιστές, η μνήμη χωρίζεται σε bytes. Κάθε byte περιέχει 8 bits. Κάθε byte στη μνήμη έχει επίσης μια διεύθυνση, η οποία είναι ένας αριθμός που λέει πού βρίσκεται το byte στη μνήμη. Το πρώτο byte στη μνήμη έχει διεύθυνση 0, το επόμενο έχει διεύθυνση 1 κ.ο.κ. Ο διαχωρισμός της μνήμης σε bytes την καθιστά διευθυνσιοδοτούμενη, επειδή κάθε byte αποκτά μια μοναδική διεύθυνση. Οι διευθύνσεις της μνήμης byte δεν μπορούν να χρησιμοποιηθούν για να αναφερθούν σε ένα μεμονωμένο bit ενός byte. Ένα byte είναι το μικρότερο κομμάτι μνήμης που μπορεί να διευθυνσιοδοτηθεί.

Παρόλο που μια διεύθυνση αναφέρεται σε ένα συγκεκριμένο byte στη μνήμη, οι επεξεργαστές επιτρέπουν τη χρήση πολλών bytes μνήμης στη σειρά. Η πιο συνηθισμένη χρήση αυτής της δυνατότητας είναι η χρήση 2 ή 4 bytes στη σειρά για την αναπαράσταση ενός αριθμού, συνήθως ενός ακέραιου. Μερικές φορές χρησιμοποιούνται και μεμονωμένα bytes για την αναπαράσταση ακεραίων αριθμών, αλλά επειδή έχουν μήκος μόνο 8 bit, μπορούν να χωρέσουν μόνο 2 8ή 256 διαφορετικές πιθανές τιμές. Η χρήση 2 ή 4 bytes σε μια σειρά αυξάνει τον αριθμό των διαφορετικών πιθανών τιμών σε 2 16, 65536 ή 2 32, 4294967296, αντίστοιχα.

Όταν ένα πρόγραμμα χρησιμοποιεί ένα byte ή έναν αριθμό bytes σε μια σειρά για να αναπαραστήσει κάτι όπως ένα γράμμα, έναν αριθμό ή οτιδήποτε άλλο, αυτά τα bytes ονομάζονται αντικείμενο επειδή είναι όλα μέρος του ίδιου πράγματος. Παρόλο που όλα τα αντικείμενα αποθηκεύονται σε πανομοιότυπα bytes της μνήμης, αντιμετωπίζονται σαν να έχουν έναν "τύπο", ο οποίος λέει πώς πρέπει να κατανοηθούν τα bytes: είτε ως ακέραιος αριθμός είτε ως χαρακτήρας είτε ως κάποιος άλλος τύπος (όπως μια μη ακέραια τιμή). Ο κώδικας μηχανής μπορεί επίσης να θεωρηθεί ως ένας τύπος που ερμηνεύεται ως εντολές. Η έννοια του τύπου είναι πολύ, πολύ σημαντική, επειδή ορίζει τι πράγματα μπορούν και τι δεν μπορούν να γίνουν στο αντικείμενο και πώς να ερμηνεύονται τα bytes του αντικειμένου. Για παράδειγμα, δεν είναι έγκυρο να αποθηκεύσετε έναν αρνητικό αριθμό σε ένα αντικείμενο θετικού αριθμού και δεν είναι έγκυρο να αποθηκεύσετε ένα κλάσμα σε έναν ακέραιο.

Μια διεύθυνση που δείχνει (είναι η διεύθυνση ενός αντικειμένου πολλών byte) είναι η διεύθυνση του πρώτου byte του αντικειμένου αυτού - το byte που έχει τη χαμηλότερη διεύθυνση. Παρεμπιπτόντως, ένα σημαντικό πράγμα που πρέπει να σημειωθεί είναι ότι δεν μπορείτε να πείτε ποιος είναι ο τύπος ενός αντικειμένου - ή ακόμη και το μέγεθός του - από τη διεύθυνσή του. Για την ακρίβεια, δεν μπορείτε καν να καταλάβετε τον τύπο ενός αντικειμένου κοιτάζοντάς το. Ένα πρόγραμμα σε γλώσσα assembly πρέπει να παρακολουθεί ποιες διευθύνσεις μνήμης περιέχουν ποια αντικείμενα και πόσο μεγάλα είναι αυτά τα αντικείμενα. Ένα πρόγραμμα που το κάνει αυτό είναι ασφαλές ως προς τον τύπο, επειδή κάνει μόνο πράγματα στα αντικείμενα που είναι ασφαλές να γίνουν με βάση τον τύπο τους. Ένα πρόγραμμα που δεν το κάνει, πιθανόν να μην λειτουργεί σωστά. Σημειώστε ότι τα περισσότερα προγράμματα στην πραγματικότητα δεν αποθηκεύουν ρητά ποιος είναι ο τύπος ενός αντικειμένου, απλώς προσπελαύνουν τα αντικείμενα με συνέπεια - το ίδιο αντικείμενο αντιμετωπίζεται πάντα ως ο ίδιος τύπος.

Ο επεξεργαστής

Ο επεξεργαστής εκτελεί (εκτελεί) εντολές, οι οποίες είναι αποθηκευμένες ως κώδικας μηχανής στην κύρια μνήμη. Εκτός από τη δυνατότητα πρόσβασης στη μνήμη για αποθήκευση, οι περισσότεροι επεξεργαστές διαθέτουν μερικούς μικρούς, γρήγορους και σταθερού μεγέθους χώρους για την αποθήκευση των αντικειμένων με τα οποία εργάζονται επί του παρόντος. Αυτοί οι χώροι ονομάζονται καταχωρητές. Οι επεξεργαστές εκτελούν συνήθως τρεις τύπους εντολών, αν και ορισμένες εντολές μπορεί να είναι συνδυασμός αυτών των τύπων. Παρακάτω παρατίθενται μερικά παραδείγματα κάθε τύπου σε γλώσσα συναρμολόγησης x86.

Εντολές που διαβάζουν ή γράφουν μνήμη

Η ακόλουθη εντολή της γλώσσας συναρμολόγησης x86 διαβάζει (φορτώνει) ένα αντικείμενο 2 byte από το byte στη διεύθυνση 4096 (0x1000 σε δεκαεξαδικό σύστημα) σε έναν καταχωρητή 16 bit που ονομάζεται 'ax':

        mov ax, [1000h]

Σε αυτή τη γλώσσα συναρμολόγησης, οι αγκύλες γύρω από έναν αριθμό (ή ένα όνομα καταχωρητή) σημαίνουν ότι ο αριθμός πρέπει να χρησιμοποιηθεί ως διεύθυνση για τα δεδομένα που πρέπει να χρησιμοποιηθούν. Η χρήση μιας διεύθυνσης για να δείξει σε δεδομένα ονομάζεται ανακατεύθυνση. Σε αυτό το επόμενο παράδειγμα, χωρίς τις αγκύλες, ένας άλλος καταχωρητής, ο bx, παίρνει στην πραγματικότητα την τιμή 20 που φορτώνεται σε αυτόν.

        mov bx, 20

Επειδή δεν χρησιμοποιήθηκε καμία παρέκβαση, η ίδια η πραγματική τιμή τοποθετήθηκε στον καταχωρητή.

Εάν οι τελεστές (τα πράγματα που ακολουθούν το μνημονικό) εμφανίζονται με αντίστροφη σειρά, μια εντολή που φορτώνει κάτι από τη μνήμη αντί να το γράφει στη μνήμη:

        mov [1000h], ax

Εδώ, η μνήμη στη διεύθυνση 1000h λαμβάνει την τιμή ax. Αν αυτό το παράδειγμα εκτελεστεί αμέσως μετά το προηγούμενο, τα 2 bytes στις 1000h και 1001h θα είναι ένας ακέραιος αριθμός 2 bytes με την τιμή 20.

Εντολές που εκτελούν μαθηματικές ή λογικές πράξεις

Ορισμένες εντολές κάνουν πράγματα όπως η αφαίρεση ή λογικές πράξεις όπως το not:

Το παράδειγμα του κώδικα μηχανής νωρίτερα σε αυτό το άρθρο θα ήταν αυτό σε γλώσσα assembly:

        προσθέστε ax, 42

Εδώ, τα 42 και ax αθροίζονται και το αποτέλεσμα αποθηκεύεται στο ax. Στη συναρμολόγηση x86 είναι επίσης δυνατό να συνδυάσετε μια προσπέλαση μνήμης και μια μαθηματική πράξη όπως αυτή:

        add ax, [1000h]

Αυτή η εντολή προσθέτει την τιμή του ακέραιου αριθμού 2 byte που είναι αποθηκευμένος στο 1000h στο ax και αποθηκεύει την απάντηση στο ax.

        ή ax, bx

Αυτή η εντολή υπολογίζει το ή των περιεχομένων των καταχωρητών ax και bx και αποθηκεύει το αποτέλεσμα πίσω στον ax.

Εντολές που αποφασίζουν ποια θα είναι η επόμενη εντολή

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

Σε αυτό το παράδειγμα, ας υποθέσουμε ότι κάποιος θέλει να υπολογίσει την ποσότητα μπογιάς που θα χρειαστεί για να βάψει ένα τετράγωνο με συγκεκριμένο μήκος πλευράς. Ωστόσο, λόγω της οικονομίας κλίμακας, το χρωματοπωλείο δεν θα του πουλήσει λιγότερη ποσότητα χρώματος από την ποσότητα χρώματος που χρειάζεται για να βάψει ένα τετράγωνο 100 x 100.

Για να υπολογίσουν την ποσότητα χρώματος που θα χρειαστούν με βάση το μήκος του τετραγώνου που θέλουν να βάψουν, καταλήγουν σε αυτό το σύνολο βημάτων:

  • αφαιρέστε 100 από το μήκος της πλευράς
  • αν η απάντηση είναι μικρότερη του μηδενός, θέστε το μήκος της πλευράς σε 100
  • πολλαπλασιάστε το μήκος της πλευράς με τον εαυτό του

Αυτός ο αλγόριθμος μπορεί να εκφραστεί με τον ακόλουθο κώδικα όπου ax είναι το μήκος της πλευράς.

        mov bx, ax     sub bx, 100    jge continue   mov ax, 100 continue: mul ax

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

Ένα από τα νέα πράγματα σε αυτό το παράδειγμα ονομάζεται ετικέτα (label), μια έννοια που συναντάται στις γλώσσες συναρμολόγησης γενικά. Οι ετικέτες μπορούν να είναι οτιδήποτε θέλει ο προγραμματιστής (εκτός αν είναι το όνομα μιας εντολής, το οποίο θα προκαλούσε σύγχυση στον assembler). Σε αυτό το παράδειγμα, η ετικέτα είναι 'continue'. Ερμηνεύεται από τον assembler ως η διεύθυνση μιας εντολής. Σε αυτή την περίπτωση, είναι η διεύθυνση της mult ax.

Μια άλλη νέα έννοια είναι αυτή των σημαιών. Στους επεξεργαστές x86, πολλές εντολές θέτουν "σημαίες" στον επεξεργαστή, οι οποίες μπορούν να χρησιμοποιηθούν από την επόμενη εντολή για να αποφασιστεί τι θα γίνει. Σε αυτή την περίπτωση, αν το bx ήταν μικρότερο από 100, η sub θα θέσει μια σημαία που λέει ότι το αποτέλεσμα ήταν μικρότερο από μηδέν.

Η επόμενη εντολή είναι η jge, η οποία είναι συντομογραφία για το 'Jump if Greater than or Equal to'. Πρόκειται για εντολή διακλάδωσης. Εάν οι σημαίες στον επεξεργαστή καθορίζουν ότι το αποτέλεσμα ήταν μεγαλύτερο ή ίσο του μηδενός, αντί να μεταβεί απλώς στην επόμενη εντολή, ο επεξεργαστής θα μεταβεί στην εντολή στην ετικέτα continue, η οποία είναι mul ax.

Αυτό το παράδειγμα λειτουργεί μια χαρά, αλλά δεν είναι αυτό που θα έγραφαν οι περισσότεροι προγραμματιστές. Η εντολή αφαίρεσης έθεσε σωστά τη σημαία, αλλά αλλάζει επίσης την τιμή στην οποία λειτουργεί, πράγμα που απαιτούσε την αντιγραφή του ax στο bx. Οι περισσότερες γλώσσες συναρμολόγησης επιτρέπουν εντολές σύγκρισης που δεν αλλάζουν κανένα από τα ορίσματα που περνούν, αλλά εξακολουθούν να θέτουν σωστά τις σημαίες και η συναρμολόγηση x86 δεν αποτελεί εξαίρεση.

        cmp ax, 100    jge continue   mov ax, 100 continue: mul ax

Τώρα, αντί να αφαιρέσουμε το 100 από το ax, να δούμε αν ο αριθμός αυτός είναι μικρότερος από το μηδέν και να τον αναθέσουμε πίσω στο ax, το ax παραμένει αμετάβλητο. Οι σημαίες εξακολουθούν να τίθενται με τον ίδιο τρόπο και το άλμα εξακολουθεί να πραγματοποιείται στις ίδιες καταστάσεις.

Είσοδος και έξοδος

Ενώ η είσοδος και η έξοδος αποτελούν θεμελιώδες μέρος της πληροφορικής, δεν υπάρχει ένας μόνο τρόπος για να γίνουν στη γλώσσα assembly. Αυτό οφείλεται στο γεγονός ότι ο τρόπος λειτουργίας των εισόδων/εξόδων εξαρτάται από τη ρύθμιση του υπολογιστή και το λειτουργικό σύστημα που τρέχει, και όχι μόνο από το είδος του επεξεργαστή που διαθέτει. Στην ενότητα των παραδειγμάτων το παράδειγμα Hello World χρησιμοποιεί κλήσεις του λειτουργικού συστήματος MS-DOS και το παράδειγμα μετά από αυτό χρησιμοποιεί κλήσεις του BIOS.

Είναι δυνατή η εκτέλεση εισόδου/εξόδου σε γλώσσα συναρμολόγησης. Πράγματι, η γλώσσα assembly μπορεί γενικά να εκφράσει οτιδήποτε μπορεί να κάνει ένας υπολογιστής. Ωστόσο, παρόλο που υπάρχουν εντολές πρόσθεσης και διακλάδωσης στη γλώσσα assembly που θα κάνουν πάντα το ίδιο πράγμα, δεν υπάρχουν εντολές στη γλώσσα assembly που να κάνουν πάντα I/O.

Το σημαντικό πράγμα που πρέπει να σημειωθεί είναι ότι ο τρόπος με τον οποίο λειτουργεί το I/O δεν αποτελεί μέρος οποιασδήποτε γλώσσας συναρμολόγησης, επειδή δεν αποτελεί μέρος του τρόπου με τον οποίο λειτουργεί ο επεξεργαστής.

Γλώσσες συναρμολόγησης και φορητότητα

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

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

Γλώσσα συναρμολόγησης και γλώσσες υψηλού επιπέδου

Αν και η γλώσσα assembly επιτρέπει έναν εύκολο τρόπο χρήσης όλων των δυνατοτήτων του επεξεργαστή, δεν χρησιμοποιείται για σύγχρονα έργα λογισμικού για διάφορους λόγους:

  • Χρειάζεται μεγάλη προσπάθεια για να εκφράσετε ένα απλό πρόγραμμα σε assembly.
  • Αν και δεν είναι τόσο επιρρεπής σε σφάλματα όσο ο κώδικας μηχανής, η γλώσσα συναρμολόγησης εξακολουθεί να προσφέρει πολύ μικρή προστασία από σφάλματα. Σχεδόν όλες οι γλώσσες συναρμολόγησης δεν επιβάλλουν ασφάλεια τύπου.
  • Η γλώσσα συναρμολόγησης δεν προωθεί καλές πρακτικές προγραμματισμού όπως η αρθρωτότητα.
  • Αν και κάθε μεμονωμένη εντολή της γλώσσας assembly είναι εύκολα κατανοητή, είναι δύσκολο να καταλάβει κανείς ποια ήταν η πρόθεση του προγραμματιστή που την έγραψε. Στην πραγματικότητα, η γλώσσα συναρμολόγησης ενός προγράμματος είναι τόσο δύσκολο να κατανοηθεί, ώστε οι εταιρείες δεν ανησυχούν για το αν οι άνθρωποι αποσυναρμολογούν (παίρνουν τη γλώσσα συναρμολόγησης) τα προγράμματά τους.

Ως αποτέλεσμα αυτών των μειονεκτημάτων, οι γλώσσες υψηλού επιπέδου όπως η Pascal, η C και η C++ χρησιμοποιούνται για τα περισσότερα έργα. Επιτρέπουν στους προγραμματιστές να εκφράζουν τις ιδέες τους πιο άμεσα, αντί να χρειάζεται να ανησυχούν για το πώς να λένε στον επεξεργαστή τι να κάνει σε κάθε βήμα. Ονομάζονται υψηλού επιπέδου επειδή οι ιδέες που μπορεί να εκφράσει ο προγραμματιστής με την ίδια ποσότητα κώδικα είναι πιο περίπλοκες.

Οι προγραμματιστές που γράφουν κώδικα σε μεταγλωττισμένες γλώσσες υψηλού επιπέδου χρησιμοποιούν ένα πρόγραμμα που ονομάζεται μεταγλωττιστής για να μετατρέψουν τον κώδικά τους σε γλώσσα assembly. Οι μεταγλωττιστές είναι πολύ πιο δύσκολο να γραφούν από ό,τι οι μεταγλωττιστές συναρμολόγησης. Επίσης, οι γλώσσες υψηλού επιπέδου δεν επιτρέπουν πάντα στους προγραμματιστές να χρησιμοποιούν όλα τα χαρακτηριστικά του επεξεργαστή. Αυτό συμβαίνει επειδή οι γλώσσες υψηλού επιπέδου έχουν σχεδιαστεί για να υποστηρίζουν όλες τις οικογένειες επεξεργαστών. Σε αντίθεση με τις γλώσσες συναρμολόγησης, που υποστηρίζουν μόνο έναν τύπο επεξεργαστή, οι γλώσσες υψηλού επιπέδου είναι φορητές.

Παρόλο που οι μεταγλωττιστές είναι πιο περίπλοκοι από τους assemblers, δεκαετίες κατασκευής και έρευνας των μεταγλωττιστών τους έχουν καταστήσει πολύ καλούς. Τώρα, δεν υπάρχει πλέον ιδιαίτερος λόγος να χρησιμοποιείται η γλώσσα assembly για τα περισσότερα προγράμματα, επειδή οι μεταγλωττιστές μπορούν συνήθως να καταλάβουν πώς να εκφράζουν προγράμματα σε γλώσσα assembly εξίσου καλά ή και καλύτερα από τους προγραμματιστές.

Παράδειγμα προγραμμάτων

Ένα πρόγραμμα Hello World γραμμένο σε x86 Assembly:

adosseg .model small .stack 100h .data hello_message db 'Hello, World! ',0dh,0ah,'$' .code main proc mov ax,@data mov ds,ax mov ah,9 mov dx,offset hello_message int 21h mov ax,4C00h int 21h main endp end main

Μια συνάρτηση που εκτυπώνει έναν αριθμό στην οθόνη χρησιμοποιώντας διακοπές BIOS γραμμένες σε συναρμολόγηση NASM x86. Ο αρθρωτός κώδικας είναι δυνατόν να γραφτεί σε assembly, αλλά χρειάζεται επιπλέον προσπάθεια. Σημειώστε ότι οτιδήποτε έρχεται μετά από μια άνω τελεία σε μια γραμμή είναι σχόλιο και αγνοείται από τον assembler. Η τοποθέτηση σχολίων στον κώδικα σε γλώσσα assembly είναι πολύ σημαντική επειδή τα μεγάλα προγράμματα σε γλώσσα assembly είναι τόσο δύσκολο να κατανοηθούν.

; void printn(int number, int base); printn:         bp      mov     bp, sp push    ax         push    bx      push    cx      push    dx      push    si      mov     si, 0   mov        ax, [bp + 4]   ; αριθμός      mov     cx, [bp + 6]   ; base gloop:  inc     si               ; μήκος της συμβολοσειράς      mov     dx, 0          ; μηδέν dx     div        cx             ; διαίρεση με τη βάση cmp     dx, 10         ; είναι ge 10; jge        num     add     dx, '0'        ; προσθέστε μηδέν στο dx       jmp     anum num:        add     dx, ('A'- 10)  ; δεκαεξαδική τιμή, προσθέστε 'A' στο dx - 10. anum:  push        dx             ; βάλτε το dx στη στοίβα.      cmp     ax, 0          ; πρέπει να συνεχίσουμε;   κλπ     gloop  mov     bx, 7h         ; για διακοπή tloop:   pop     ax               ; πάρτε την τιμή του   mov     ah, 0eh        ; για διακοπή int     10h               ; γράψτε χαρακτήρα     dec     si             ; ξεφορτώσου τον χαρακτήρα         jnz     tloop  pop     si      pop     dx      pop     cx      pop     bx      pop        ax      pop     bp      ret    

Ερωτήσεις και απαντήσεις

Ερ: Τι είναι μια γλώσσα συναρμολόγησης;


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

Ε: Πώς καταλαβαίνει ένας υπολογιστής ένα πρόγραμμα assembly;


Α: Ένας υπολογιστής δεν μπορεί πραγματικά να κατανοήσει άμεσα ένα πρόγραμμα assembly, αλλά μπορεί εύκολα να μετατρέψει το πρόγραμμα σε κώδικα μηχανής αντικαθιστώντας τις λέξεις του προγράμματος με τους αριθμούς που αντιπροσωπεύουν. Η διαδικασία αυτή γίνεται με τη χρήση ενός assembler.

Ερ: Τι είναι οι εντολές σε μια γλώσσα συναρμολόγησης;


Α: Οι εντολές σε μια γλώσσα συναρμολόγησης είναι μικρές εργασίες που εκτελεί ο υπολογιστής όταν εκτελεί το πρόγραμμα. Ονομάζονται οδηγίες επειδή καθοδηγούν τον υπολογιστή τι να κάνει. Το τμήμα του υπολογιστή που είναι υπεύθυνο για την εκτέλεση αυτών των οδηγιών ονομάζεται επεξεργαστής.

Ερ: Τι είδους γλώσσα προγραμματισμού είναι η assembly;


Α: Η γλώσσα συναρμολόγησης είναι μια γλώσσα προγραμματισμού χαμηλού επιπέδου, πράγμα που σημαίνει ότι μπορεί να χρησιμοποιηθεί μόνο για την εκτέλεση απλών εργασιών τις οποίες ο υπολογιστής μπορεί να κατανοήσει άμεσα. Για να εκτελέσει κανείς πιο σύνθετες εργασίες, πρέπει να αναλύσει κάθε εργασία στα επιμέρους συστατικά της και να δώσει οδηγίες για κάθε συστατικό ξεχωριστά.

Ερ: Σε τι διαφέρει αυτό από τις γλώσσες υψηλού επιπέδου;


Α: Οι γλώσσες υψηλού επιπέδου μπορούν να έχουν μεμονωμένες εντολές όπως η PRINT "Hello, world!" η οποία θα πει στον υπολογιστή να εκτελέσει όλες αυτές τις μικρές εργασίες αυτόματα χωρίς να χρειάζεται να τις προσδιορίσετε ξεχωριστά όπως θα έπρεπε να κάνετε με ένα πρόγραμμα assembly. Αυτό κάνει τις γλώσσες υψηλού επιπέδου πιο εύκολες στην ανάγνωση και κατανόηση από τον άνθρωπο σε σχέση με τα προγράμματα assembly που αποτελούνται από πολλές μεμονωμένες εντολές.

Ερ: Γιατί μπορεί να είναι δύσκολο για τους ανθρώπους να διαβάσουν ένα πρόγραμμα συναρμολόγησης;


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

AlegsaOnline.com - 2020 / 2023 - License CC3