Créer un code machine dans le secteur boot

 

Voici un petit programme qui affiche des nounours à l'écran. Les nounours ne sont pas de moi, mais désolé, je ne me souviens pas où j'ai pu prendre l'image du nounours, cela date des années 90, il y a 15 ans...(au moment ou je tape ces lignes...)

Mais bon, je ne fais pas que cela:

Je contrôle aussi l'adresse $42c afin de vérifier qu'il n'y a pas un programme qui aurait détourné la fonction RESET. Si c'est le cas, j'affiche un écran en rouge. (Cependant, s'il y avait un virus, il est déjà trop tard. En effet, le virus est réactivé au RESET et il y a eu un accès disque pour lire le boot. Le virus a donc très certainement écrasé le code du secteur boot pour le remplacer par le sien !).

Enfin la barre espace pour sortir du programme sans attendre la chute de tous les nounours...

Bon maintenant un boot exécutable:

Evidemment le code d'un secteur boot sera du code machine pour le MC68000...

Avant d'installer un programme dans le secteur boot, il faut tout d'abord lire les données techniques de la disquette sur laquelle on veut mettre un boot exécutable: le nombre de piste, secteur, face, ... (voir Secteur BOOT).

Ensuite, on prépare un nouveau secteur boot avec les infos que l'on vient de lire + le code machine et quelques manip. pour rendre le code exécutable.

Enfin on enregistre le nouveau secteur boot.

 

Dans le détail, cela donne:

Le code machine peut-être stocké dans le secteur boot à partir de l'offset $1E (30) et il doit normalement s'arrêter avant l'offset $01FE. Ce qui ne nous laisse que 480 octets de disponible. La taille disponible pour un programme est donc plutôt mince...

J'utilise pour mon exemple DEVPAC qui permet de coder comme on le désire contrairement à d'autres assembleurs qui remplacent nos instructions par d'autres normalement optimisées au moment de l'assemblage...

Le fait de pouvoir indiquer le codage de l'instruction va me permettre de forcer l'utilisation d'instructions occupand un minimum de place.

De plus, nous ne pouvons pas savoir à l'avance où le code sera chargé en mémoire. Le code devra donc être 100% relogeable, donc pas de référence à des adresses fixes comme pourrait le faire JMP, label mémoire au niveau du code du boot. Bien sûr, le reste (vecteurs, et autres adresses officielles d'Atari) étant utilisable normalement.

Les manip. à faire au niveau du secteur boot:

Il doit y avoir un BRA.S suivi de l'offset du début du code - 2 sur les deux premiers octets du boot. En effet, si le système détecte qu'il y a un boot exécutable sur la disquette, celui-ci exécute le programme du secteur boot à partir de l'offset 0.

Pour calculer la valeur du branchement:

En tant normal, on calcul le déplacement de la manière suivante: compter les octets entre l'instruction BRA et là où l'on veut aller. Il ne faut pas compter le BRA.s valeur qui font 2 octets lorque l'instruction est codé en machine (le code instruction et la valeur du saut). En effet, si on imagine le programme en cours d'exécution, lorque le 68000 exécute le "BRA déplacement" a son PC (Program counter, registre indiquant où se trouve la prochaine instruction à exécuté) déjà positionné sur l'instruction suivante, il faut bien lire l'instruction avant de l'exécuter !

Le code dans l'exemple débutera à l'offset $1E. Ce qui nous donne donc 28 octets entre le BRA valeur et la première instruction = $1C or $1E-2=$1C (normal, on commence à l'offet 0). l'instruction BRA.S se code $60. Les deux premiers octets seront donc ici à $60 $1C

Enfin, il y a un nombre magique à connaître: $1234. Cette valeur indique que la disquette contient un code machine a exécuter au moment du boot.

Comment ça marche ?

En fait, il faut faire la somme de tous les mots (2 octets) du boot (donc sur les 512 octets).

Cette somme fait une certaine valeur sur 32 bits dont la partie basse sur 16 bits doit faire $1234.

Au moment de l'enregistrement du code dans le secteur boot, on utilise les deux derniers octets du boot ($1FE et $1FF) pour permettre d'atteindre cette valeur $1234 et équilibrer ainsi le boot, le rendant exécutable...

Donc pour le calcul:

Si la somme = $1234, on va mettre 0 dans $1FE et $1FF

Si la somme < $1234 alors on fais la différence entre $1234 et la somme calculer. Cette différence sera stockée dans $1FE et $1FF

Par exemple, la somme = $1000 Pour obtenir l'équilibre du boot on enregistrera $1234 - $1000 = $234.

Si la somme est > $1234, et bien il faut faire un tour complet de compteur ou si vous préférez comme autre explication (peut-être plus simple), retirer la valeur en trop.Ce qui se traduit par: $10000 (le tour complet) + $1234 - somme, ou deuxième explication: $1234 - somme = un nombre négatif or un nombre négatif sur un ordinateur s'écrit en complément à 2.

Rappel, le complément à deux : Il suffit d’inverser tous les bits. Sur ce nouveau nombre, on ajoute 1.

Par exemple, la somme = $1235 ce qui nous fait 1 de trop. $11234 - $1235 = $FFFF ou

$1234-$1235 = -1 or -1 en complément à deux donne:

1 inversé sur 16 bits = %11111110

On ajoute 1, ce qui nous donne %11111111 = $FFFF . -1 s'écriera donc $FFFF en complément à deux !

0001001000110101

Voici le code assembleur du boot à installer:

Image non trouvée !

Contient le programme puis trois fichiers pour former l'image du nounours.

Enfin, un programme (en GFA BASIC) pour enregistrer ce code dans le secteur boot:

Image non trouvée !

 

Dans notre programme, on va donc lire le secteur boot. Puis installer le BRA.S vers l'offet $1C. Faire la somme des mots de l'offset 0 à 508 inclus. Calculer la valeur pour équilibrer le secteur boot et enregistrer cette valeur sur l'offset 510 et 511. On enregistre alors le nouveau secteur boot.

 

Voilà. On pourra ensuite se créer un programme permettant d'enregistrer les différents boots dans un fichier.

Avec ce fichier "éprouvette", vous pourrez restaurer ou analyser les disquettes et donc détecter les boots contaminés par des virus, des boots loader, des boots marrants...

J'avais fait ce genre de code en gfabasic, mais pas moyen de remettre la main dessus. Je le referai peut-être ?