Obligement - L'Amiga au maximum

Jeudi 28 mars 2024 - 14:30  

Translate

En De Nl Nl
Es Pt It Nl


Rubriques

Actualité (récente)
Actualité (archive)
Comparatifs
Dossiers
Entrevues
Matériel (tests)
Matériel (bidouilles)
Points de vue
En pratique
Programmation
Reportages
Quizz
Tests de jeux
Tests de logiciels
Tests de compilations
Trucs et astuces
Articles divers

Articles in english


Réseaux sociaux

Suivez-nous sur X




Liste des jeux Amiga

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


Trucs et astuces

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


Glossaire

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


Galeries

Menu des galeries

BD d'Amiga Spécial
Caricatures Dudai
Caricatures Jet d'ail
Diagrammes de Jay Miner
Images insolites
Fin de jeux (de A à E)
Fin de Jeux (de F à O)
Fin de jeux (de P à Z)
Galerie de Mike Dafunk
Logos d'Obligement
Pubs pour matériels
Systèmes d'exploitation
Trombinoscope Alchimie 7
Vidéos


Téléchargement

Documents
Jeux
Logiciels
Magazines
Divers


Liens

Associations
Jeux
Logiciels
Matériel
Magazines et médias
Pages personnelles
Réparateurs
Revendeurs
Scène démo
Sites de téléchargement
Divers


Partenaires

Annuaire Amiga

Amedia Computer

Relec


A Propos

A propos d'Obligement

A Propos


Contact

David Brunet

Courriel

 


Programmation : Assembleur - Les interruptions (et programme Sentinelle)
(Article écrit par Frédéric Mazué et extrait d'Amiga News Tech - décembre 1990)


L'objectif de cet article

Le mois dernier, nous nous sommes entretenus des exceptions du 68000 pouvant être déclenchées par programmation. Aujourd'hui, nous allons aborder un autre type d'exception : les interruptions.

Il n'est pas question de traiter exhaustivement des interruptions dans le cadre d'un petit article comme celui-ci car ce sujet est immense dans le cas de l'Amiga. Nous allons simplement expliquer brièvement ce qu'est une interruption, comment ajouter un serveur d'interruption au système et illustrer ceci par quelques exemples dont un utilitaire... utile.

Qu'est-ce qu'une interruption et à quoi ça sert ?

Vu de l'extérieur, quand un ordinateur exécute un programme, on a l'impression qu'il se consacre totalement et uniquement à ce programme, mais ceci n'est pas vrai, même dans le cas d'une toute petite calculatrice comme l'Atari ST par exemple.

En effet, tout ordinateur a besoin périodiquement de reprendre la main sur le programme qu'il exécute. En ce qui concerne notre Amiga, ceci est nécessaire afin que soient traités convenablement certains événements comme :
  • La reconnaissance d'une touche appuyée au clavier.
  • La mise à jour de la liste Copper.
  • Le déroulement et sélection de points de menu.
  • Le déplacement du pointeur de la souris.
  • Le changement de port fenêtre suivant l'endroit où pointe la souris.
  • L'envoi et réception de messages et de signaux.
  • La commutation des tâches.
  • La fin d'accès disque.
  • La fin de travail du Copper ou du Blitter.
  • Et plein d'autres choses encore.
Nous avons dit plus haut qu'une interruption est également une exception. Précisons : une exception est déclenchée de manière "interne" par programmation. Une interruption est déclenchée de manière externe par envoi de signaux électriques sur les broches IPL0, IPL1 et IPL2 du 68000. Avec trois signaux, il est possible de coder les valeurs de 0 à 7. La valeur 0 (aucun signal) correspond au fonctionnement normal et les valeurs 1 à 7 correspondent donc aux sept niveaux d'interruption dont dispose le 68000.

Peut-être savez-vous que l'Amiga utilise en fait 15 niveaux d'interruption. De ce fait, les signaux issus des différents composants électroniques ne sont pas envoyés directement sur le 68000, mais d'abord regroupés en 7 niveaux par Paula. Lorsque le 68000 reçoit un signal d'interruption, il :
  • Passe en mode superviseur.
  • Empile le PC et le registre d'état.
  • Modifie le registre d'état selon le niveau d'interruption.
  • Saute dans le vecteur d'interruption correspondant au niveau d'interruption.
Comme pour les vecteurs d'exception, les vecteurs d'interruption ne dépendent pas du 68000 mais de l'ordinateur. Sur l'Amiga, chaque routine commence à lire les registres INTENA et INTREQ de Paula afin de retrouver le niveau "Amiga" de l'interruption déclenchée et de poursuivre en conséquence.

Mes explications pourront peut-être paraître sibyllines, mais je ne peux pas entrer dans les détails faute de place.

Programmation d'une routine d'interruption

Comme pour les exceptions, il y a ici deux méthodes : la bonne et la mauvaise. Voyons d'abord la mauvaise. Elle consiste à détourner le vecteur en bas de mémoire sur une routine personnelle, puis à la fin de celle-ci sauter à l'adresse initialement prévue. Cette méthode n'est pas bonne car si plusieurs programmes tentent de faire de même, le chaînage des routines risque d'apporter quelques surprises désagréables. Par contre, cette méthode sauvage conviendra parfaitement aux programmeurs fous qui ne jurent que par les mégas-démos.

La bonne méthode maintenant : programmer un gestionnaire (handler) ou un serveur d'interruption. Nous ne verrons que le cas du serveur, utilisé par les interruptions CIA, Copper, blanc vertical, Blitter, non masquables. Pas de panique, la programmation d'un gestionnaire est identique à celle d'un serveur à quelques détails près. Reportez-vous à la documentation pour en savoir plus.

Une interruption dépend de la structure suivante :

struct Interrupt }
   struct Node is_Node;
   APTR   is_Data;
   VOID (*is_Code)();
   (); }
  • is_Node est un noeud de type NT-INTERRUPT. La priorité du noeud doit être définie entre +127 et -128. Les serveurs sont appelés suivant cet ordre de priorité. Il est également recommandé d'initialiser le pointeur de nom du noeud si l'on risque d'avoir besoin de retrouver le noeud plus tard.
  • is_Data est un pointeur sur le champ de données que bon vous semblera. Son initialisation n'est pas indispensable.
  • is_Code est un pointeur sur la routine à exécuter lors de l'interruption. Pour ajouter ou enlever une telle structure à la liste des serveurs d'interruption, il suffit d'utiliser les routines AddIntServer et RemIntServer d'exec.library.
