Οδηγίες βραχίονα. Μελέτη του συνόλου εντολών επεξεργαστή ARM. Εκτέλεση εντολής υπό όρους

Γεια σε όλους!
Είμαι προγραμματιστής Java στο επάγγελμα. Οι τελευταίοι μήνες εργασίας με ανάγκασαν να εξοικειωθώ με την ανάπτυξη για το Android NDK και, κατά συνέπεια, να γράφω εγγενείς εφαρμογές σε C. Στη συνέχεια αντιμετώπισα το πρόβλημα της βελτιστοποίησης των βιβλιοθηκών Linux. Πολλοί αποδείχτηκαν ότι δεν ήταν απολύτως βελτιστοποιημένοι για ARM και φόρτωσαν πολύ τον επεξεργαστή. Προηγουμένως, πρακτικά δεν προγραμμάτιζα στη γλώσσα assembly, οπότε στην αρχή ήταν δύσκολο να ξεκινήσω να μαθαίνω αυτήν τη γλώσσα, αλλά παρόλα αυτά αποφάσισα να τη δοκιμάσω. Αυτό το άρθρο είναι γραμμένο, θα λέγαμε, από αρχάριους έως αρχάριους. Θα προσπαθήσω να περιγράψω τα βασικά που έχω ήδη μάθει, ελπίζω ότι κάποιος θα ενδιαφέρεται για αυτό. Επιπλέον, θα χαιρόμουν να δεχτώ εποικοδομητική κριτική από επαγγελματίες.

Εισαγωγή
Λοιπόν, πρώτα, ας καταλάβουμε τι είναι το ARM. Η Wikipedia δίνει αυτόν τον ορισμό:

Η αρχιτεκτονική ARM (Advanced RISC Machine, Acorn RISC Machine, advanced RISC machine) είναι μια οικογένεια αδειοδοτημένων πυρήνων μικροεπεξεργαστή 32-bit και 64-bit που αναπτύχθηκε από την ARM Limited. Η εταιρεία ασχολείται αποκλειστικά με την ανάπτυξη πυρήνων και εργαλείων για αυτούς (μεταγλωττιστές, εργαλεία εντοπισμού σφαλμάτων κ.λπ.), κερδίζοντας χρήματα από την αδειοδότηση της αρχιτεκτονικής σε τρίτους κατασκευαστές.

Αν κάποιος δεν ξέρει, τώρα οι περισσότερες φορητές συσκευές, ταμπλέτες αναπτύσσονται ακριβώς σε αυτήν την αρχιτεκτονική επεξεργαστή. Το κύριο πλεονέκτημα αυτής της οικογένειας είναι η χαμηλή κατανάλωση ενέργειας, γεγονός που την κάνει να χρησιμοποιείται συχνά σε διάφορα ενσωματωμένα συστήματα. Η αρχιτεκτονική έχει εξελιχθεί με την πάροδο του χρόνου και από το ARMv7 έχουν οριστεί 3 προφίλ: «A» (εφαρμογή) για εφαρμογές, «R» (σε πραγματικό χρόνο) για πραγματικό χρόνο, «M» (μικροελεγκτής) για έναν μικροελεγκτή. Μπορείτε να διαβάσετε την ιστορία της ανάπτυξης αυτής της τεχνολογίας και άλλα ενδιαφέροντα δεδομένα στη Wikipedia ή κάνοντας google στο Διαδίκτυο. Το ARM υποστηρίζει διαφορετικούς τρόπους λειτουργίας (Thumb και ARM, επιπλέον, πρόσφατα εμφανίστηκε το Thumb-2, το οποίο είναι ένα μείγμα ARM και Thumb). Σε αυτό το άρθρο, θα εξετάσουμε την πραγματική λειτουργία ARM, στην οποία εκτελείται το σύνολο εντολών 32-bit.

Κάθε επεξεργαστής ARM είναι κατασκευασμένος από τα ακόλουθα μπλοκ:

  • 37 μητρώα (από τα οποία μόνο 17 είναι ορατά κατά την ανάπτυξη)
  • Αριθμητική-λογική μονάδα (ALU) - εκτελεί αριθμητικές και λογικές εργασίες
  • Barrel shifter - μια συσκευή σχεδιασμένη να μετακινεί μπλοκ δεδομένων κατά συγκεκριμένο αριθμό bit
  • Το CP15 είναι ένα ειδικό σύστημα που ελέγχει τους συνεπεξεργαστές ARM
  • Αποκωδικοποιητής εντολών - ασχολείται με τη μετατροπή μιας εντολής σε μια ακολουθία μικρο-λειτουργιών
Αυτά δεν είναι όλα μέρη του ARM, αλλά η εμβάθυνση στη ζούγκλα των επεξεργαστών κτιρίων δεν εμπίπτει στο πεδίο εφαρμογής αυτού του άρθρου.
Εκτέλεση αγωγού
Οι επεξεργαστές ARM χρησιμοποιούν αγωγό 3 σταδίων (από το ARM8, έχει υλοποιηθεί ένας αγωγός 5 σταδίων). Ας δούμε έναν απλό αγωγό χρησιμοποιώντας τον επεξεργαστή ARM7TDMI ως παράδειγμα. Η εκτέλεση κάθε εντολής αποτελείται από τρία βήματα:

1. Στάδιο δειγματοληψίας (F)
Σε αυτό το σημείο, οι οδηγίες ρέουν από τη μνήμη RAM στον αγωγό του επεξεργαστή.
2. Στάδιο αποκωδικοποίησης (D)
Οι οδηγίες αποκωδικοποιούνται και αναγνωρίζεται ο τύπος τους.
3. Στάδιο εκτέλεσης (Ε)
Τα δεδομένα εισάγονται στο ALU και εκτελούνται και η τιμή που προκύπτει εγγράφεται στον καθορισμένο καταχωρητή.

Αλλά κατά την ανάπτυξη, πρέπει να ληφθεί υπόψη ότι υπάρχουν οδηγίες που χρησιμοποιούν διάφορους κύκλους εκτέλεσης, για παράδειγμα, φόρτωση (LDR) ή αποθήκευση. Σε αυτήν την περίπτωση, το στάδιο εκτέλεσης (Ε) χωρίζεται σε στάδια (Ε1, Ε2, Ε3 ...).

Εκτέλεση υπό όρους
Μία από τις πιο σημαντικές λειτουργίες του assembler ARM είναι η εκτέλεση υπό όρους. Κάθε εντολή μπορεί να εκτελεστεί υπό όρους και για αυτό χρησιμοποιούνται επιθήματα. Εάν προστεθεί ένα επίθημα στο όνομα της εντολής, οι παράμετροι ελέγχονται πριν από την εκτέλεσή της. Εάν οι παράμετροι δεν ταιριάζουν με τη συνθήκη, τότε η εντολή δεν εκτελείται. Επιθήματα:
MI - αρνητικός αριθμός
PL - θετικό ή μηδέν
AL - εκτελείτε πάντα την εντολή
Υπάρχουν πολλά ακόμη επιθήματα υπό όρους. Διαβάστε τα υπόλοιπα επιθέματα και παραδείγματα στην επίσημη τεκμηρίωση: Τεκμηρίωση ARM
Τώρα ήρθε η ώρα να σκεφτούμε…
Βασικά στοιχεία σύνταξης ARM assembler
Για όσους έχουν εργαστεί με το assembler στο παρελθόν, αυτό το σημείο μπορεί πραγματικά να παραλειφθεί. Για όλους τους άλλους, θα περιγράψω τα βασικά της εργασίας με αυτήν τη γλώσσα. Έτσι, κάθε πρόγραμμα γλώσσας assembly αποτελείται από οδηγίες. Η οδηγία δημιουργείται με αυτόν τον τρόπο:
(ετικέτα) (οδηγία | τελεστές) (@ σχόλιο)
Η ετικέτα είναι μια προαιρετική παράμετρος. Μια εντολή είναι άμεσα μια μνημονική μιας εντολής σε έναν επεξεργαστή. Οι βασικές οδηγίες και η χρήση τους θα συζητηθούν αργότερα. Τελεστές - σταθερές, καταχωρήσεις διευθύνσεων, διευθύνσεις στη μνήμη RAM. Το σχόλιο είναι μια προαιρετική παράμετρος που δεν επηρεάζει την εκτέλεση του προγράμματος.
Καταχωρίστε ονόματα
Επιτρέπονται τα ακόλουθα ονόματα μητρώων:
1.r0-r15

3.v1-v8 (μεταβλητοί καταχωρητές, r4 έως r11)

4.sb και SB (στατικός καταχωρητής, r9)

5.sl και SL (r10)

6.fp και FP (r11)

7.ip και IP (r12)

8.sp και SP (r13)

9.lr και LR (r14)

10.pc και Η/Υ (μετρητής προγράμματος, r15).

Μεταβλητές και σταθερές
Στο assembler ARM, όπως και σε οποιαδήποτε άλλη (πρακτικά) άλλη γλώσσα προγραμματισμού, μπορούν να χρησιμοποιηθούν μεταβλητές και σταθερές. Χωρίζονται στους εξής τύπους:
  • Αριθμητικός
  • σπαζοκεφαλιά
  • Σειρά
