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 : Amiga E - un programme auto-détachant
(Article écrit par Pierre Girard et extrait d'Amiga News - juillet/août 1997)
|
|
Pour les deux longs mois d'été à venir, je vous ai concocté un programme un peu spécial. Celui-ci ne fait rien de particulier
(il ouvre une fenêtre), excepté qu'il se détache du Shell. J'espère qu'il va vous plaire et vous être utile parce que je pensais
que sa réalisation serait plus facile que cela.
Prologue
Qui n'a pas hurlé en s'apercevant qu'un programme, très utile au demeurant, bloquait purement et simplement le Shell à partir
duquel il avait été lancé ? Il existe des solutions. Si l'on utilise CSH, il suffit de taper nom_du_programme& et le problème
est réglé sinon, on peut utiliser "run".
Cependant, pour toutes les personnes désirant élaborer de petits programmes auto-détachants, il faut s'atteler à la tâche qui
n'est pas expliquée dans les documentations officielles, genre RKRM.
Le lapin, le lapin !
Nous atteignons ici le deuxième effet de cet article, à savoir les différentes solutions qui s'offrent à nous. Il y en existe
plusieurs mais il faut nuancer. Ainsi, si l'on programme en assembleur, c'est la simplicité même. Il suffit de définir plusieurs
sections dans son programme (qui deviendront des segments dans le fichier exécutable), de "couper" la liste des segments afin que
l'Amiga croit qu'il n'y en a qu'un, d'initialiser un "process" (avec CreateNewProc() ou CreateProc()) dont le début est la
deuxième section. Il suffit ensuite de quitter avec un RTS, ce qui permet de signaler au Shell que l'on rend la main (après,
bien sûr avoir libéré la mémoire allouée, fermé les bibliothèques dont on ne se sert plus, etc.).
Il y a une autre méthode qui consiste en quelque sorte à faire une copie de notre programme en indiquant dans les tags passés
à la fonction CreateNewProc() l'adresse du premier segment de notre programme.
Ma méthode
Elle est un peu limitative, mais je pense qu'elle convient très bien pour de petits programmes comme ceux que nous avons l'habitude
de voir dans notre revue préférée. Ici, l'astuce consiste non pas à donner à CreateNewProc() l'adresse d'un segment, mais directement
une adresse à l'intérieur de notre programme. En clair, la portion de notre programme qui continuera à fonctionner n'est autre qu'une
procédure.
Dans le détail
Notre programme contient quatre procédures : main() qui ne sert qu'à lancer un autre processus, debut() qui est la procédure
appelée par CreateNewProc(), savea4() et loada4(). Ces deux dernières servent à sauvegarder puis à recharger la valeur du
registre a4 qui sert au compilateur E à adresser les variables globales (a5 pour les variables locales). C'est une étape par
laquelle il est indispensable de passer, sinon le méchant Guru risque de venir vous rendre visite. ;)
Tout d'abord, il nous faut remplir une structure process concernant notre tâche. Pour rappel, une structure process est une
structure task contenant des informations supplémentaires. On pointe sur execbase, puis sur la tâche en cours qui, en l'occurrence,
est la nôtre. Il ne reste plus qu'à déterminer si notre programme a été lancé du CLI (ou du Shell) en vérifiant si CLI
pointe sur une structure commandlineinterface. BADDR() est une macro-commande définie dans dos/dos.m et qui permet de convertir
une adresse BCPL en une valeur utilisable (elle ne fait que multiplier par quatre). Malheureusement pour nous, pauvres programmeurs,
la seule façon de savoir si un champ d'une structure est en fait un pointeur BCPL est de regarder dans les includes assembleur
ou C, car showmodule ne nous l'indique pas.
On aurait pu aussi utiliser la fonction cli() de la dos.library qui retourne un pointeur sur la structure CLI (si elle existe)
mais c'était quand même plus amusant d'aller explorer la structure execbase. Si le programme a été lancé du CLI,
on peut initialiser notre nouveau processus.
Le nouveau processus
Il est initialisé grâce à la fonction CreateNewProc() de la dos.library (je parie que vous aviez deviné). Cette fonction ne
prend qu'un argument, un pointeur sur une structure tags (en E, on peut passer directement les arguments). Je ne décrirai
ici que les tags que nous utilisons : NP_ENTRY est l'adresse de départ du code à exécuter, c'est-à-dire dans notre cas
l'adresse de la procédure debut ({debut}). NP_NAME est un pointeur sur le nom du processus. Je pense qu'il est inutile que je
détaille NP_PRIORITY, quant au flag NP_WINDOWPTR, il sert à s'assurer que c'est bien l'écran par défaut qui sera utilisé en cas
de requête du système. On quitte en rendant la mémoire et la procédure continue à s'exécuter toute seule. Il est à noter qu'il
faut exécuter un Exit() qui rend la mémoire allouée par CreateNewProc(). Je vous laisse essayer tout seul une autre méthode.
Bonnes vacances.
|