Suivez-nous sur X
|
|
|
0,
A,
B,
C,
D,
E,
F,
G,
H,
I,
J,
K,
L,
M,
N,
O,
P,
Q,
R,
S,
T,
U,
V,
W,
X,
Y,
Z,
ALL
|
|
0,
A,
B,
C,
D,
E,
F,
G,
H,
I,
J,
K,
L,
M,
N,
O,
P,
Q,
R,
S,
T,
U,
V,
W,
X,
Y,
Z
|
|
0,
A,
B,
C,
D,
E,
F,
G,
H,
I,
J,
K,
L,
M,
N,
O,
P,
Q,
R,
S,
T,
U,
V,
W,
X,
Y,
Z
|
|
A propos d'Obligement
|
|
David Brunet
|
|
|
|
Programmation : Assembleur - les routines cachées de l'exec.library
(Article écrit par Xavier Leclercq et extrait d'Amiga News - avril 1991)
|
|
Par routines "cachées" j'entends simplement certaines fonctions d'Exec qui ne sont pas utilisées par les
programmeurs. Non pas parce qu'elles sont difficiles à comprendre mais simplement par manque évident
de documentation de la principale bibliothèque sur Amiga : j'ai nommé l'exec.library. Pourtant certaines
de ces fonctions cachées peuvent se révéler très utiles !
BASIC et token
Lorsque vous tapez PRINT"Coucou" en BASIC, l'instruction PRINT sera interprétée par BASIC qui effectuera
un "saut" à un point d'entrée de la commande PRINT. En fait, PRINT ne s'écrit pas en toutes lettres
PRINT dans le programme mais est tokénisé, c'est-à-dire représenté par un ou deux octets appelés tokens.
Ces derniers, lors de l'interprétation, seront comparés à un tableau de tokens déjà en mémoire et BASIC
associera à chaque token son point d'entrée (début de la routine) en langage machine. Si je prends cet
exemple, c'est tout simplement pour expliquer en parallèle les appels de bibliothèque.
A chaque décalage négatif est associé une adresse de saut à la routine qui lui correspond.
Exemples :
Fonction token-Offset Adresse de saut
BASIC PRINT $91 JMP $9ce2 (GW-BASIC 2.0 sur PC)
Exec TypeOfMem -534 JMP $FC1856 (ROM 1.3)
|
Le décalage négatif est ajouté à l'adresse de base de la bibliothèque qui, comme tout le monde le sait
(du moins je l'espère), prend sa valeur en $4. move.l $4.w,a6 ; execbase en a6. Le tableau de saut
débute, quant à lui, à execbase-$276.
Si vous ouvrez La Bible de l'Amiga à la fin de la section consacrée à Exec, vous pourrez découvrir une
fonction de cette bibliothèque de décalage -612 répondant au nom de "KickSumdata". Jusque-là,
pas de quoi en faire un plat... Mais si vous êtes curieux de nature vous êtes en droit de vous
demander ce qui peut bien se cacher avant et après le décalage -612. En effet, la dernière fonction
référencée connue d'Exec est la fonction OpenLibary() de décalage -552. Chaque appel de fonction
prenant six octets, un rapide calcul vous amène donc à conclure qu'il y exactement neuf fonctions
qui se cachent entre -552 et -612... A ces dernières, je dois encore ajouter trois appels de
fonctions se situant avant le décalage -612 (-618 ; -624 ; -630).
Résultat des courses : 9+3 donne 12 jusqu'à preuve du contraire et c'est donc 12 fonctions dont
la plupart d'entre vous ignorent sans doute tout. Et pour couronner le tout, il existe aussi des routines
en langage machine dont l'appel en ROM 1.2 ou 1.3 est le même et donc pouvant rendre de grands services
quoique sous réserves d'incompatibilités avec le système 2.0 !
Voici le nom et les décalages d'appel des fonctions : [en A6 se trouve Execbasej
- InitSemaphore -558(a6)
- ObtainSemaphore -564(a6)
- ReleaseSemaphore -570(a6)
- AttemptSemaphore -576(a6)
- ObtainSemaphoreList -582(a6)
- ReleaseSemaphoreList -588(a6)
- FindSemaphore -594(a6)
- ProtectedEnQueue -600(a6)
- ProtectedDeQueue -606(a6)
- KickSumData -612(a6)
- AddMemList -618(a6)
- CopyMem -624(a6)
- QuickCopyMem -630(a6)
Quant aux routines Exec n'étant pas repris dans les appels de la bibliothèque j'ai retenu :
- ProcClearMem $fc0602
- ProcFillMem $fc0604 --> ROM 1.2 et 1.3
- ProcFinChip $fc0592
Un moyen rapide de copier les données
Je vais vous expliquer QuickCopyMem, CopyMem, ProcClearMem, ProcFillMem et ProcFinChip.
Le reste est consacré à la gestion des sémaphores dont je parlerai peut-être une autre fois
(pour donner une "image", les sémaphores sont comme des feux de circulation pour les
tâches sous la supervision de l'ordonnanceur).
L'appel de bibliothèque QuickCopyMem est, comme son nom l'indique, un moyen très rapide de
copier des données d'un endroit quelconque de la mémoire à un autre endroit.
CopyMem est pratiquement la même routine mais, avec cette dernière, il est possible de copier
n'importe quelle taille tandis qu'avec QuickCopyMem seulement une taille multiple de quatre
octets est possible. La raison est que CopyMem, après avoir copié le nombre de longs mots,
copiera aussi le nombre d'octets (<4 octets) nécessaires.
La copie, comme je vous l'ai dit, est très rapide grâce à l'emploi de la pile.
Moins rapide qu'avec le Blitter mais avec un énorme avantage en plus : la source
peut-être située en mémoire Fast et la destination en mémoire Chip...
Trois tests successifs sont réalisés suivant la taille des données à copier.
Si la taille est inférieure à 4, la copie est faite octet par octet (CopyMem
seulement). Si la taille est inférieure à 96, la copie est faite long mot
par long mot (move.l). Enfin, si la taille est supérieure à 96, la copie est
réalisée grâce à la pile via les registres.
Voici le coeur de cette dernière routine :
Ces deux dernières routines ont pratiquement le même point d'entrée et sont en
définitive assez courtes. Les voici :
Pour la procédure suivante, je vous dois absolument des explications pour clarifier
la situation. Il s'agit de résoudre le problème suivant : comment déterminer la
mémoire Chip disponible sur mon Amiga et du même coup l'adresse où elle se termine ?
Pour ce faire, Exec utilise une routine qui écrit un "long" tous les quatre kilo-octets
et tente à chaque fois de le relire. En cas d'échec cela marque soit la fin de la
mémoire Chip soit une défection d'un circuit mémoire. Mais un problème se pose.
Il faut obligatoirement que le petit programme qui suit soit assemblé en mémoire Fast
et ceci pour une bonne raison : le programme risquerait de s'autodétruire de lui-même
en étant en mémoire Chip... (parce qu'il écrit une valeur particulière tous les 4 ko).
Une astuce
J'ai de plus utilisé une astuce pour ne pas employer l'appel absolu de la routine en
ROM et pour être certain que la routine ne n'exécutera qu'en mémoire Chip.
En effet, en fixant le l'octet "Overlay", je bascule la ROM en mémoire Chip
(si le programme est situé en mémoire Chip, il continuera alors en ROM et c'est
pour cela qu'il faut le placer en mémoire Fast). En 4, il n'y a donc plus Execbase
mais bien la valeur qu'il y a en $fc0004 (si la ROM est en $fc0000 mais Commodore a
aussi prévu de la placer en $f00000 et pour le A3000, le Kickstart 2.0 peut-être
en $200000 ou bien en $f80000...). Cette valeur est l'entrée de la routine "RESET"
$fc00d2 je n'ai donc plus qu'à l'incrémenter de $4c0 pour retrouver le point d'entrée
de la routine.
Attention au plantage
Attention, cette routine peut parfois planter la machine ! En d0 se trouve le résultat,
c'est-à-dire l'adresse de fin de mémoire Chip et par conséquent (la mémoire Chip
débute en 0), la taille de la mémoire Chip disponible. Après l'exécution,
ne vous étonnez pas de voir apparaître de petites barres horizontales un peu n'importe
où à l'écran, c'est tout simplement le long mot écrit tous les 4 ko !
En fait, cette routine est appelée lors de la routine "RESET" et c'est dans ce
contexte quelle devrait être utilisée. Mais rien n'empêche de l'employer quand
même sous un environnement monotâche.
Maintenant, plus rien ne vous empêche d'utiliser ces fonctions avec abondance. Les
plus largement utilisées resteront sans doute QuickCopyMem et CopyMem. C'est
un gain de place mémoire et de vitesse que vous ne devez plus négliger !
|