Χρησιμοποιώντας τις resload_Protect#?
Θεωρία
Υπάρχουν διάφορες περιπτώσεις στις οποίες ίσως είναι πολύ χρήσιμο να πληροφορείστε
όταν το εγκατεστημένο πρόγραμμα έχει προσβάσεις σε συγκεκριμένες περιοχές μνήμης.
Με τις συναρτήσεις resload_Protect#?
είναι δυνατόν να προστατευτούν μερικές περιοχές μνήμης από ανάγνωση και/ή εγγραφή από
τον επεξεργαστή. Προστασία σημαίνει ότι κάθε πρόσβαση σε τέτοια προστατευόμενη περιοχή
θα δημιουργήσει μία εξαίρεση Access Fault που θα έχει σας αποτέλεσμα έναν
αντίστοιχο επιλογέα από το WHDLoad. Αν ορίσετε μία περιοχή μνήμης ως προστατευόμενη
χρησιμοποιώντας τη συνάρτηση resload_Protect#?
το WHDLoad θα τροποποιήσει τις περιγραφές των επηρεαζόμενων σελίδων στο δέντρο μετάφρασης του MMU.
Τώρα κάθε πρόσβαση στη προστατευόμενη σελίδα από το CPU θα δημιουργήσει μία εξαίρεση Access Fault.
Ο χειριστής εξαιρέσεων μέσα στο WHDLoad θα επιβεβαιώση το λόγο για την
εξαίρεση. Αν ο λόγος ήταν μία πρόσβαση σε προστατευμένη σελίδα αλλά η πρόσβαση
δεν ταιριάζει με την προστατευόμενη περιοχή η πρόσβαση θα εξομοιωθεί, και θα
συνεχιστή η κανονική εκτέλεση του προγράμματος. Διαφορετικά το WHDLoad θα τερματιστεί με έναν κατάλληλο
επιλογέα. Αν η πρόσβαση ήταν μία πρόσβαση στη ροή εντολών (π.χ. το cpu
προσπαθεί να φορτώσει κώδικα) θα εξομοιωθεί πάντα, ή με άλλα λόγια οι συναρτήσεις resload_Protect#? επηρεάζουν μόνο ανάγνωση και εγγραφή δεδομένων.
Το γεγονός ότι κάθε πρόσβαση σε προστατευόμενη σελίδα
(το μέγεθος σελίδας προς το παρόν είναι $1000) θα δημιουργήσει ένα σφάλμα πρόσβασης,
ακόμα και αν η προστατευόμενη περιοχή έχει μήκος μόνο 1 byte, έχει ως αποτέλεσμα μια
σημαντική καθυστέρηση της ταχύτητας εκτέλεσης του προγράμματος. Ειδικά αν κομμάτια του κώδικα βρίσκονται
στην ίδια σελίδα. Αν το πρόγραμμα εξαρτάται από την ταχύτητα εκτέλεσης, είναι πιθανές
οι διαφορές στην εκτέλεση. Οπότε είναι πιθανόν μερικά προγράμματα να μην λειτουργήσουν
με το χαρακτηριστικό προστασίας.
Παράδειγμα: checksums πάνω σε κώδικα
Αν εγκαταστήσετε ένα παιχνίδι χρησιμοποιώντας το WHDLoad πρέπει να διορθώσετε τις αρχικές
ρουτίνες του loader στο παιχνίδι με τέτοιο τρόπο ώστε να χρησιμοποιούν το WHDLoad για να φορτώσουν
τα δεδομένα του παιχνιδιού. Μερικά παιχνίδια πραγματοποιούν checksums πάνω σε συγκεκριμένες περιοχές κώδικα
για να ανακαλύψουν αν ο αυθεντικός κώδικας έχει αλλαχθεί. Αυτές οι ρουτίνες ελέγχου μπορεί μερικές φορές
να είναι δυσεύρετες. Αλλά χρησιμοποιώντας τις συναρτήσεις resload_Protect#? στο WHDLoad
τίποτα δεν είναι ποιό εύκολο από αυτό. Το μόνο που πρέπει να κάνετε είναι να προστατέψετε τα bytes
που αλλάξατε στο κώδικα του παιχνιδιού από ανάγνωση. Τώρα κάθε ρουτίνα που προσπαθεί να κάνει
ένα checksum και να διαβάσει το διορθωμένο κώδικά σας θα προκαλέσει ένα σφάλμα πρόσβασης. Και θα ξέρετε
που βρίσκεται η ρουτίνα.
Περιορισμοί
Δεν πρέπει να προστατέψετε τη σελίδα μνήμης στην οποία δείχνει το SSP. Αν το κάνετε,
και παρουσιαστεί μία Εξαίρεση, θα έχει ως αποτέλεσμα ένα Double Bus Fault γιατί το CPU
δεν θα μπορεί να γράψει το stackframe εξαιρέσεων. Μετά από ένα Double Bus Fault
μόνο ένα reset μπορεί να συνεχίσει την εκτέλεση. Το WHDLoad ελέγχει για
σύγκρουση των προστατευόμενων περιοχών με το SSP και τερματίζεται αν υπάρξει, αλλά αυτό
δεν θα βοηθήσει αν το SSP αλλάξει μετά.
- 68020 + 68851
- αυτό το hardware δεν υποστηρίζεται προς το παρόν
- 68030
- Μεταφορές 3-Byte δεν υποστηρίζονται και θα δημιουργήσουν ένα πραγματικό σφάλμα Access Fault,
τέτοιες μεταφορές θα γίνουν αν ένα longword σε μία μονή διεύθυνση στο όριο μίας σελίδας
προσπελαστεί (π.χ. "
tst.l ($fff)
" όπου η σελίδα στη $1000 είναι προστατευμένη),
επειδή αυτό είναι άκυρο σε έναν 68000 μάλλον δεν θα δείτε ποτέ κάτι
τέτοιο
- κλειδωμένες μεταφορές που προκαλούνται από
tas
, cas
ή cas2
δεν υποστηρίζονται και θα
δημιουργήσουν πραγματικό σφάλμα Access Fault, δεν είναι πρόβλημα γιατί οι κλειδωμένες μεταφορές δεν
υποστηρίζονται σε Amiga hardware
- 68040
- αυτό το hardware δεν υποστηρίζεται προς το παρόν
- 68060
- μη-ευθυγραμμισμένες προσβάσεις ροής δεδομένων δεν υποστηρίζονται και θα δημιουργήσουν
πραγματικό σφάλμα Access Fault, μία μη-ευθυγραμμισμένη πρόσβαση είναι μία πρόσβαση που αποτελείται από δύο σελίδες (και
τουλάχισοτν μία ή και οι δύο είναι προστατευμένες), για παράδειγμα "
tst.l ($ffe)
" επηρεάζει τη σελίδα
$0..$fff και τη σελίδα $1000..$1fff, αυτός ο περιορισμός είναι πραγματικό πρόβλημα και θα
κάνει το χαρακτηριστικό resload_Protect σχεδόν άχρηστο μερικές φορές, ίσως να προσπαθήσω
στο μέλλον να το υποστηρίξω αλλά είναι δύσκολο.
- μη-ευθυγραμμισμένες προσβάσεις ροής εντολών δεν υποστηρίζονται και θα δημιουργήσουν
πραγματικό σφάλμα Access Fault αν και οι δύο επηρεαζόμενες σελίδες είναι προστατευμένες, τις περισσότερες φορες
τέτοια περίπτωση πρέπει να είναι δυνατό να αποφευχθεί.
- οι κλειδωμένες μεταφορές που προκαλούνται από
tas
ή cas
δεν υποστηρίζονται και θα
δημιουργήσουν πραγματικό σφάλμα Access Fault, δεν είναι πρόβλημα γιατί οι κλειδωμένες μεταφορές δεν υποστηρίζονται
ούτως ή άλλως από Amiga hardware
- ντολές που μένουν σε προστατευόμενη σελίδα (και οπότε θα
εξομοιωθούν) και προσπελαύνουν το κομμάτι supervisor του καταχωρητή status θα
εκτελεστούν λανθασμένα, αυτές οι εντολές θα βλέπουν πάντα το trace bit ως 1
και τη μάσκα προτεραιότητας του interrupt ως 7, κάθε τροποποίηση του κομματιού supervisor
θα είναι χωρίς αποτέλεσμα (δηλ. το κομμάτι supervisor θα παραμείνει
απαράλαχτο)
- η εντολή
movem
μπορεί να προσπελάσει μία προστατευόμενη περιοχή χωρίς να δημιουργήσει εξαίρεση Access
Fault, αυτό είναι δυνατό γιατί μόνο η πρώτη πρόσβαση (word ή longword) θα επιβεβαιωθεί
για ταίριασμα με την προστατευόμενη περιοχή
- η εντολή
move16
και οι λειτουργίες διπλής ακρίβειας (FPU) δεν υποστηρίζονται και θα
δημιουργήσουν ένα πραγματικό σφάλμα Access Fault
- μία "
move (mem),(mem)
" με επικαλυπτόμενες διευθύνσεις πηγής και προορισμού που
δημιουργεί ένα σφάλμα Access Fault λόγο μη-ευθυγράμμισης θα εκτελεστεί λανθασμένα,
για παράδειγμα "move.l ($ffc),($ffe)
" όπου η σελίδα $1000..$1fff είναι προστατευόμενη και
η μνήμη πριν την εκτέλεση περιέχει ($ffc)=$11112222, ($1000)=$33334444, μετά την
εκτέλεση η $1000 περιέχει $11114444 και όχι $22224444