Οι αριθμητικές μεταβλητές αρχικοποιούνται ως εξής:
ένα SETA 100? δημιουργείται μια αριθμητική μεταβλητή "a" με τιμή 100.
Μεταβλητές συμβολοσειράς:
improb ΣΕΤ "κυριολεκτικά"? δημιουργείται μια μεταβλητή improb με την τιμή "literal". ΠΡΟΣΟΧΗ! Η τιμή της μεταβλητής δεν μπορεί να υπερβαίνει τους 5120 χαρακτήρες.
Οι μεταβλητές Boolean χρησιμοποιούν τις τιμές TRUE και FALSE, αντίστοιχα.
Παραδείγματα οδηγιών συναρμολόγησης ARM
Σε αυτόν τον πίνακα, έχω συγκεντρώσει τις βασικές οδηγίες που θα απαιτηθούν για περαιτέρω ανάπτυξη (στο πιο βασικό στάδιο :):

Για να στερεοποιήσουμε τη χρήση των βασικών οδηγιών, ας γράψουμε μερικά απλά παραδείγματα, αλλά πρώτα χρειαζόμαστε την αλυσίδα εργαλείων του βραχίονα. Δουλεύω σε Linux και έτσι επέλεξα: frank.harvard.edu/~coldwell/toolchain (arm-unknown-linux-gnu toolchain). Εγκαθίσταται τόσο εύκολα όσο το ξεφλούδισμα των αχλαδιών, όπως κάθε άλλο πρόγραμμα Linux. Στην περίπτωσή μου (ρωσικό Fedora) χρειάστηκα μόνο να εγκαταστήσω τα πακέτα rpm από τον ιστότοπο.
Τώρα ήρθε η ώρα να γράψουμε το πιο απλό παράδειγμα. Το πρόγραμμα θα είναι εντελώς άχρηστο, αλλά το κύριο πράγμα είναι ότι θα λειτουργήσει :) Εδώ είναι ο κώδικας που σας προσφέρω:
start: @ Προαιρετική γραμμή που δείχνει την αρχή του προγράμματος mov r0, # 3 @ Φορτώστε την τιμή 3 στον καταχωρητή r0 mov r1, # 2 @ Κάντε το ίδιο με τον καταχωρητή r1, μόνο τώρα με την τιμή 2 προσθέστε r2, r1, r0 @ Προσθέστε τις τιμές των r0 και r1, γράψτε την απάντηση σε r2 mul r3, r1, r0 @ Πολλαπλασιάστε την τιμή του καταχωρητή r1 με την τιμή του καταχωρητή r0, γράψτε την απάντηση στο r3 stop: b stop @ Line του τερματισμού του προγράμματος
Μεταγλωττίστε το πρόγραμμα για να λάβετε το αρχείο .bin:
/ usr / arm / bin / arm-unknown-linux-gnu-as -o arm.o arm.s / usr / arm / bin / arm-unknown-linux-gnu-ld -Ttext = 0x0 -o ​​·arm. elf arm .o / usr / arm / bin / arm-unknown-linux-gnu-objcopy -O binary arm.elf arm.bin
(ο κώδικας βρίσκεται στο αρχείο arm.s και η αλυσίδα εργαλείων στην περίπτωσή μου βρίσκεται στον κατάλογο / usr / arm / bin /)
Εάν όλα πήγαν καλά, θα έχετε 3 αρχεία: arm.s (ο πραγματικός κωδικός), arm.o, arm.elf, arm.bin (το πραγματικό εκτελέσιμο πρόγραμμα). Για να ελέγξετε τη λειτουργία του προγράμματος, δεν είναι απαραίτητο να έχετε τη δική σας συσκευή βραχίονα. Αρκεί να εγκαταστήσετε το QEMU. Για αναφορά:

Το QEMU είναι ένα δωρεάν και ανοιχτού κώδικα λογισμικό εξομοίωσης υλικού για διάφορες πλατφόρμες.

Περιλαμβάνει εξομοίωση επεξεργαστών Intel x86 και συσκευών I/O. Μπορεί να μιμηθεί επεξεργαστές 80386, 80486, Pentium, Pentium Pro, AMD64 και άλλους συμβατούς με x86. PowerPC, ARM, MIPS, SPARC, SPARC64, m68k - μόνο εν μέρει.

Λειτουργεί σε Syllable, FreeBSD, FreeDOS, Linux, Windows 9x, Windows 2000, Mac OS X, QNX, Android και πολλά άλλα.

Έτσι, για να μιμηθείς βραχίονα, χρειάζεσαι qemu-system-arm. Αυτό το πακέτο είναι άψογο, οπότε για όσους έχουν το Fedora, δεν χρειάζεται να ασχοληθείτε και απλώς εκτελέστε την εντολή:
yum εγκατάσταση qemu-system-arm

Στη συνέχεια, πρέπει να ξεκινήσετε τον εξομοιωτή ARM, ώστε να εκτελέσει το πρόγραμμα arm.bin. Για να γίνει αυτό, θα δημιουργήσουμε ένα αρχείο flash.bin, το οποίο θα είναι η μνήμη flash για το QEMU. Είναι πολύ εύκολο να το κάνετε αυτό:
dd if = / dev / zero of = flash.bin bs = 4096 count = 4096 dd if = arm.bin of = flash.bin bs = 4096 conv = notrunc
Τώρα φορτώνουμε το QEMU με τη λαμβανόμενη μνήμη flash:
qemu-system-arm -M connex -pflash flash.bin -nographic -serial / dev / null
Θα λάβετε κάτι σαν αυτό στην έξοδο:

$ qemu-system-arm -M connex -pflash flash.bin -nographic -serial / dev / null
Οθόνη QEMU 0.15.1 - πληκτρολογήστε "help" για περισσότερες πληροφορίες
(qemu)

Το πρόγραμμα arm.bin έπρεπε να αλλάξει τις τιμές τεσσάρων καταχωρητών, επομένως, για να ελέγξουμε την ορθότητα της εργασίας, ας δούμε αυτούς τους ίδιους τους καταχωρητές. Αυτό γίνεται με μια πολύ απλή εντολή: info registers
Στην έξοδο θα δείτε και τους 15 καταχωρητές ARM, με τέσσερις από αυτούς να έχουν αλλάξει τιμές. Ελέγξτε :) Οι τιμές των καταχωρητών συμπίπτουν με αυτές που μπορούν να αναμένονται μετά την εκτέλεση του προγράμματος:
(Qemu) Πληροφορίες καταχωρεί R00 = 00000003 R01 = 00000002 R02 = 00000005 R03 = 00000006 R04 = 00000000 R05 = 00000000 R06 = 00000000 R07 = 00000000 R08 = 00000000 R09 = 00000000 R10 = 00000000 R11 = 00000000 R12 = 00000000 R13 = 00000000 R14 = 00000000 R15 = 00000010 PSR = 400001d3 -Z-- A svc32

ΥΣΤΕΡΟΓΡΑΦΟ. Σε αυτό το άρθρο, προσπάθησα να περιγράψω τα βασικά του προγραμματισμού στο assembler ARM. Ελπίζω να το απολαύσατε! Αυτό είναι αρκετό για να εμβαθύνουμε περαιτέρω στη ζούγκλα αυτής της γλώσσας και να γράψουμε προγράμματα σε αυτήν. Αν όλα πάνε καλά, θα συνεχίσω να γράφω για αυτά που ανακαλύπτω μόνος μου. Εάν υπάρχουν λάθη, μην κλωτσάτε, καθώς είμαι νέος στο assembler.

Εάν χρησιμοποιείτε μια διανομή Raspbian ως το λειτουργικό σύστημα του Raspberry Pi, θα χρειαστείτε δύο βοηθητικά προγράμματα, συγκεκριμένα ως (ένα assembler που μετατρέπει τον πηγαίο κώδικα της γλώσσας συγκρότησης σε δυαδικό κώδικα) και το ld (ένα σύνδεσμο που δημιουργεί το εκτελέσιμο αρχείο που προκύπτει). Και τα δύο βοηθητικά προγράμματα βρίσκονται στο πακέτο λογισμικού binutils, επομένως ενδέχεται να υπάρχουν ήδη στο σύστημά σας. Φυσικά, χρειάζεστε επίσης ένα καλό πρόγραμμα επεξεργασίας κειμένου. Συνιστώ πάντα τη χρήση του Vim για την ανάπτυξη λογισμικού, αλλά έχει μεγάλο εμπόδιο στην είσοδο, οπότε το Nano ή οποιοδήποτε άλλο πρόγραμμα επεξεργασίας κειμένου GUI θα τα κάνει μια χαρά.

Είστε έτοιμοι να ξεκινήσετε; Αντιγράψτε τον παρακάτω κώδικα και αποθηκεύστε τον στο αρχείο myfirst.s:

Καθολική _start _start: mov r7, # 4 mov r0, # 1 ldr r1, = string mov r2, #stringlen swi 0 mov r7, # 1 swi 0 .data string: .ascii "Ciao! \ N" stringlen =. - κορδόνι

