01 / ΠΟΥ ΥΠΑΡΧΕΙ Η ΔΟΜΗ;
Ο assembler προετοιμάζει. Ο 8502 διαβάζει.
Το AIS4CBM χρησιμοποιεί τον Kick Assembler του Mads Nielsenγια τη συναρμολόγηση του πυρήνα γλώσσας μηχανής. Μαζί με τις εντολές assembly, η γλώσσα scripting παρέχει δομές, λίστες και πίνακες κατακερματισμού. Αυτά βοηθούν να κατασκευάσουμε το πρόγραμμα στον υπολογιστή ανάπτυξης.
Ο ορισμός μιας δομής δεν δεσμεύει αυτόματα αντίστοιχη εγγραφή στη μνήμη του Commodore. Επιλέγουμε τι θα παραχθεί με οδηγίες όπως .byte και .word. Ο C128 λαμβάνει τον παραγόμενο κώδικα και τα δεδομένα.
- 01 / ΣΤΟ PCΠεριγραφή του πεδίου
Μια ονομασμένη δομή κρατά το πλάτος εισόδου, το μέγεθος εξόδου και τον τύπο.
- 02 / ΚΑΤΑ ΤΗ ΣΥΝΑΡΜΟΛΟΓΗΣΗΠαραγωγή μικρού πίνακα
Ο Kick Assembler γράφει τρία byte περιγραφέα και επιλύει τις αναφορές προς αυτά.
- 03 / ΣΤΟΝ C128Ανάγνωση και αποκωδικοποίηση
Ο 8502 διαβάζει αυτά τα byte και καλεί έναν κοινό χειριστή πεδίων.
Αυτή η διάκριση εξηγεί το όφελος: περιγραφικός πηγαίος κώδικας παράγει συμπαγή αναπαράσταση κατά την εκτέλεση. Τα ονόματα πεδίων και οι πίνακες κατακερματισμού κάνουν τη δουλειά τους στη συναρμολόγηση.
Αναφορές Kick Assembler: η γλώσσα scripting · οδηγίες ορισμού τιμών ή παραγωγής byte.
02 / ΞΕΚΙΝΗΣΤΕ ΜΕ ΕΝΑ ΠΕΔΙΟ
Τρεις ιδιότητες περιγράφουν τη δουλειά.
Η εφαρμογή ορίζει μια μικρή δομή για τη μορφή κάθε πεδίου:
.struct aField {bits,bytes,dataType}
| Ιδιότητα | Σημασία | Παράδειγμα ταχύτητας |
|---|---|---|
bits | Bit που καταναλώνονται από το εισερχόμενο φορτίο. | 10 |
bytes | Byte που καταλαμβάνει το αποκωδικοποιημένο πεδίο. | 2 |
dataType | Ο κωδικός αριθμητικού τύπου ή κειμένου που ορίζει η εφαρμογή. | uInt |
aField(10,2,uInt) δημιουργεί μια τιμή δομής. Η ιδιότητα .bits είναι 10, η .bytes είναι 2 και η .dataType είναι η σταθερά της εφαρμογής uInt. Το AIS4CBM ορίζει uInt=1, Int=2 και String=3. Αυτά τα ονόματα περιγράφουν τα αποκωδικοποιημένα πεδία μας· δεν είναι οι τύποι τιμών του ίδιου του Kick Assembler.
Ένας πίνακας κατακερματισμού δίνει όνομα σε κάθε περιγραφή. Το συντομευμένο απόσπασμα κρατά τα αναγνωριστικά της εφαρμογής, μαζί με την ορθογραφία allFiledsHT:
.define allFiledsHT {
.var allFiledsHT = Hashtable()
}
.eval allFiledsHT.put("mmsi",aField(30,4,uInt))
.eval allFiledsHT.put("sog",aField(10,2,uInt))
.eval allFiledsHT.put("name",aField(120,20,String))
put(key,value) αποθηκεύει μια περιγραφή· η get(key) την ανακτά. Για παράδειγμα, το allFiledsHT.get("sog").bits δίνει 10. .var ορίζει μεταβλητή scripting και η .eval αξιολογεί μια έκφραση scripting. Καμία από τις δύο δεν εκτελείται από τον 8502.
Οι πραγματικοί ορισμοί πεδίων · Δομές που ορίζει ο χρήστης · Πίνακες κατακερματισμού του Kick Assembler.
03 / ΑΠΟ ΤΙΣ ΠΕΡΙΓΡΑΦΕΣ ΣΤΑ ΔΕΔΟΜΕΝΑ
Αυτός ο βρόχος εκτελείται στη συναρμολόγηση.
keys() δίνει μια λίστα με τα ονόματα του καταλόγου. Ο επόμενος βρόχος αναζητά κάθε περιγραφή και παράγει τρία byte στον AISFields:
AISFields:
.for (var i=0; i<allFiledsHT.keys().size(); i++) {
.var fieldKey = allFiledsHT.keys().get(i)
field:
.byte allFiledsHT.get(fieldKey).bits
.byte allFiledsHT.get(fieldKey).bytes
.byte allFiledsHT.get(fieldKey).dataType
}
Για την ταχύτητα, τα byte είναι 0A 02 01: δέκα bit εισόδου, δύο byte εξόδου και ακέραιος χωρίς πρόσημο. Περιγράφουν το πεδίο· δεν περιέχουν την πραγματική ταχύτητα ενός σκάφους. Ο περιγραφέας καταλαμβάνει τρία byte.
Κάθε επανάληψη έχει τη δική της ετικέτα field . Ο Kick Assembler επιτρέπει στον επόμενο βρόχο να αναφερθεί στην ετικέτα της επανάληψης i ως AISFields[i].field. Χρησιμοποιούμε αυτή τη διεύθυνση για έναν δεύτερο πίνακα κατακερματισμού:
.for (var i=0; i<allFiledsHT.keys().size(); i++) {
.eval aisFieldAddressByName.put(
allFiledsHT.keys().get(i), AISFields[i].field)
}
Ο πρώτος πίνακας αντιστοιχίζει όνομα → περιγραφή. Ο δεύτερος αντιστοιχίζει όνομα → διεύθυνση παραγόμενου περιγραφέα. Και οι δύο βοηθούν κατά τη συναρμολόγηση. Μια επόμενη οδηγία .word aisFieldAddressByName.get("sog") τοποθετεί την επιλυμένη διεύθυνση των δύο byte στο πρόγραμμα.
AISFields, έλεγχος μεγέθους και aisFieldAddressByName · Πρόσβαση σε ετικέτες βρόχων for/while.
04 / ΒΑΛΤΕ ΤΑ ΠΕΔΙΑ ΣΕ ΣΕΙΡΑ
Ο κατάλογος ορίζει τη μορφή. Η διάταξη ορίζει τη σειρά.
Διαφορετικά μηνύματα AIS επαναχρησιμοποιούν πολλά ίδια πεδία. Η κοινή κεφαλίδα αναφέρεται στον τύπο, στον δείκτη επανάληψης και στο MMSI:
hmesg: .word aisFieldAddressByName.get("type")
.word aisFieldAddressByName.get("ri")
.word aisFieldAddressByName.get("mmsi")
.byte 0
Ο αποκωδικοποιητής ακολουθεί τις αναφορές με αυτή τη σειρά. Καταναλώνει 6 + 2 + 30 = 38 bit εισόδου και παράγει 1 + 1 + 4 = 6 αποκωδικοποιημένα byte. Έπειτα επιλέγει τη διάταξη φορτίου από τον τύπο μηνύματος. Το τελικό μηδέν σηματοδοτεί το τέλος της λίστας της εφαρμογής.
Kick Assembler List() περιγράφουν επίσης τη σειρά για τον υπολογισμό μετατοπίσεων και μεγεθών. Για παράδειγμα, η λίστα αναφοράς θέσης είναι:
.var posmsgFieldList = List().add("navst","rot","sog","p_acc","long","lat","cog","hdg","time_stamp").lock()
add() προσθέτει στοιχεία με τη σειρά, η get(i) ανακτά ένα στοιχείο και η size() δίνει το πλήθος. lock() αποτρέπει μεταγενέστερες αλλαγές στη λίστα. Βοηθητικές συναρτήσεις αθροίζουν τα byte εξόδου των περιγραφών για να υπολογίσουν τη μετατόπιση κάθε αποκωδικοποιημένου πεδίου. Ο τρέχων κώδικας δηλώνει τις αντίστοιχες εγγραφές εκτέλεσης .word ξεχωριστά, οπότε οι δύο αναπαραστάσεις πρέπει να συμφωνούν.
Κατά την εκτέλεση, η processMessage διαβάζει μια διεύθυνση περιγραφέα, φορτώνει πλήθος bit, πλήθος byte και τύπο, και καλεί numericFieldHandler ή stringFieldHandler. Όταν ολοκληρωθεί το πεδίο, προχωρά τον δείκτη εξόδου κατά το πλήθος byte του περιγραφέα. Αριθμοί με και χωρίς πρόσημο μοιράζονται τον βρόχο εξαγωγής· η μεταγενέστερη μετατροπή ερμηνεύει τον τύπο τους.
processMessage και οι δύο χειριστές πεδίων · Τιμές List · Μεταβλητές και κλείδωμα μεταβλητών τιμών.
05 / ΑΚΟΛΟΥΘΗΣΤΕ ΕΝΑ ΠΕΔΙΟ
Μία περιγραφή. Τρία byte. Μια αποκωδικοποιημένη τιμή.
Επιλέξτε πεδίο και αλλάξτε την τιμή του παραδείγματος. Προσέξτε ότι ο περιγραφέας παραμένει ίδιος. Έπειτα διαβάστε ένα bit κάθε φορά ή αποκωδικοποιήστε ολόκληρο το πεδίο.
Ταχύτητα: aField(10,2,uInt) παράγει περιγραφέα 0A 02 01. Τα δέκα bit εισόδου 0010111011 αναπαριστούν το 187. Η αποκωδικοποίηση παράγει 00 BB, που η προβολή κλάσης A/B εμφανίζει ως 18,7 κόμβους. Η αλλαγή ταχύτητας δεν αλλάζει τον περιγραφέα.
Ενεργοποιήστε JavaScript για να αλλάξετε πεδία και να δοκιμάσετε το παράδειγμα βήμα προς βήμα.
- bits
- bytes
- dataType
Τρία byte περιγραφέα · δεκαεξαδικά
Στον C128 · κατανάλωση των bit του πεδίου
Τα πράσινα bit έχουν διαβαστεί. Το χρυσό δείχνει το επόμενο.
Αποκωδικοποιημένα byte εξόδου · δεκαεξαδικάΤο παράδειγμα του φυλλομετρητή μοντελοποιεί την εξαγωγή πεδίου από ήδη απομονωμένη ακολουθία bit. Δεν εκτελεί τον Kick Assembler ούτε εξομοιώνει τον 8502, τα αθροίσματα ελέγχου NMEA, την κωδικοποίηση μεταφοράς έξι bit ή τον χειρισμό κατακερματισμένων μηνυμάτων. Οι ομάδες bit διευκολύνουν την ανάγνωση· ένα πραγματικό πεδίο μπορεί να αρχίζει μέσα σε χαρακτήρα μεταφοράς. Οι τιμές είναι ενδεικτικές. Οι έλεγχοι εύρους αφορούν το πλάτος αποθήκευσης, όχι όλους τους κανόνες εγκυρότητας του πρωτοκόλλου.
06 / ΑΛΛΑΞΤΕ ΤΗΝ ΠΕΡΙΓΡΑΦΗ
Νέο πεδίο χωρίς νέα ρουτίνα εξαγωγής.
Για νέο πεδίο με υπάρχουσα κωδικοποίηση, ορίστε τη μορφή του και τοποθετήστε την αναφορά περιγραφέα στο σωστό σημείο του μηνύματος. Οι κοινοί χειριστές γνωρίζουν ήδη πώς να καταναλώνουν το δηλωμένο πλήθος bit και να παράγουν τα ζητούμενα byte.
- Περιγράψτε το πεδίο. Δώστε όνομα, πλάτος εισόδου, μέγεθος εξόδου και έναν υποστηριζόμενο τύπο.
- Τοποθετήστε το στην πραγματική διάταξη μηνύματος. Ακολουθήστε τη σειρά και τα πλάτη πεδίων του αποστολέα, μαζί με ενδιάμεσα εφεδρικά bit. Ενημερώστε και την αντίστοιχη λίστα υπολογισμού μετατοπίσεων και μεγεθών.
- Ελέγξτε όσους χρησιμοποιούν τα δεδομένα. Εξασφαλίστε αρκετό χώρο στις περιοχές αποκωδικοποίησης και στα αποθηκευμένα φορτία. Ελέγξτε επιλογείς πεδίων, μορφοποίηση, κλίμακα και κανόνες διαθεσιμότητας. Ανακατασκευάστε μαζί πίνακες και κώδικα που εξαρτώνται από αυτούς.
- Επαληθεύστε ένα γνωστό μήνυμα. Ελέγξτε το νέο πεδίο και όσα ακολουθούν: λάθος πλάτος μετακινεί τα όρια όλων των επόμενων πεδίων.
Η σειρά διάσχισης του καταλόγου δεν είναι η σειρά πεδίων του πρωτοκόλλου. Οι διατάξεις μηνυμάτων την ορίζουν ρητά. Οι παραγόμενοι δείκτες περιγραφέων τροφοδοτούν και τους επιλογείς BASIC, άρα νέες εγγραφές απαιτούν έλεγχο των αντίστοιχων σταθερών του περιβάλλοντος.
Το επαναχρησιμοποιήσιμο μέρος είναι ο μηχανισμός εξαγωγής. Μια νέα κωδικοποίηση ίσως χρειαστεί νέο χειριστή και μια υπό συνθήκη διάταξη πρόσθετη λογική. Η στατική αναφορά τύπου 24 έχει ήδη ξεχωριστή διαδρομή φορτίου υπό συνθήκη. Οι περιγραφές διευκολύνουν την επέκταση, χωρίς να κρύβουν αυτές τις ευθύνες.
07 / Η ΙΔΕΑ ΤΑΞΙΔΕΥΕΙ
Από τα σκάφη στα αεροσκάφη.
Ας υποθέσουμε ότι η επόμενη εφαρμογή παρακολουθεί αεροσκάφη. Θα περιγράφαμε αναγνωριστικό, ύψος, ταχύτητα εδάφους, θέση και διεύθυνση, και θα οργανώναμε τα πεδία στις απαιτούμενες διατάξεις μηνυμάτων. Κοινές ρουτίνες θα εκτελούσαν πάλι την επαναλαμβανόμενη εξαγωγή.
Υπάρχει ήδη μικρό παράδειγμα στην εφαρμογή: το μήνυμα AIS τύπου 9 περιγράφει αεροσκάφη έρευνας και διάσωσης. Η διάταξή του χρησιμοποιεί το altitude μαζί με γνώριμα πεδία όπως ταχύτητα, μήκος, πλάτος και πορεία. Το διαδραστικό παράδειγμα ύψους χρησιμοποιεί αυτόν τον πραγματικό περιγραφέα:
.eval allFiledsHT.put("altitude",aField(12,2,uInt))Μια ροή αεροσκαφών με άλλο πρωτόκολλο, όπως το ADS-B, θα χρειαζόταν και την αντίστοιχη πλαισίωση, κωδικοποίηση και ερμηνεία. Η μεταφέρσιμη ιδέα είναι να περιγράφουμε διατάξεις πεδίων και να επαναχρησιμοποιούμε τον μηχανισμό αποκωδικοποίησης όπου το επιτρέπει η κωδικοποίηση.
Κατασκευασμένο με Kick Assembler
Ευχαριστούμε τον Mads Nielsen για τον Kick Assembler. Το scripting και οι δομές δεδομένων του κάνουν δυνατές τις περιγραφές πεδίων και τους παραγόμενους πίνακες.
- Ιστότοπος Kick Assembler και επίσημο εγχειρίδιο.
- decoderHeaders.asm — κατάλογος πεδίων, περιγραφείς, διατάξεις μηνυμάτων και βοηθήματα μετατοπίσεων.
- decoder.asm — ο κοινός αποκωδικοποιητής και οι χειριστές πεδίων.
- Ρωτήστε την ML, πάρτε τιμή BASIC: USR — πώς το περιβάλλον διαβάζει ένα αποκωδικοποιημένο πεδίο.
- Από έναν ακέραιο AIS στον FAC — μετατροπή αποκωδικοποιημένου ακεραίου σε αριθμό BASIC.
Τα αποσπάσματα διατηρούν τα αναγνωριστικά και τις εντολές της εφαρμογής, παραλείποντας τον γύρω κώδικα και απλοποιώντας τα κενά. Εξηγούν την υπάρχουσα έκδοση· δεν αποτελούν αυτόνομο αποκωδικοποιητή. Οι σύνδεσμοι κώδικα ακολουθούν το main.