01 / ΩΣ ΠΟΥ ΒΟΗΘΑ Η ROM
Δύο byte είναι εύκολα. Το AIS χρειάζεται περισσότερα.
Ο C128 διαθέτει ήδη ρουτίνες μετατροπής ακεραίων σε κινητή υποδιαστολή στη ROM της BASIC. Τιμές ενός byte και ακέραιοι 16 bit έχουν έτοιμες διαδρομές μετατροπής:
| Είσοδος | Διαδρομή ROM | Σύμβαση εισόδου |
|---|---|---|
| 8 bit με πρόσημο | $8C68 | Τιμή στον A, από −128 έως 127. |
| 16 bit με πρόσημο | JGIVAYF / $AF03 | Υψηλό byte στον A, χαμηλό στον Y. |
| 16 bit χωρίς πρόσημο | JFLOATC / $AF0F | Υψηλό/χαμηλό byte στα $64/$65, X = $90, carry ενεργό. |
Ένα byte χωρίς πρόσημο επεκτείνεται σε δύο με μηδενικό υψηλό byte· αυτή τη διαδρομή χρησιμοποιεί το fac.asm. Οι τυπικές ρουτίνες δεν δέχονται αυθαίρετο ακέραιο τεσσάρων byte. Η BASIC αναπαριστά μεγαλύτερους αριθμούς και η ROM διαθέτει χαμηλότερου επιπέδου μαθηματικές λειτουργίες, αλλά αυτός ο πίνακας αλμάτων δεν προσφέρει αντίστοιχη είσοδο τεσσάρων byte.
Αναφορές: μετατροπή byte στην καταχώριση ROM · Mapping the Commodore 128, έντυπες σελίδες 231–232.
Το AIS4CBM αποθηκεύει MMSI 30 bit, μήκος 28 bit και πλάτος 27 bit σε τέσσερα byte το καθένα. Η είσοδος μετατροπής ελέγχει το μήκος αποθήκευσης και στέλνει τα μεγαλύτερα πεδία στη δική της ρουτίνα:
lda fragment.fieldLength
cmp #3
bcc !+
jmp big
Επιλογή ρουτίνας ROM στο fac.asm · Οι μακροεντολές κλήσης ROM · Πλάτη πεδίων AIS
02 / ΓΝΩΡΙΣΤΕ ΤΟΝ ΠΡΟΟΡΙΣΜΟ
Ο FAC είναι συσσωρευτής εργασίας.
FAC σημαίνει συσσωρευτής κινητής υποδιαστολής. Είναι ο χώρος εργασίας της BASIC για έναν αριθμό. Η μετατροπή κατασκευάζει τα ακόλουθα μέρη του FAC1 στην πραγματική μηδενική σελίδα:
| Θέση | Περιεχόμενο |
|---|---|
$63 | Εκθέτης με πόλωση· το μηδέν δηλώνει τον αριθμό μηδέν. |
$64–$67 | Τέσσερα byte σημαντικού μέρους, πιο σημαντικό πρώτο, με ρητό αρχικό 1 για κανονικοποιημένη μη μηδενική τιμή. |
$68 | Ξεχωριστό πρόσημο· το bit 7 δηλώνει αρνητικό αριθμό. |
Για θετικό ακέραιο, βρείτε το υψηλότερο ενεργό bit στη θέση p, με αρίθμηση από το 0. Μετακινήστε το στην κορυφή του σημαντικού μέρους των τεσσάρων byte και αποθηκεύστε τον εκθέτη ως 129 + p. Το σημαντικό μέρος αναπαριστά τώρα τιμή από 1 έως μικρότερη του 2· ο εκθέτης δίνει την κλίμακα.
Η αποσυσκευασία ROM επαναφέρει το αρχικό 1 και διαχωρίζει το πρόσημο · Χάρτης μνήμης FAC1, έντυπες σελίδες 41–44
03 / ΑΚΟΛΟΥΘΗΣΤΕ ΕΝΑΝ ΑΡΙΘΜΟ
123456789, byte προς byte.
Χρησιμοποιήστε 123456789 ως ενδεικτική τιμή μεγέθους MMSI. Τα τέσσερα byte εισόδου είναι 07 5B CD 15, πιο σημαντικό πρώτο. Ο περιγραφέας δηλώνει 30 bit, τέσσερα byte, χωρίς πρόσημο. Το υψηλότερο ενεργό bit είναι στη θέση 26.
Η αναζήτηση αφήνει Y = 27, θέση bit με αρίθμηση από το 1. Το πλήθος ολισθήσεων είναι 32 − 27 = 5. Ο εκθέτης γίνεται 129 + 26 = 155 ($9B). Ο FAC1 περιέχει εκθέτη 9B, σημαντικό μέρος EB 79 A2 A0 και πρόσημο 00.
Αν η BASIC αποθηκεύσει αυτή την ακριβή τιμή σε μεταβλητή, τα πέντε byte είναι 9B 6B 79 A2 A0: το θετικό πρόσημο αντικαθιστά το ανώτερο bit. Ο ακέραιος χωρά ακριβώς· η κανονικοποίηση δεν χάνει σημαντικά bit.
04 / Ο ΚΩΔΙΚΑΣ ΤΗΣ ΜΕΤΑΤΡΟΠΗΣ
Εύρεση bit. Ολίσθηση. Ορισμός κλίμακας.
Ακολουθούν αποσπάσματα από το τρέχον src/Include/fac.asm, με απλοποιημένα κενά και χωρίς σχόλια. Μοιράζονται ετικέτες, μεταδεδομένα και μακροεντολές ROM με το υπόλοιπο πρόγραμμα· δεν είναι αυτόνομο αρχείο assembly.
Πριν την αναζήτηση, η big μηδενίζει εκθέτη και πρόσημο, αντιγράφει την είσοδο στο σημαντικό μέρος και τοποθετεί τη μάσκα bit στο δηλωμένο πλάτος. Τα πεδία με πρόσημο ελέγχουν και το bit προσήμου και καλούν Fac1Complement() όταν είναι αρνητικά. Η διαδρομή MMSI χωρίς πρόσημο παραλείπει αυτό το βήμα.
1. Βρείτε το υψηλότερο ενεργό bit
facByte:
!: bit $64
bne calculateExponent
lsr
bne !+
lda #128
inc facByte+1
!: dey
bne !--
jmp reset
Ο A κρατά τη μάσκα bit. LSR τη μετακινεί μέσα στο byte· όταν εξαντληθεί, ο κώδικας ξαναρχίζει από το bit 7 του επόμενου byte. inc facByte+1 τροποποιεί τον τελεστέο διεύθυνσης της BIT. Ο Y παρακολουθεί την εναπομένουσα θέση bit. Αν κανένα bit δεν είναι ενεργό, ο εκθέτης παραμένει μηδέν.
Προετοιμασία, πρόσημο και αναζήτηση αρχικού bit
2. Κανονικοποιήστε το σημαντικό μέρος των τεσσάρων byte
shiftLeft:
{
sty counter+1
lda #32
sec
counter:
sbc #0
tay
!: clc
ldx #3
!: rol workingBuffer+1,x
dex
bmi !+
jmp !-
!: dey
bne !---
rts
}
counter+1 γίνεται η αρχική τιμή Y, οπότε η αφαίρεση υπολογίζει 32 − Y. Κάθε πέρασμα αρχίζει από το λιγότερο σημαντικό byte και περιστρέφει προς το πιο σημαντικό. Το carry μεταφέρει το εξερχόμενο bit από το ένα byte στο επόμενο. CLC πριν από κάθε πέρασμα τεσσάρων byte εισάγει μηδέν στο χαμηλό άκρο· η SEC κάνει την αφαίρεση ανεξάρτητη από το προηγούμενο carry.
3. Αποθηκεύστε τον εκθέτη με πόλωση
calculateExponent:
tya
pha
jsr shiftLeft
pla
tay
dey
sty exponentPower+1
lda #129
clc
exponentPower:
adc #0
sta workingBuffer
jmp reset
Ο αρχικός Y διατηρείται στη στοίβα όσο εκτελείται η ολίσθηση. DEY μετατρέπει την αρίθμηση από το 1 σε δύναμη με βάση το 0. Η τροποποιημένη ADC προσθέτει 129, με το carry ρητά μηδενισμένο. workingBuffer ορίζεται ως $63, ο εκθέτης FAC1.
05 / ΟΙ ΛΕΠΤΟΜΕΡΕΙΕΣ ΠΟΥ ΜΕΤΡΟΥΝ
Ορίστε σαφώς τη σύμβαση εισόδου.
- Το πλάτος σε byte διαφέρει από το πλάτος σε bit. Το MMSI 30 bit καταλαμβάνει τέσσερα byte. Ο περιγραφέας λέει στον μετατροπέα πού να αρχίσει την αναζήτηση.
- Διατηρήστε τη σειρά byte. Εδώ το πιο σημαντικό byte προηγείται. Μια τυπική διεύθυνση 6502 αποθηκεύεται με την αντίστροφη σειρά.
- Χρησιμοποιήστε την πραγματική μηδενική σελίδα. Ο C128 μπορεί να την ανατοποθετήσει.
transεπιλέγει τη σελίδα 0 και επαναφέρει έπειτα τη σελίδα του καλούντος· ο κώδικας που χρησιμοποιεί τον FAC1 πρέπει επίσης να βλέπει τη σωστή σελίδα. - Το carry είναι μέρος του υπολογισμού. Οι ρητές εντολές
SECκαιCLCαπομονώνουν την αφαίρεση, τις ολισθήσεις και το άθροισμα εκθέτη από την προηγούμενη κατάσταση του επεξεργαστή.
Διαβάστε τον κώδικα
Οι σύνδεσμοι δείχνουν στο main του δημόσιου αποθετηρίου GitLab. Οι αριθμοί γραμμών μπορεί να αλλάξουν.
- fac.asm — μεταδεδομένα εισόδου, επιλογή ROM και διαδρομή μεγαλύτερων ακεραίων.
- getDataByField — αντιγραφή περιγραφέα και byte εισόδου, έπειτα άλμα στη
trans. - c128macros.asm — γέφυρες ROM και βοηθητική ρουτίνα συμπληρώματος.
- decoderHeaders.asm — ορισμοί πεδίων MMSI και συντεταγμένων.