Αυτό το πρόγραμμα απλώς εκτυπώνει τη συμβολοσειρά "Ciao!" στην οθόνη και αν έχετε διαβάσει τα άρθρα σχετικά με τη χρήση της γλώσσας assembly για την εργασία με κεντρικές μονάδες επεξεργασίας x86, ορισμένες από τις οδηγίες που χρησιμοποιούνται μπορεί να σας είναι γνωστές. Ωστόσο, υπάρχουν πολλές διαφορές μεταξύ των οδηγιών των αρχιτεκτονικών x86 και ARM, κάτι που μπορεί να ειπωθεί και για τη σύνταξη του πηγαίου κώδικα, οπότε θα το αναλύσουμε λεπτομερώς.

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

As -o myfirst.o myfirst.s && ld -o myfirst myfirst.o

Τώρα μπορείτε να εκτελέσετε το πρόγραμμα που δημιουργήσατε με την εντολή. / Myfirst. Πιθανότατα παρατηρήσατε ότι το εκτελέσιμο αρχείο έχει πολύ μικρό μέγεθος, περίπου 900 byte - αν χρησιμοποιούσατε τη γλώσσα προγραμματισμού C και τη συνάρτηση puts (), το μέγεθος του δυαδικού αρχείου θα ήταν περίπου πέντε φορές μεγαλύτερο!

Δημιουργήστε το δικό σας λειτουργικό σύστημα για το Raspberry Pi

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

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

Ένα από τα καλύτερα τέτοια έγγραφα είναι ένα έγγραφο που ονομάζεται Baking Pi (www.cl.cam.ac.uk/projects/raspberrypi/tutorials/os/index.html) από το Πανεπιστήμιο του Cambridge. Βασικά, είναι ένα σύνολο από σεμινάρια που περιγράφουν τεχνικές γλώσσας συναρμολόγησης για την ενεργοποίηση των LED, την πρόσβαση σε pixel στην οθόνη, τη λήψη εισόδου από το πληκτρολόγιο και ούτω καθεξής. Καθώς διαβάζετε, θα μάθετε πολλά για το υλικό του Raspberry Pi, με τα εγχειρίδια που γράφτηκαν για τα αυθεντικά μοντέλα αυτών των υπολογιστών μονής πλακέτας, επομένως δεν υπάρχει καμία εγγύηση ότι θα είναι σχετικά με μοντέλα όπως τα A+, B. + και Pi 2.

Εάν προτιμάτε τη γλώσσα προγραμματισμού C, θα πρέπει να ανατρέξετε στο έγγραφο Valvers που βρίσκεται στη διεύθυνση http://tinyurl.com/qa2s9bg, το οποίο περιγράφει τη διαδικασία διαμόρφωσης του cross compiler και δημιουργίας του απλούστερου πυρήνα λειτουργικού συστήματος, και στην ενότητα Wiki του ο χρήσιμος πόρος OSDev που βρίσκεται Δείτε http://wiki.osdev.org/Raspberry_Pi_Bare_Bones για πληροφορίες σχετικά με τον τρόπο δημιουργίας και εκτέλεσης ενός βασικού πυρήνα λειτουργικού συστήματος σε ένα Raspberry Pi.

Όπως αναφέρθηκε παραπάνω, το μεγαλύτερο πρόβλημα σε αυτήν την περίπτωση είναι η ανάγκη ανάπτυξης προγραμμάτων οδήγησης για διάφορες συσκευές υλικού Raspberry Pi: ελεγκτής USB, υποδοχή κάρτας SD και ούτω καθεξής. Εξάλλου, ακόμη και ο κωδικός για τις αναφερόμενες συσκευές μπορεί να πάρει δεκάδες χιλιάδες γραμμές. Εάν εξακολουθείτε να θέλετε να αναπτύξετε το δικό σας πλήρως λειτουργικό λειτουργικό σύστημα για το Raspberry Pi, θα πρέπει να επισκεφτείτε τα φόρουμ στο www.osdev.org και να ρωτήσετε εάν κάποιος έχει ήδη αναπτύξει προγράμματα οδήγησης για αυτές τις συσκευές και, αν είναι δυνατόν, να τα προσαρμόσετε για τον πυρήνα σας. λειτουργικό σύστημα, εξοικονομώντας έτσι μεγάλο μέρος του χρόνου σας.

Πώς λειτουργούν όλα

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