Lorsque Exec passe la main à notre routine d'interruption, les registres 68000 sont dans l'état suivant :
  • D0 scratch
  • D1 scratch
  • A0 scratch sauf dans un cas
  • A1 pointe sur le champ de données défini dans la structure (scratch)
  • A5 pointe sur la routine d'interruption (scratch)
  • A6 scratch
On voit donc que les registres D2-D7/A2-A4 ne doivent pas être utilisés. Il est évidemment possible, pour les forcenés, d'empiler ces registres, de s'en servir puis de les récupérer sur la pile avant de quitter. On voit également que D0, D1, A6 ne contiennent rien de particulier en entrée et ne doivent, de même que A1 et A5, rien contenir de particulier à la sortie de la routine (c'est ça que veut dire scratch). A0 est un cas à part : il contiendra $dff000 si le serveur est initialisé sur l'interruption blanc vertical avec une priorité supérieure ou égale à 10 et cette valeur ($dff000) devra être conservée en sortie de routine. Pour une priorité inférieure le registre A0 est scratch.

Il faut en outre savoir que si l'on quitte notre routine avec le drapeau Z mis, Exec passera ensuite la main aux serveurs de priorité (de noeud) inférieure pour une même interruption. Si Z n'est pas mis, Exec considère que le traitement de l'interruption est terminé et retourne au mode normal. Pour placer le drapeau Z, il suffit de faire un moveq #0,D0 avant de quitter.

Une routine d'interruption doit se terminer par RTS et non par RTE car c'est Exec qui se chargera de repasser en mode User.

Le premier programme

Le principal étant maintenant dit, nous allons passer tout de suite à la pratique avec le programme Crazy Led. Le seul intérêt de ce programme est de permettre la visualisation des interruptions.

Déroulement du programme :
  • Ouverture de intuition.library.
  • Ouverture d'une fenêtre.
  • Réservation de mémoire pour la structure interruption.
  • Initialisation de la structure.
  • Ajout de la structure à la liste du système.
    (à partir de ce moment, vous verrez la diode d'alimentation clignoter (sans gourou !). En effet, la routine d'interruption bascule l'état de la diode tous les 25 passages, soit toutes les demi-secondes)
  • La tâche est mise en état d'attente.
Puis lorsque le gadget de fermeture de la fenêtre est cliqué :
  • La structure d'interruption est retirée de la liste.
  • L'allumage de la diode est assuré.
  • La mémoire est libérée.
  • La fenêtre est fermée.
  • intuition.library est fermée.
Une petite remarque : le fait de basculer l'état de la diode a également pour effet de basculer l'état du Low-Pass-Filter. Donc utiliser ce programme conjointement avec un programme musical risque de ne pas être une très bonne idée...

assembleur
assembleur
assembleur

Réouverture de la chasse aux virus

Encore un antivirus pensez-vous ? N'y en a-t-il pas suffisamment dans le domaine public ? Eh bien non, car, ici aussi, il est intéressant de repenser le problème et pour éviter que certains ne me lancent le clavier de leur Amiga flambant neuf en pleine figure, je précise tout de suite que finalement ce n'est pas un antivirus "classique" que je vous propose. Analysons la situation :

Les virus

Tous les virus que je connais se "reproduisent" par l'intermédiaire de la réinitialisation de façon à infecter les disquettes de manière inaperçue. Ces programmes s'implantent soit sur le vecteur ColdCapture, soit sur le vecteur CoolCapture, soit installent un module résident (Cf. article Boot Allocator) dans exec.library. Je ne connais pas de virus s'installant sur le vecteur WarmCapture de la même exec.library, mais il est tout à fait possible et facile de surveiller également ce vecteur de la même façon que les autres.

Les premiers virus étaient facilement détectables car présents à un endroit bien précis des disquettes infectées : le bloc d'amorce. Malheureusement, les nouveaux virus dit virus "coquilles" se greffent sur n'importe quel fichier exécutable, ne sont donc pas limités en taille et ne sont pas détectables tant que le virus est inconnu des programmeurs d'antivirus. Toutefois, les virus coquilles doivent, lorsqu'ils sont chargés, s'installer eux aussi sur la réinitialisation afin de pouvoir se reproduire ultérieurement. Là est leur point faible.

Un virus régénérant ses propres vecteurs de réinitialisation sous interruption deviendra difficile à tuer. Un tel virus existe : le très redoutable et dévastateur "Lamer Revenge Virus" par exemple. Attention, ce virus est capable d'attaquer férocement votre disque dur et de vous en effacer tout un répertoire sans coup férir (à vous les erreurs de lecture/écriture !).

Les antivirus

Tous les antivirus de ma connaissance semblent souffrir du même cruel manque d'imagination : ils s'efforcent seulement de détecter les virus déjà connus. Il est certes très intéressant de savoir de quel virus il s'agit, mais évidemment lorsqu'un nouveau virus apparaît, il n'est pas détecté. On se rappelle le désespoir de quelques-uns qui ont été infectés par le "Lamer Exterminator" lors de sa sortie.

Les antivirus connaissant les caractéristiques des virus qu'ils recherchent, examinent quels vecteurs de sauts de bibliothèques ou quels vecteurs de sauts d'interruption ont bien pu être détournés ou encore examinent le haut de la mémoire Chip, car beaucoup de virus s'implantent à adresses fixes à cet endroit. Il y a un hic : certains programmeurs de virus savent programmer correctement un serveur d'interruption, donc sans détourner bestialement les vecteurs. C'est ici encore le cas du "Lamer Revenge Virus".

Si l'on utilise par exemple les antivirus : VirusX et Master Virus Killer qui se veulent pourtant être les meilleurs antivirus du moment, on verra que VirusX sait reconnaître la présence du "Lamer Revenge Virus" mais est incapable de le tuer et que le "Master Virus Killer" nous annonce "virus inconnu en mémoire", ne comprend rien à ce qui se passe car il ne fait qu'examiner la table de sauts d'interruption sans détecter un éventuel serveur suspect, boucle (sans possibilité de reprendre la main) sur son test, et est bien sûr totalement incapable de tuer le virus. L'auteur nous dit même dans sa documentation que pour tuer un tel virus, le mieux est encore d'éteindre la machine (!?). Ceci condidéré, je vous propose une sentinelle.

Sentinelle

Ce programme a pour vocation de combattre les pires virus avec leurs propres armes, non pas en nettoyant les disques infectés comme un antivirus classique, mais en empêchant le virus de s'installer en mémoire. Pour cela, il installe un serveur d'interruption sur le blanc vertical, dont la mission est de vérifier périodiquement (50 fois par seconde) que les vecteurs de réinitialisation (reset) sont inoccupés.

En cas d'occupation d'un vecteur Reset, ce serveur nettoie ledit vecteur et envoie un signal afin de réveiller sa tâche mère. Celle-ci enverra alors une alerte destinée à prévenir l'utilisateur.

La sentinelle peut tuer

En effet, si l'alerte apparaît, il y a deux possibilités :
  • Cliquer sur le bouton de gauche de la souris afin de reprendre la main. Attention, ceci est risqué car la sentinelle ne répare pas les bibliothèques éventuellement modifiées par le virus. Un accès disque peut donc permettre encore au virus d'agir et procurer quelques désagréments.

  • Deuxième possibilité : cliquer le bouton de droite. Cette alternative devient une obligation si le virus détecté se régénère sous interruption car évidemment l'alerte revient tout le temps vous avertir du danger et ne vous laisse pas reprendre la main.
Ceci dit, le meilleur moyen, à mon avis, pour tuer un virus est encore de faire une réinitialisation. Mais non je ne divague pas et vous avez bien lu : faire une réinitialisation et c'est cela que j'appelle combattre un virus avec ses propres armes. Je m'étonne même que personne (à ma connaissance) n'ait pensé à ce moyen pourtant évident. Il n'est évidemment pas question de réinitialisation avec les touches Ctrl-A-A mais d'une réinitialisation programmée comme suit :
  • Interdiction des interruptions. A partir de ce moment, un virus tel que le "Lamer Revenge Virus" ne peut plus se régénérer.
  • Nettoyage des vecteurs Reset. A ce moment, le virus est annihilé en ce qui concerne sa reproduction par la réinitialisation.
  • Les interruptions sont interdites. Si on les autorise à nouveau, le virus risque de réapparaître. D'autre part, il n'est pas possible d'interdire les interruptions sur l'Amiga pendant plus de 250 microsecondes sans risquer le plantage. C'est pour cela que la réinitialisation devient nécessaire. Bien sûr celle-ci doit être correctement programmée, c'est-à-dire comme expliqué dans l'article Faisons une réinitialisation avec le sourire. Cette façon de faire assure la reconstitution de toutes les tables de sauts et à ce moment n'importe quel virus est impitoyablement massacré.
Veillez tout de même à ne pas redémarrer une disquette infectée...

Un virus peut-il déjouer la sentinelle ? Un virus "normal" ne le peut pas. Toutefois, un virus spécialement conçu pour attaquer la sentinelle peut-être embêtant sauf si l'on prend quelques précautions.
  • Un virus peut rechercher la sentinelle à travers la liste des tâches et la liste des serveurs d'interruptions dans le but inavouable d'effacer la tâche et le serveur. Le remède est simple. Trouvez-vous un nom personnel pour ce programme et un nom pour son serveur : un virus ne pourra plus rien trouver car il ne saura pas ce qu'il cherche...

  • Un virus peut rechercher la sentinelle à travers une recherche d'octets. Pour déjouer ceci, il suffit de modifier l'ordre de quelques instructions dans le programme ou encore de rajouter quelques instructions parfaitement inutiles pour déjouer la recherche d'octets.
D'autres méchancetés ?

Un virus peut-il interdire les interruptions ? Non, car cela provoquerait un plantage. C'est d'ailleurs pour cela que la sentinelle s'installe sur le blanc vertical car un programme tentant d'interdire ce niveau d'interruption se fera immédiatement remarquer.

Un virus peut-il éviter de "rendre la main" au serveur de la sentinelle en omettant de positionner le drapeau Z ? Non, car le serveur de la sentinelle est au niveau de priorité maximum et ne pas lui passer la main équivaudrait pratiquement à interdire le blanc vertical ce qui ne passerait pas vraiment inaperçu...

Un virus peut-il détourner un saut d'interruption à son seul profit ? Non, car il devra obligatoirement "sauter" tôt ou tard dans le vecteur légal ce qui va alerter immédiatement la sentinelle...

L'union fait la force

La sentinelle, protection idéale contre les virus coquilles, n'est toutefois pas un antivirus. Vous pouvez, si le coeur vous en dit, la rendre telle en ajoutant les routines que bon vous semblera au programme. Par exemple, vous pouvez activer le drapeau DISKREMOVE de la fenêtre afin d'être prévenu de l'insertion d'une disquette et de pouvoir aller tester son bloc d'amorce, etc. Toutefois, donner libre cours à sa paresse n'est pas vraiment désagréable.

Les VirusX de Steve Tibett étant très bien programmés, je me permets de vous recommander d'en utiliser la dernière version conjointement avec la sentinelle. Ces deux programmes sont tous les deux en état d'attente et leur présence ne se remarque même pas du point de vue du ralentissement de l'ordinateur. Par contre, cette combinaison est remarquablement efficace car à ce jour pas un virus n'a pu me faire le moindre dégât et pourtant ce n'est pas faute d'avoir essayé.

Rien ne doit passer

C'est pour cela que la sentinelle vous tuera impitoyablement le RAD: que vous auriez décidé d'installer. Vous pouvez très facilement modifier la sentinelle si vous voulez qu'elle ne tue pas le RAD: car celui-ci s'installe toujours à la même adresse. Toutefois, vous risquez ainsi de laisser passer un virus qui "imiterait" le RAD:...

Mise en oeuvre de la sentinelle

C'est un programme assembleur qui pourra être lancé à partir du Workbench à condition d'ajouter : include "misc/easystart.i" à la suite des autres instructions include. Néanmoins, il est plus intéressant de pouvoir le lancer en tâche de fond à partir d'un CLI et donc dans une startup-sequence. Pour cela, vous devrez relier les programmes sentinelle.c, sentinelle-asm et le cback du Lattice C ensemble. Je vous expliquerai prochainement comment lancer un programme assembleur en le décrochant du CLI, mais il y a là matière à un article entier. C'est tout pour cette année.

assembleur
assembleur
assembleur
assembleur


[Retour en haut] / [Retour aux articles]