Με την παρακάτω οδηγία, βάζουμε τον αριθμό 4 στον καταχωρητή r7. (Εάν δεν έχετε εργαστεί ποτέ με τη γλώσσα assembly στο παρελθόν, θα πρέπει να γνωρίζετε ότι ένας καταχωρητής είναι μια θέση μνήμης που βρίσκεται απευθείας στην κεντρική μονάδα επεξεργασίας. Οι περισσότερες σύγχρονες μονάδες κεντρικής επεξεργασίας εφαρμόζουν μικρό αριθμό καταχωρητών σε σύγκριση με εκατομμύρια ή δισεκατομμύρια θέσεις RAM , αλλά οι καταχωρητές είναι τσιπ αρχιτεκτονικής ARM παρέχουν στους προγραμματιστές μεγάλο αριθμό καταχωρητών γενικής χρήσης: ένας προγραμματιστής μπορεί να χρησιμοποιήσει έως και 16 καταχωρητές με ονόματα από r0 έως r15 και αυτοί οι καταχωρητές δεν σχετίζονται με ιστορικούς περιορισμούς, όπως στην περίπτωση του αρχιτεκτονική x86, όπου ορισμένοι από τους καταχωρητές μπορούν να χρησιμοποιηθούν για συγκεκριμένους σκοπούς σε συγκεκριμένες χρονικές στιγμές.

Έτσι, παρόλο που η εντολή mov είναι πολύ παρόμοια με την οδηγία με το ίδιο όνομα στην αρχιτεκτονική x86, σε κάθε περίπτωση, θα πρέπει να δώσετε προσοχή στο σύμβολο κατακερματισμού δίπλα στον αριθμό 4, που υποδεικνύει ότι η επόμενη είναι μια ακέραια τιμή και όχι μια διεύθυνση στη μνήμη. Σε αυτήν την περίπτωση, θέλουμε να χρησιμοποιήσουμε την κλήση συστήματος εγγραφής πυρήνα Linux για να εκτυπώσουμε τη γραμμή μας. για να χρησιμοποιήσετε κλήσεις συστήματος, πρέπει να συμπληρώσετε τους καταχωρητές με τις απαιτούμενες τιμές προτού επιτρέψετε στον πυρήνα να κάνει τη δουλειά του. Ο αριθμός κλήσης συστήματος πρέπει να τοποθετηθεί στον καταχωρητή r7, με τον αριθμό 4 να είναι ο αριθμός κλήσης συστήματος εγγραφής.

Με την ακόλουθη οδηγία mov, βάζουμε τον περιγραφέα του αρχείου στο οποίο πρέπει να γραφεί η συμβολοσειρά "Ciao!", δηλαδή τον περιγραφέα της τυπικής ροής εξόδου, στον καταχωρητή r0. Εφόσον σε αυτήν την περίπτωση χρησιμοποιείται το τυπικό ρεύμα εξόδου, ο τυπικός περιγραφέας του τοποθετείται στον καταχωρητή, δηλαδή 1. Στη συνέχεια, πρέπει να βάλουμε τη διεύθυνση της συμβολοσειράς που θέλουμε να εξάγουμε στον καταχωρητή r1 χρησιμοποιώντας την εντολή ldr (την εντολή "φόρτωση στον καταχωρητή", σημειώστε το σύμβολο ίσου, υποδεικνύοντας ότι ακολουθείται από μια ετικέτα, όχι μια διεύθυνση). Στο τέλος του κώδικα, δηλαδή στην ενότητα δεδομένων, δηλώνουμε αυτή τη συμβολοσειρά με τη μορφή μιας ακολουθίας χαρακτήρων ASCII. Για να χρησιμοποιήσουμε με επιτυχία την κλήση συστήματος "εγγραφής", πρέπει επίσης να πούμε στον πυρήνα του λειτουργικού συστήματος ποιο είναι το μήκος της συμβολοσειράς εξόδου, οπότε βάζουμε την τιμή stringlen στον καταχωρητή r2. (Η τιμή του stringlen υπολογίζεται αφαιρώντας τη διεύθυνση τέλους της συμβολοσειράς από τη διεύθυνση έναρξης.)

Σε αυτό το σημείο, έχουμε συμπληρώσει όλους τους καταχωρητές με τα απαραίτητα δεδομένα και είμαστε έτοιμοι να μεταφέρουμε τον έλεγχο στον πυρήνα του Linux. Για να το κάνουμε αυτό, χρησιμοποιούμε την οδηγία swi, η οποία σημαίνει "διακοπή λογισμικού", για να μεταβούμε στο χώρο του πυρήνα του λειτουργικού συστήματος (με τον ίδιο περίπου τρόπο όπως η οδηγία int στα άρθρα αρχιτεκτονικής x86). Ο πυρήνας του λειτουργικού συστήματος εξετάζει τα περιεχόμενα του καταχωρητή r7, βρίσκει μια ακέραια τιμή 4 σε αυτόν και καταλήγει στο συμπέρασμα: "Έτσι, ο καλών θέλει να εκτυπώσει μια συμβολοσειρά." Μετά από αυτό, εξετάζει τα περιεχόμενα άλλων καταχωρητών, βγάζει τη συμβολοσειρά και επιστρέφει τον έλεγχο στο πρόγραμμά μας.

Έτσι, βλέπουμε τη γραμμή "Ciao!" Στην οθόνη, μετά την οποία πρέπει απλώς να τερματίσουμε σωστά την εκτέλεση του προγράμματος. Επιλύουμε αυτό το πρόβλημα τοποθετώντας τον αριθμό syscall εξόδου στον καταχωρητή r7 και στη συνέχεια επικαλώντας την εντολή διακοπής λογισμικού μηδέν. Και αυτό είναι όλο - ο πυρήνας του λειτουργικού συστήματος ολοκληρώνει την εκτέλεση του προγράμματός μας και μεταβαίνουμε ξανά στο κέλυφος εντολών.

Το Vim (αριστερά) είναι ένας εξαιρετικός επεξεργαστής κειμένου για τη σύνταξη γλώσσας assembly - ένα αρχείο επισήμανσης σύνταξης για την αρχιτεκτονική ARM είναι διαθέσιμο στη διεύθυνση http://tinyurl.com/psdvjen.

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

Αντίστροφη μηχανική

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

Objdump -d myfirst

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

Υπορουτίνες, βρόχοι και εντολές υπό όρους

Τώρα που ξέρουμε πώς να σχεδιάζουμε, να συναρμολογούμε και να συνδέουμε απλά προγράμματα, ας προχωρήσουμε στην εξέταση κάτι λίγο πιο περίπλοκο. Στο επόμενο πρόγραμμα, οι υπορουτίνες χρησιμοποιούνται για την έξοδο γραμμών (χάρη σε αυτές, μπορούμε να επαναχρησιμοποιήσουμε θραύσματα κώδικα και να γλιτώσουμε από την ανάγκη να εκτελέσουμε τον ίδιο τύπο λειτουργιών για την πλήρωση καταχωρητών με δεδομένα). Αυτό το πρόγραμμα υλοποιεί έναν κύριο βρόχο συμβάντος που σας επιτρέπει να εξάγετε μια γραμμή μέχρι ο χρήστης να εισαγάγει "q". Μελετήστε τον κώδικα και προσπαθήστε να κατανοήσετε (ή να μαντέψετε!) τον σκοπό των οδηγιών, αλλά μην απελπίζεστε αν δεν καταλαβαίνετε κάτι, γιατί λίγο αργότερα θα το εξετάσουμε και με μεγάλη λεπτομέρεια. Σημειώστε ότι τα σύμβολα @ χρησιμοποιούνται για την επισήμανση σχολίων στη γλώσσα συναρμολόγησης ARM.

Καθολική _start _start: ldr r1, = string1 mov r2, # string1len bl print_string loop: mov r7, # 3 @ read mov r0, # 0 @ stdin ldr r1, = char mov r2, # 2 @ δύο χαρακτήρες swi 0 ldr r1, = char ldrb r2, cmp r2, # 113 @ ASCII κωδικός χαρακτήρα "q" beq γίνει ldr r1, = string2 mov r2, # string2len bl print_string b loop done: mov r7, # 1 swi 0 print_string: mov r7, # 4 mov r0, # 1 swi 0 bx lr .data string1: .ascii "Εισαγάγετε q για έξοδο! \ n" string1len =. - string1 string2: .ascii "That wasn" t q ... \ n "string2len =. - string2 char: .word 0

Το πρόγραμμά μας ξεκινά τοποθετώντας έναν δείκτη στην αρχή της συμβολοσειράς και το μήκος της στους κατάλληλους καταχωρητές για την επακόλουθη υλοποίηση της κλήσης συστήματος εγγραφής και αμέσως μετά πηγαίνει στην υπορουτίνα print_string, που βρίσκεται κάτω στον κώδικα. Για να γίνει αυτή η μετάβαση, χρησιμοποιείται η εντολή bl, το όνομα της οποίας σημαίνει "branch and link" και η ίδια αποθηκεύει την τρέχουσα διεύθυνση στον κώδικα, ο οποίος σας επιτρέπει να επιστρέψετε σε αυτήν αργότερα χρησιμοποιώντας την εντολή bx. Η ρουτίνα print_string απλώς συμπληρώνει τους άλλους καταχωρητές για να πραγματοποιήσει την κλήση συστήματος εγγραφής με τον ίδιο τρόπο όπως στο πρώτο μας πρόγραμμα πριν μεταβούμε στον χώρο του πυρήνα του λειτουργικού συστήματος και στη συνέχεια επιστρέψουμε στην αποθηκευμένη διεύθυνση κώδικα με την εντολή bx.

Επιστρέφοντας στον κωδικό κλήσης, μπορούμε να βρούμε μια ετικέτα που ονομάζεται loop - το όνομα της ετικέτας ήδη υποδηλώνει ότι θα επιστρέψουμε σε αυτήν μετά από λίγο. Αλλά πρώτα, χρησιμοποιούμε μια άλλη κλήση συστήματος που ονομάζεται ανάγνωση (στον αριθμό 3) για να διαβάσουμε έναν χαρακτήρα που έχει εισαχθεί από τον χρήστη χρησιμοποιώντας το πληκτρολόγιο. Επομένως, βάζουμε την τιμή 3 στον καταχωρητή r7 και την τιμή 0 (την τυπική λαβή ροής εισόδου) στον καταχωρητή r0, αφού πρέπει να διαβάσουμε την είσοδο χρήστη, όχι δεδομένα από το αρχείο.

Στη συνέχεια, τοποθετούμε τη διεύθυνση στην οποία θέλουμε να αποθηκεύσουμε τον χαρακτήρα που διαβάζεται και τοποθετείται από τον πυρήνα του λειτουργικού συστήματος στον καταχωρητή r1 - στην περίπτωσή μας, αυτή είναι η περιοχή μνήμης χαρακτήρων που περιγράφεται στο τέλος της ενότητας δεδομένων. (Στην πραγματικότητα, χρειαζόμαστε μια λέξη μηχανής, δηλαδή μια περιοχή μνήμης για την αποθήκευση δύο χαρακτήρων, επειδή θα αποθηκεύει επίσης τον κωδικό κλειδιού Enter. Όταν εργάζεστε με τη γλώσσα συναρμολόγησης, είναι σημαντικό να θυμάστε πάντα την πιθανότητα υπερχείλισης περιοχών μνήμης , γιατί δεν υπάρχουν μηχανισμοί υψηλού επιπέδου έτοιμοι να σας βοηθήσουν!).

Επιστρέφοντας στον κύριο κωδικό, θα δούμε ότι η τιμή 2 τοποθετείται στον καταχωρητή r2, η οποία αντιστοιχεί στους δύο χαρακτήρες που θέλουμε να αποθηκεύσουμε και μετά πηγαίνουμε στο χώρο του πυρήνα του λειτουργικού συστήματος για να εκτελέσουμε τη λειτουργία ανάγνωσης. Ο χρήστης εισάγει έναν χαρακτήρα και πατά το πλήκτρο Enter. Τώρα πρέπει να ελέγξουμε τι είναι αυτός ο χαρακτήρας: βάζουμε τη διεύθυνση της περιοχής μνήμης (char στην ενότητα δεδομένων) στον καταχωρητή r1 και, στη συνέχεια, χρησιμοποιώντας την εντολή ldrb φορτώνουμε ένα byte από την περιοχή μνήμης που δείχνει η τιμή από αυτό κανω ΕΓΓΡΑΦΗ.

Οι αγκύλες σε αυτή την περίπτωση υποδεικνύουν ότι τα δεδομένα αποθηκεύονται στην περιοχή ενδιαφέροντος μνήμης και όχι στον ίδιο τον καταχωρητή. Έτσι, ο καταχωρητής r2 περιέχει τώρα έναν μεμονωμένο χαρακτήρα από τον χαρακτήρα της περιοχής μνήμης από την ενότητα δεδομένων, και αυτός είναι ακριβώς ο χαρακτήρας που εισήγαγε ο χρήστης. Η επόμενη εργασία μας θα είναι να συγκρίνουμε τα περιεχόμενα του καταχωρητή r2 με τον χαρακτήρα "q", που είναι ο 113ος χαρακτήρας του πίνακα ASCII (δείτε τον πίνακα χαρακτήρων που βρίσκεται στη διεύθυνση www.asciichart.com). Τώρα χρησιμοποιούμε την εντολή cmp για να εκτελέσουμε τη λειτουργία σύγκρισης και στη συνέχεια χρησιμοποιούμε την εντολή beq, το όνομα της οποίας σημαίνει "branch if equal", για να μεταβούμε στην ετικέτα done εάν η τιμή στον καταχωρητή r2 είναι 113. Εάν αυτή δεν είναι η case, μετά εκτυπώνουμε τη δεύτερη γραμμή μας και μετά πηγαίνουμε στην αρχή του βρόχου χρησιμοποιώντας την εντολή b.

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

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

Φυσικά, οι πληροφορίες που παρέχονται σε αυτό το άρθρο σχετικά με τη χρήση της γλώσσας assembly για την αρχιτεκτονική ARM είναι μόνο η κορυφή του παγόβουνου. Η χρήση αυτής της γλώσσας προγραμματισμού συνδέεται πάντα με έναν τεράστιο αριθμό αποχρώσεων και αν θέλετε να γράψουμε για αυτές σε ένα από τα παρακάτω άρθρα, απλώς ενημερώστε μας για αυτό! Στο μεταξύ, σας συνιστούμε να επισκεφθείτε τον εξαιρετικό πόρο με πολλά υλικά για εκμάθηση τεχνικών για τη δημιουργία προγραμμάτων για συστήματα Linux που εκτελούνται σε υπολογιστές με κεντρικούς επεξεργαστές βασισμένους σε ARM, ο οποίος βρίσκεται στη διεύθυνση http://tinyurl.com/nsgzq89. Καλό προγραμματισμό!

Προηγούμενα άρθρα από τη σειρά "School of Assembler":

Αρχικά ΜΠΡΑΤΣΟμάλλον ασυνήθιστο assembler (αν ξαναμάθετε με x86, MCS51ή AVR). Έχει όμως μια αρκετά απλή και λογική οργάνωση, οπότε μαθαίνεται γρήγορα.

Υπάρχει πολύ λίγη τεκμηρίωση στη γλώσσα συναρμολόγησης στα ρωσικά. Μπορώ να σας συμβουλεύσω να μεταβείτε σε 2 συνδέσμους (μήπως μπορείτε να βρείτε περισσότερα και να μου πείτε; Θα σας ήμουν ευγνώμων.):
Αρχιτεκτονική και σετ οδηγιών επεξεργαστών ARM RISC - http://www.gaw.ru/html.cgi/txt/doc/micros/arm/index.htm
Κατανοώντας το ARM Assembler, από τη σειρά άρθρων "GBA ASM", του Mike H, μετάφρ. Aquila - http://wasm.ru/series.php?sid=21.

Ο τελευταίος σύνδεσμος με βοήθησε πολύ, διέλυσε την ομίχλη =). Το δεύτερο πράγμα που μπορεί να βοηθήσει είναι, παραδόξως, ο μεταγλωττιστής C Ενσωματωμένος πάγκος εργασίας IAR για ARM(εφεξής απλά IAR EW ARM). Γεγονός είναι ότι από την αρχαιότητα ήταν σε θέση (όπως όλοι οι μεταγλωττιστές που σέβονται τον εαυτό τους, ωστόσο) να μεταγλωττίσει τον κώδικα C σε κώδικα assembler, ο οποίος, με τη σειρά του, μεταγλωττίζεται εξίσου εύκολα σε κώδικα αντικειμένου από τον συναρμολογητή IAR. Επομένως, δεν υπάρχει τίποτα καλύτερο από το να γράψετε την απλούστερη συνάρτηση στο C, να την μεταγλωττίσετε σε assembler και θα γίνει αμέσως σαφές ποια εντολή assembler κάνει τι, πώς περνούν τα ορίσματα και πώς επιστρέφεται το αποτέλεσμα. Σκοτώνεις δύο πουλιά με μια πέτρα - μαθαίνεις assembler και ταυτόχρονα λαμβάνεις πληροφορίες για το πώς να ενσωματώσεις τον κώδικα συναρμολόγησης σε ένα έργο στο C. Εκπαιδεύτηκα στη συνάρτηση μέτρησης CRC16 και ως αποτέλεσμα έλαβα την πλήρη έκδοσή του στο assembler.

Εδώ είναι η αρχική συνάρτηση C (το u16 σημαίνει ανυπόγραφο σύντομο, το u32 σημαίνει ανυπόγραφο int, το u8 σημαίνει ανυπόγραφο χαρακτήρα):
// αρχείο crc16.c
u16 CRC16 (κενό * databuf, μέγεθος u32)
{
u16 tmpWord, crc16, idx;
u8 bitCnt;
#define CRC_POLY 0x1021;

Crc16 = 0;
idx = 0;
ενώ (μέγεθος! = 0)
{
/ * προσθέστε το υψηλό byte του crc16 και το byte εισόδου xor * /
tmpWord = (crc16 >> 8) ^ (* (((u8 *) databuf) + idx));
/ * γράψτε το αποτέλεσμα στο υψηλό byte crc16 * /
tmpWord<<= 8;
crc16 = tmpWord + (0x00FF & crc16);
για (bitCnt = 8; bitCnt! = 0; bitCnt--)
{
/ * ελέγξτε την μπαταρία υψηλής τάξης CRC * /
εάν (crc16 & 0x8000)
{
crc16<<= 1;
crc16 ^ = CRC_POLY;
}
αλλού
crc16<<= 1;
}
idx ++;
Μέγεθος--;
}
επιστροφή crc16;
}

Είναι πολύ εύκολο να δημιουργηθεί ο κωδικός συναρμολόγησης IAR EW ARM. Στις επιλογές του αρχείου crc16.c (προστέθηκε στο έργο) έβαλα daw Παράκαμψη κληρονομικών ρυθμίσεωνκαι, στη συνέχεια, τοποθετήστε 3 πλαίσια ελέγχου στην καρτέλα Λίστα - Αρχείο εξόδου assembler, Συμπεριλάβετε την πηγήκαι Συμπεριλάβετε πληροφορίες πλαισίου κλήσεων(αν και το τελευταίο πλαίσιο ελέγχου, πιθανώς, μπορεί να παραλειφθεί - δημιουργεί ένα σωρό περιττές CFI-διευθυντικός). Μετά τη μεταγλώττιση, το αρχείο είναι project_folder \ ewp \ at91sam7x256_sram \ List \ crc16.s. Αυτό το αρχείο μπορεί να προστεθεί εξίσου εύκολα σε ένα έργο με ένα αρχείο C (θα μεταγλωττίσει μια χαρά).

Φυσικά, όταν έβαλα την άκοπη έκδοση του κώδικα C στον μεταγλωττιστή C, μου έδωσε μια τέτοια λίστα του assembler που δεν κατάλαβα τίποτα γι 'αυτό. Αλλά όταν αφαίρεσα όλους τους τελεστές C εκτός από έναν από τη συνάρτηση, έγινε πιο ξεκάθαρο. Στη συνέχεια, βήμα προς βήμα, πρόσθεσα C-operators, και αυτό συνέβη στο τέλος:

; αρχείο crc16.s
ΟΝΟΜΑ crc16
PUBLIC CRC16

CRC_POLY EQU 0x1021

ΕΝΟΤΗΤΑ `.text`: ΚΩΔΙΚΟΣ: NOROOT (2)
ΜΠΡΑΤΣΟ

// u16 CRC16 (κενό * databuf, μέγεθος u32)
; R0 - αποτέλεσμα επιστροφής, CRC16
R1 - παράμετρος μεγέθους
; R2 - παράμετρος databuf (ήταν κατά την εισαγωγή του R0)
; R3, R12 - προσωρινά μητρώα

CRC16:
PUSH (R3, R12); πληκτρολογώντας, ανακάλυψα ότι τα R3 και R13 πρέπει να αποθηκευτούν
; όχι απαραίτητο. Αλλά αποφάσισα να το κρατήσω για όλους
; συμβαίνει.
MOVS R2, R0, τώρα R2 == databuf
MOV R3, # + 0
MOVS R0, R3, crc16 = 0
CRC16_LOOP:
CMP R1, # + 0, όλα τα byte υποβλήθηκαν σε επεξεργασία (μέγεθος == 0);
BEQ CRC16_RETURN. Εάν ναι, βγείτε
LSR R3, R0, # + 8; R3 = crc16 >> 8
LDRB R12, R12 = * databuf
EOR R3, R3, R12; R3 = * databuf ^ HIGH (crc16)
LSL R3, R3, # + 8, R3<<= 8 (tmpWord <<= 8)
ΚΑΙ R0, R0, # + 255; crc16 & = 0x00FF
ΠΡΟΣΘΗΚΗ R0, R0, R3; crc16 = tmpWord + (0x00FF & crc16)
MOV R12, # + 8, bitCnt = 8
CRC16_BIT_LOOP:
BEQ CRC16_NEXT_BYTE; bitCnt == 0;
TST R0, # 0x8000; Δεν έχουν υποστεί ακόμη επεξεργασία όλα τα bit.
BEQ CRC16_BIT15ZERO; Ελέγξτε το υψηλό bit του crc16.
LSL R0, R0, # + 1, crc16<<= 1
MOV R3, # + (LOW (CRC_POLY)); crc16 ^ = CRC_POLY
ORR R3, R3, # + (HIGH (CRC_POLY)<< 8) ;
EOR R0, R3, R0;
B CRC16_NEXT_BIT

CRC16_BIT15ZERO:
LSL R0, R0, # + 1, crc16<<= 1
CRC16_NEXT_BIT:
SUBS R12, R12, # + 1; bitCnt--
B CRC16_BIT_LOOP;

CRC16_NEXT_BYTE:
ΠΡΟΣΘΗΚΗ R2, R2, # + 1, databuf ++
SUBS R1, R1, # + 1, μέγεθος--
B CRC16_LOOP, βρόχος σε όλα τα byte

CRC16_RETURN:
POP (R3, R12), επαναφορά καταχωρητών
BX LR, υπορουτίνα εξόδου, R0 == crc16

Ο μεταγλωττιστής IAR C κάνει εκπληκτικά καλό κώδικα. Κατάφερα να το βελτιστοποιήσω ελάχιστα. Πέταξε μόνο έναν επιπλέον προσωρινό καταχωρητή που ήθελε να χρησιμοποιήσει ο μεταγλωττιστής (για κάποιο λόγο πήρε το LR ως επιπλέον προσωρινό καταχωρητή, αν και τα R3 και R12 ήταν αρκετά), και αφαίρεσε επίσης μερικές περιττές εντολές που ελέγχουν τους μετρητές και ορίζουν σημαίες ( προσθέτοντας απλώς το επίθημα S στις απαιτούμενες ομάδες).

Αυτή η ενότητα περιγράφει τα σύνολα οδηγιών του επεξεργαστή ARM7TDMI.

4.1 Σύντομη περιγραφή της μορφής

Αυτή η ενότητα παρέχει μια σύντομη περιγραφή των συνόλων εντολών ARM και Thumb.

Το κλειδί για τους πίνακες συνόλων εντολών φαίνεται στον Πίνακα 1.1.

Ο επεξεργαστής ARM7TDMI βασίζεται στην αρχιτεκτονική ARMv4T. Για μια πιο πλήρη περιγραφή και των δύο συνόλων εντολών, ανατρέξτε στο Εγχειρίδιο αναφοράς αρχιτεκτονικής ARM.

Πίνακας 1.1. Κλειδί για τραπέζια

Οι μορφές του συνόλου εντολών ARM φαίνονται στην Εικόνα 1.5.

Για περισσότερες πληροφορίες σχετικά με τις μορφές σετ εντολών ARM, ανατρέξτε στο "Αρχιτεκτονικό Εγχειρίδιο Αναφοράς ARM".

Εικόνα 1.5. Μορφές σετ εντολών ARM

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

4.2 Σύντομη περιγραφή των οδηγιών ARM

Το σετ εντολών ARM φαίνεται στον Πίνακα 1.2.

Πίνακας 1.2. Σύντομη εισαγωγή οδηγιών ARM

Λειτουργίες Σύνταξη Assembler
Αποστολή Αποστολή MOV (συνέχεια) (S) Rd,
Αποστολή ΟΧΙ MVN (συνέχεια) (S) Rd,
Μεταφορά SPSR για εγγραφή MRS (συνέχεια) Rd, SPSR
Μεταφορά CPSR στην εγγραφή MRS (συνέχεια) Rd, CPSR
Μεταφορά μητρώου SPSR MSR (συνδ.) SPSR (πεδίο), Rm
Προώθηση CPSR MSR (συνέχεια) CPSR (πεδίο), Rm
Μεταβίβαση σταθερών σε σημαίες SPSR MSR (συνθήκη) SPSR_f, # 32bit_Imm
Μεταβίβαση σταθερών σε σημαίες CPSR MSR (συνθήκη) CPSR_f, # 32bit_Imm
Αριθμητική Πρόσθεση ADD (συνέχεια) (S) Rd, Rn,
Μεταφέρετε αναδιπλούμενο ADC (συνέχεια) (S) Rd, Rn,
Αφαίρεση SUB (συνέχεια) (S) Rd, Rn,
Αφαίρεση με μεταφορά SBC (συνέχεια) (S) Rd, Rn,
Αφαίρεση αντίστροφη αφαίρεση RSB (συνέχεια) (S) Rd, Rn,
Αφαίρεση προς τα πίσω αφαίρεση με μεταφορά RSC (συνέχεια) (S) Rd, Rn,
Πολλαπλασιασμός MUL (συντ.) (S) Rd, Rm, Rs
Πολλαπλασιασμός-συσσώρευση MLA (συνέχεια) (S) Rd, Rm, Rs, Rn
Πολλαπλασιασμός μεγάλων ανυπόγραφων αριθμών UMULL
Πολλαπλασιασμός - ανυπόγραφη συσσώρευση μεγάλων τιμών UMLAL (συνθήκη) (S) RdLo, RdHi, Rm, Rs
Πολλαπλασιασμός υπογεγραμμένου μακρού SMULL (συνθήκη) (S) RdLo, RdHi, Rm, Rs
Πολλαπλασιασμός - υπογεγραμμένη συσσώρευση μεγάλων τιμών SMLAL (συνθήκη) (S) RdLo, RdHi, Rm, Rs
Σύγκριση CMP (συνέχεια) Rd,
Αρνητική σύγκριση CMN (συνέχεια) Rd,
σπαζοκεφαλιά Εξέταση TST (συνέχεια) Rn,
Έλεγχος ισοδυναμίας TEQ (συνέχεια) Rn,
Κούτσουρο. ΚΑΙ ΚΑΙ (συνέχεια) (S) Rd, Rn,
Εξαιρ. Ή EOR (συνέχεια) (S) Rd, Rn,
ORR ORR (συνέχεια) (S) Rd, Rn,
Καθαρίζοντας λίγο BIC (συνέχεια) (S) Rd, Rn, >
Μετάβαση Μετάβαση (συν) ετικέτα
Ακολουθώντας έναν σύνδεσμο (συν) ετικέτα
Πλοήγηση και αλλαγή ενός συνόλου οδηγιών (συνέχεια) Rn
ΑΝΑΓΝΩΣΗ οι λέξεις LDR (cond) Rd,
LDR (συνέχεια) T Rd,
bytes LDR (συντ.) B Rd,
LDR (συντ.) BT Rd,
υπογεγραμμένο byte LDR (συντ.) SB Rd,
μισές λέξεις LDR (συνέχεια) H Rd,
μισή λέξη με σημάδι LDR (συνθήκη) SH Rd,
λειτουργίες με πολλαπλά μπλοκ δεδομένων -
  • με προκαταρκτική προσαύξηση
  • LDM (συνθήκη) IB Rd (, !} {^}
  • με επακόλουθη προσαύξηση
  • LDM (συνθήκη) IA Rd (, !} {^}
  • με προ-μείωση
  • LDM (συνθήκη) DB Rd (, !} {^}
  • με επακόλουθη μείωση
  • LDM (συνέχεια) DA Rd (, !} {^}
  • λειτουργία στοίβας
  • LDM (κατάσταση) Rd (, !}
  • λειτουργία στοίβας και ανάκτηση CPSR
  • LDM (κατάσταση) Rd (, !} ^
    λειτουργία στοίβας με μητρώα χρηστών LDM (κατάσταση) Rd (, !} ^
    Εγγραφή οι λέξεις STR (cond) Rd,
    λέξεις με προτίμηση λειτουργίας χρήστη STR (συνέχεια) T Rd,
    bytes STR (συνέχεια) B Rd,
    byte με προτίμηση λειτουργίας χρήστη STR (συνέχεια) BT Rd,
    μισές λέξεις STR (συνέχεια) H Rd,
    λειτουργίες σε πολλαπλά μπλοκ δεδομένων -
  • με προκαταρκτική προσαύξηση
  • STM (συνθήκη) IB Rd (, !} {^}
  • με επακόλουθη προσαύξηση
  • STM (συνέχεια) IA Rd (, !} {^}
  • με προ-μείωση
  • STM (συνθήκη) DB Rd (, !} {^}
    o ακολουθούμενη από μείωση STM (συνέχεια) DA Rd (, !} {^}
  • λειτουργία στοίβας
  • STM (συνθήκη) Rd (, !}
  • λειτουργία στοίβας με μητρώα χρηστών
  • STM (συνθήκη) Rd (, !} ^
    Ανταλλαγή λόγια SWP (συνέχεια) Rd, Rm,
    ψηφιόλεξη SWP (συντ.) B Rd, Rm,
    Συνεπεξεργαστής Λειτουργία δεδομένων CDP (συνέχεια) σελ , , CRd, CRn, CRm,
    Μεταφορά στο μητρώο ARM από τον συνεπεξεργαστή MRC (συνέχεια) σελ , , Rd, CRn, CRm,
    Μεταφορά στον συνεπεξεργαστή από το μητρώο ARM MCR (cond) p , , Rd, CRn, CRm,
    ΑΝΑΓΝΩΣΗ LDC (συνέχεια) σελ , CRd,
    Εγγραφή STC (συνέχεια) σελ , CRd,
    Διακοπή λογισμικού SWI 24bit_Imm

    Μπορείτε να μάθετε περισσότερα για το σύστημα εντολών στη λειτουργία ARM.

    Τρόποι διευθυνσιοδότησης

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

    • Λειτουργία 1 - Μετατόπιση τελεστών για οδηγίες επεξεργασίας δεδομένων.
    • Λειτουργία 2 - Διαβάστε και γράψτε μια λέξη ή ένα byte χωρίς υπογραφή.
    • Λειτουργία 3 - Διαβάστε και γράψτε μισή λέξη ή φόρτωση byte σύμβολο.
    • Λειτουργία 4 - Πολλαπλή ανάγνωση και εγγραφή.
    • Λειτουργία 5 - Συνεπεξεργαστής ανάγνωσης και εγγραφής.

    Οι τρόποι διευθυνσιοδότησης με ένδειξη των τύπων τους και οι μνημονικοί κώδικες παρουσιάζονται στον Πίνακα 1.3.

    Πίνακας 1.3. Τρόποι διευθυνσιοδότησης

    Λειτουργία διεύθυνσης Τύπος ή τρόπος διεύθυνσης Μνημονικός κώδικας ή τύπος στοίβας
    Λειτουργία 2 Μετατόπιση σταθερά
    Καταχωρητής όφσετ
    Μετατόπιση καταχωρητή κλιμάκωσης
    Προκαθορισμένη μετατόπιση -
    Συνεχής !
    Κανω ΕΓΓΡΑΦΗ !
    Εγγραφή κλίμακας !
    !
    !
    !
    !
    -
    Συνεχής , # + / - 12bit_Offset
    Κανω ΕΓΓΡΑΦΗ , +/- Rm
    Εγγραφή κλίμακας
    Λειτουργία 2, προνομιακή Μετατόπιση σταθερά
    Καταχωρητής όφσετ
    Μετατόπιση καταχωρητή κλιμάκωσης
    Μετατόπιση ακολουθούμενη από ευρετηρίαση -
    Συνεχής , # + / - 12bit_Offset
    Κανω ΕΓΓΡΑΦΗ , +/- Rm
    Εγγραφή κλίμακας , +/- Rm, LSL # 5bit_shift_imm
    , +/- Rm, LSR # 5bit_shift_imm
    , +/- Rm, ASR # 5bit_shift_imm
    , +/- Rm, ROR # 5bit_shift_imm
    Λειτουργία 3, > Μετατόπιση σταθερά
    !
    Επακόλουθη ευρετηρίαση , # + / - 8bit_Offset
    Κανω ΕΓΓΡΑΦΗ
    Προκαταρκτική ευρετηρίαση !
    Επακόλουθη ευρετηρίαση , +/- Rm
    Λειτουργία 4, ανάγνωση ΙΑ, επακόλουθη αύξηση FD, πλήρως φθίνουσα
    ED, κενό φθίνουσα
    DA, μεταγενέστερη μείωση FA, πλήρως ανοδική
    Προ-μείωση DB EA, κενό αύξουσα
    Λειτουργία 4, εγγραφή ΙΑ, επακόλουθη αύξηση FD, πλήρως φθίνουσα
    IB, προ-αύξηση ED, κενό φθίνουσα
    DA, μεταγενέστερη μείωση FA, πλήρως ανοδική
    Προ-μείωση DB EA, κενό αύξουσα
    Λειτουργία 5, μεταφορά δεδομένων συνεπεξεργαστή Μετατόπιση σταθερά
    Προκαταρκτική ευρετηρίαση !
    Επακόλουθη ευρετηρίαση , # + / - (8bit_Offset * 4)

    Λειτουργία 2

    Ένας τελεστής είναι μέρος μιας εντολής που αναφέρεται σε δεδομένα ή μια περιφερειακή συσκευή. Οι τελεστές 2 παρουσιάζονται στον πίνακα 1.4.

    Πίνακας 1.4. Λειτουργία 2

    Τα πεδία παρουσιάζονται στον πίνακα 1.5.

    Πίνακας 1.5. Πεδία

    Πεδία συνθήκης

    Τα πεδία συνθηκών παρουσιάζονται στον πίνακα 1.6.

    Πίνακας 1.6. Πεδία συνθήκης

    Τύπος πεδίου Κατάληξη Περιγραφή Κατάσταση
    Κατάσταση (κατάσταση) EQ Ίσο Z = 1
    ΒΑ Όχι ίσα Z = 0
    CS Ανυπόγραφο μεγαλύτερο ή ίσο C = 1
    CC Ανυπόγραφο λιγότερο C = 0
    ΜΙ Αρνητικός N = 1
    PL Θετικό ή μηδέν N = 0
    VS Ξεχείλισμα V = 1
    VC Χωρίς υπερχείλιση V = 0
    ΓΕΙΑ Ανυπόγραφο Greater C = 1, Z = 0
    LS Ανυπόγραφο μικρότερο ή ίσο C = 0, Z = 1
    GE Περισσότερο ή ίσο N = V (N = V = 1 ή N = V = 0)
    LT Μικρότερος NV (N = 1 και V = 0) ή (N = 0 και V = 1)
    GT Περισσότερο Z = 0, N = V (N = V = 1 ή N = V = 0)
    LE Μικρότερο ή ίσο με Z = 0 ή NV (N = 1 και V = 0) ή (N = 0 και V = 1)
    AL Πάντα αληθινός οι σημαίες αγνοούνται

    4.3 Σύντομη περιγραφή του σετ εντολών Thumb

    Οι μορφές του συνόλου εντολών Thumb φαίνονται στην Εικόνα 1.6. Για περισσότερες πληροφορίες σχετικά με τις μορφές σετ εντολών ARM, ανατρέξτε στο Εγχειρίδιο ARM Architectural Reference.


    Εικόνα 1.6. Μορφές σετ οδηγιών αντίχειρα

    Το σετ εντολών Thumb φαίνεται στον Πίνακα 1.7.

    Πίνακας 1.7. Μια σύντομη περιγραφή του σετ εντολών Thumb

    Λειτουργία Σύνταξη Assembler
    Προώθηση (αντιγραφή) σταθερές MOV Rd, # 8bit_Imm
    ανώτερος έως κατώτερος MOV Rd, Hs
    κατώτερος έως ανώτερος MOV HD, Rs
    ανώτερος σε ανώτερος MOV Hd, Hs
    Αριθμητική πρόσθεση ΠΡΟΣΘΗΚΗ Rd, Rs, # 3bit_Imm
    προσθέστε junior σε junior ΠΡΟΣΘΗΚΗ Rd, Rs, Rn
    προσθέστε μεγαλύτερο σε νεότερο ADD Rd, Hs
    προσθήκη κατώτερου σε ανώτερο ΠΡΟΣΘΗΚΗ HD, Rs
    προσθήκη ανώτερος σε ανώτερος ADD Hd, Hs
    σταθερή προσθήκη ADD Rd, # 8bit_Imm
    προσθέτουν αξία στο SP ADD SP, # 7bit_Imm ADD SP, # -7bit_Imm
    μεταφερόμενη προσθήκη ADC Rd, Rs
    αφαίρεση SUB Rd, Rs, Rn SUB Rd, Rs, # 3bit_Imm
    αφαίρεση σταθεράς SUB Rd, # 8bit_Imm
    φέρω αφαίρεση SBC Rd, Rs
    αντιστροφή του σημείου NEG Rd, Rs
    πολλαπλασιασμός MUL Rd, Rs
    συγκρίνετε junior με junior CMP Rd, Rs
    συγκρίνετε junior και senior CMP Rd, Hs
    συγκρίνετε ανώτερους και κατώτερους CMP HD, Rs
    συγκρίνετε ανώτερους και ανώτερους CMP Hd, Hs
    συγκρίνετε αρνητικά CMN Rd, Rs
    σύγκριση με σταθερά CMP Rd, # 8bit_Imm
    σπαζοκεφαλιά ΚΑΙ AND Rd, Rs
    Εξαιρ. Ή EOR Rd, Rs
    Ή ORR Rd, Rs
    Καθαρίζοντας λίγο BIC Rd, Rs
    Αποστολή ΟΧΙ MVN Rd, Rs
    Δοκιμή bit TST Rd, Rs
    Μετατόπιση / Περιστροφή Λογική αριστερή μετατόπιση LSL Rd, Rs, # 5bit_shift_imm LSL Rd, Rs
    Λογική μετατόπιση δεξιά LSR Rd, Rs, # 5bit_shift_imm LSR Rd, Rs
    Αριθμητική μετατόπιση προς τα δεξιά ASR Rd, Rs, # 5bit_shift_imm ASR Rd, Rs
    Δεξιά περιστροφή ROR Rd, Rs
    Μετάβαση άλματα υπό όρους -
    Ετικέτα BEQ
    Ετικέτα BNE
    Ετικέτα BCS
    Ετικέτα BCC
    Ετικέτα ΔΜΣ
    Ετικέτα BPL
    Ετικέτα BVS
    Ετικέτα BVC
  • C = 1, Z = 0
  • Ετικέτα BHI
  • C = 0, Z = 1
  • Ετικέτα BLS
  • N = 1, V = 1 ή N = 0, V = 0
  • Ετικέτα BGE
  • N = 1, V = 0 ή N = 0, V = 1
  • Ετικέτα BLT
  • Z = 0 και ((N ή V = 1) ή (N ή V = 0))
  • Ετικέτα BGT
  • Z = 1 ή ((N = 1 ή V = 0) ή (N = 0 και V = 1))
  • Ετικέτα BLE
    Άλμα άνευ όρων Ετικέτα Β
    Κάντε παρατεταμένο κλικ στον σύνδεσμο Ετικέτα BL
    Προαιρετική αλλαγή κατάστασης -
  • στη διεύθυνση σε ml. κανω ΕΓΓΡΑΦΗ
  • BX Rs
  • στη διεύθυνση στην οδό. κανω ΕΓΓΡΑΦΗ
  • BX Hs
    ΑΝΑΓΝΩΣΗ με σταθερά μετατόπισης -
  • οι λέξεις
  • LDR Rd,
  • μισές λέξεις
  • LDRH Rd,
  • bytes
  • LDRB Rd,
    με καταχωρητή offset -
  • οι λέξεις
  • LDR Rd,
  • μισές λέξεις
  • LDRH Rd,
  • μισή λέξη
  • LDRSH Rd,
    LDRB Rd,
  • υπογεγραμμένο byte
  • LDRSB Rd,
    σε σχέση με τον μετρητή προγράμματος υπολογιστή LDR Rd,
    σε σχέση με τον δείκτη στοίβας SP LDR Rd,
    Διεύθυνση -
  • χρησιμοποιώντας υπολογιστή
  • ADD Rd, PC, # 10bit_Offset
  • με ΣΠ
  • ADD Rd, SP, # 10bit_Offset
    Πολλαπλή ανάγνωση LDMIA Rb!,
    Εγγραφή με σταθερά μετατόπισης -
  • οι λέξεις
  • STR Rd,
  • μισές λέξεις
  • STRH Rd,
  • bytes
  • STRB Rd,
    με καταχωρητή offset -
  • οι λέξεις
  • STR Rd,
  • μισές λέξεις
  • STRH Rd,
  • bytes
  • STRB Rd,
    σε σχέση με το SP STR Rd,
    ΠΟΛΛΑΠΛΗ ΕΙΣΟΔΟΣ STMIA Rb !,
    Τοποθέτηση / σκάσιμο από τη στοίβα Σπρώξτε τους καταχωρητές στη στοίβα ΣΠΡΩΞΤΕ
    Πιέστε το LR και εγγραφείτε στη στοίβα ΣΠΡΩΞΤΕ
    Pop καταχωρεί από τη στοίβα ΚΡΟΤΟΣ
    Pop καταχωρητές και υπολογιστές από τη στοίβα ΚΡΟΤΟΣ
    Διακοπή λογισμικού - SWI 8bit_Imm

    Προς το παρόν, για προγραμματισμό ακόμη και αρκετά απλών μικροελεγκτών, χρησιμοποιούνται, κατά κανόνα, γλώσσες υψηλού επιπέδου, οι οποίες είναι υποσύνολα της γλώσσας C ή C ++.

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

    Πριν προχωρήσετε στην εξέταση των εντολών ARM7, είναι απαραίτητο να σημειώσετε τα ακόλουθα χαρακτηριστικά του:

      Υποστηρίζει δύο σετ εντολών: ARM με οδηγίες 32 bit και THUMB με οδηγίες 16 bit. Στη συνέχεια, θα εξετάσουμε ένα σύνολο εντολών 32-bit, η λέξη ARM θα σημαίνει τις οδηγίες που ανήκουν σε αυτήν τη μορφή και η λέξη ARM7 θα σημαίνει την ίδια την CPU.

      Υποστηρίζει δύο μορφές διευθύνσεων 32-bit: επεξεργαστή big-endian και επεξεργαστή small-edian). Στην πρώτη περίπτωση, το πιο σημαντικό bit (Most Significant Bit - MSB) βρίσκεται στο λιγότερο σημαντικό bit της λέξης και στη δεύτερη περίπτωση - στο πιο σημαντικό. Αυτό διασφαλίζει τη συμβατότητα με άλλες οικογένειες επεξεργαστών 32-bit κατά τη χρήση γλωσσών υψηλού επιπέδου. Ωστόσο, σε μια σειρά από οικογένειες επεξεργαστών με τον πυρήνα ARM, χρησιμοποιείται μόνο μεγάλη σειρά byte (δηλαδή το MSB είναι το πιο σημαντικό κομμάτι της διεύθυνσης), γεγονός που απλοποιεί σημαντικά τη δουλειά με τον επεξεργαστή. Δεδομένου ότι ο μεταγλωττιστής που χρησιμοποιείται για το ARM7 λειτουργεί με κώδικα και στις δύο μορφές, πρέπει να βεβαιωθείτε ότι η μορφή λέξης είναι σωστή, διαφορετικά ο κώδικας που θα προκύψει θα "γυριστεί από μέσα προς τα έξω".

      Η δυνατότητα εκτέλεσης διαφόρων τύπων μετατόπισης ενός από τους τελεστές "στο πέρασμα" πριν από τη χρήση του στην ALU

      Υποστήριξη για εκτέλεση οποιασδήποτε εντολής υπό όρους

      Δυνατότητα απαγόρευσης αλλαγής των σημαιών των αποτελεσμάτων λειτουργίας.

        1. Εκτέλεση εντολής υπό όρους

    Ένα από τα σημαντικά χαρακτηριστικά του συνόλου εντολών ARM είναι ότι υποστηρίζει την υπό όρους εκτέλεση οποιασδήποτε εντολής. Στους παραδοσιακούς μικροελεγκτές, οι μόνες εντολές υπό όρους είναι οι οδηγίες μετάβασης υπό όρους, και ίσως ορισμένες άλλες, όπως εντολές για έλεγχο ή αλλαγή της κατάστασης μεμονωμένων bit. Στο σύνολο εντολών ARM, τα πιο σημαντικά 4 bit του κώδικα εντολών συγκρίνονται πάντα με τις σημαίες συνθήκης στον καταχωρητή CPSR. Εάν οι τιμές τους δεν ταιριάζουν, η εντολή στο στάδιο της αποκρυπτογράφησης αντικαθίσταται από την εντολή NOP (χωρίς λειτουργία).

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

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

    Για να εφαρμόσετε αυτήν τη δυνατότητα, πρέπει να προσθέσετε οποιοδήποτε από τα δεκαέξι προθέματα που ορίζουν τις δοκιμασμένες καταστάσεις των σημαιών συνθήκης στη βασική μνημονική σημείωση των εντολών assembler (και το C είναι το ίδιο). Αυτά τα προθέματα φαίνονται στον πίνακα. 3. Αντίστοιχα, υπάρχουν 16 επιλογές για κάθε εντολή. Για παράδειγμα, η ακόλουθη εντολή:

    MOVEQ R1, # 0x008

    σημαίνει ότι ο αριθμός 0x00800000 θα φορτωθεί στον καταχωρητή R1 μόνο εάν το αποτέλεσμα της τελευταίας εντολής επεξεργασίας δεδομένων ήταν "ίσο" ή το αποτέλεσμα ήταν 0 και η σημαία (Z) του καταχωρητή CPSR είχε οριστεί ανάλογα.

    Πίνακας 3

    Προθέματα εντολών

    Εννοια

    Το Z εγκατεστημένο

    Ο Ζ έπεσε

    Με εγκατεστημένο

    Ανώτερο ή ίσο (ανυπόγραφο)

    Το C μηδενίζεται

    Παρακάτω (ανυπόγραφο)

    N εγκατεστημένο

    Αρνητικό αποτέλεσμα

    N καθαρίστηκε

    Θετικό ή 0

    V σετ

    Ξεχείλισμα

    Το V έπεσε

    Χωρίς υπερχείλιση

    Με εγκατεστημένο,

    Ο Ζ έπεσε

    Πάνω (ανυπόγραφο)

    Με πέσει,

    Το Z εγκατεστημένο

    Κάτω ή ίσο (ανυπόγραφο)

    Μεγαλύτερο ή ίσο με (υπογεγραμμένο)

    Το N δεν ισούται με το V

    Λιγότερο (εικονικό)

    Ο Ζ έπεσε ΚΑΙ

    (N ίσον V)

    Περισσότερα (εικονική)

    Το Z ορίζεται OR

    (Το N δεν ισούται με V)

    Μικρότερο ή ίσο με (υπογεγραμμένο)

    (αγνοήθηκε)

    Εκτέλεση άνευ όρων

    Συνεχίζοντας το θέμα:
    Ενας υπολογιστής

    Η καθολική και πιο οικονομική έκδοση του δρομολογητή για εργασία με ενσύρματα δίκτυα και διανομή δικτύων Wi Fi στην οικογένεια Kinetic είναι το Zyxel Keenetic Lite iii. Το...

    Νέα άρθρα
    /
    Δημοφιλής