En effet, le langage d'assemblage est la solution aux problèmes les plus pointus sur PC.
On peut se débrouiller avec les outils de mise au point tels DEBUG et SID mais posséder un assembleur comme MASM est préférable. Je peux vous donner un exemple d'un utilitaire résident écrit sommairement : il n'affiche aucun message, ne possède aucun paramètre, ne vérifie pas s'il est déjà installé et ne propose pas de se retirer de la mémoire. J'expose mon problème.
UTILISER L'IBM BASIC A3.40 SUR UN COMPATIBLE
En théorie,
IBM BASICA (Advanced BASIC) nécessite un BASIC de ROM que seuls les micros IBM possédaient.
Les autres micros, qu'on nomme les compatibles, doivent se contenter de son homologue GW-BASIC.
Cependant, il existe une solution simple pour lancer la
version 3.40 livrée avec
PC/DOS 5 sur un compatible. Celle-ci, qui posséde du code supplémentaire par rapport aux versions d'avant, demande l'adresse du BASIC de ROM à la fonction 22h de l'interruption 15h du BIOS. Si la fonction n'est pas supportée, l'interpréteur considère que la ROM se situe à l'adresse F600:0000h habituelle. D'ailleurs, il faut noter que cette version de BASICA recopie la ROM au sommet de la mémoire conventionnelle. Pour les autres versions, la solution est plus complexe, mais il existe un utilitaire, RUNBASIC.COM, à utiliser sur un micro IBM afin de créer le programme résident ROMBASIC.COM destiné aux compatibles. (
http://www.cnd.org/HYPLAN/yawei/freesoft.html).
Il nous reste donc à obtenir la ROM BASIC sous forme de fichier, la charger en mémoire, noter son emplacement et détourner l'interruption 15h.
Au passage, on modifie le vecteur de l'interruption 18h pour qu'il pointe cet emplacement, comme c'est le cas sur les machines IBM. Il se trouve à l'adresse 0:60h (18h x 4).
La solution est de créer un programme résident (TSR,
Terminate and Stay Resident) qu'on nommera BASICTSR.COM.
On procède en quatre étapes. Le code d'assemblage sera tapé avec un logiciel de mise au point tel DEBUG fourni avec MS/DOS et PC/DOS ou SID, accompagnant DR DOS.
1) Télécharger le BASIC de ROM qu'on renommera IBMBAS11.ROM à cette adresse:
http://www.hampa.ch/pce/rom/ibm-basic-1.10.rom
2) Créer la partie résidente du programme, DEBUT.COM, qui remplace l'interruption 15h pour traiter la fonction 22h et lui donne la main dans les autres cas. Cette fonction fonctionne ainsi :
Entrée :
AH = 22h
Sortie :
- si fonction non supportée,
CF (carry flag) activé
AH = 86h
- sinon (dans le cas de certains PS/2),
CF désactivé
AH = 0
ES:BX : adresse de la ROM BASIC
3) Créer la partie non résidente du programme, FIN.COM, servant à son installation.
4) Regrouper les fichiers DEBUT.COM, IBMBAS11.ROM et FIN.COM en un fichier unique, BASICTSR.COM.
Ce qui donne en pratique :
* Créer DEBUT.COM (important de préciser une extension .COM pour SID vu qu'il permet d'écrire aussi des exécutables .EXE)
DEBUG < DEBUT.TXT SID < DEBUT.TXT
Avec comme contenu de DEBUT.TXT,
a100
JMP 8120
CMP AH,22
JNZ 011B
POP AX
POP BX
POPF
CLC
PUSHF
PUSH BX
PUSH AX
MOV AX,CS
ADD AX,0012
MOV ES,AX
XOR AX,AX
XOR BX,BX
IRET
JMP 0000:0000
n debut.com wdebut.com,100,11f
r cx q
20
w
q
* Créer FIN.COM
DEBUG < FIN.TXT SID < FIN.TXT
Avec comme contenu de FIN.TXT,
a100
MOV AX,3515
INT 21
MOV [11C],BX
MOV [11E],ES
MOV AX,2515
MOV DX,107
INT 21
LEA DX,[120]
MOV AX,DS
MOV CL,4
SHR DX,CL
ADD AX,DX
XOR DX,DX
MOV ES,DX
ES:
MOV [60],DX
ES:
MOV [62],AX
MOV DX,8120
INT 27
n fin.com wfin.com,100,132
r cx q
33
w
q
* Concaténation binaire :
COPY /B DEBUT.COM + IBMBAS11.ROM + FIN.COM BASICTSR.COM
|
Une fois le TSR créé, on peut le commenter :
; Tout programme .COM commence à l'offset 100h vu que les 256 premiers octets
; appartiennent au PSP.
; Une adresse de type segment:offset peut s'écrire de plusieurs façons :
; 1234:3210 équivaut à 1200:3550 ou 1555:0000, etc.
; Le nouveau vecteur de l'int 15h pointe sur CS:0107.
0100 JMP 8120 ; Va à l'installation
0103 CMP AH,22 ; Fct 22h (localiser BASIC) ?
0106 JNE 0114 ; Si non, va à l'anc. int 15h
0108 POP AX ; Dépile le segment & l'offset
0109 POP BX ; de l'appelant pour restaurer
010A POPF ; le registre Drapeaux
010B CLC ; Bit de retenue à zéro
010C PUSHF ; Sauve le registre Drapeaux
010D PUSH BX ; et restitue l'adresse de
010E PUSH AX ; l'appelant sur la pile
010F MOV AX,CS ; Obtient segment BASIC à
0111 ADD AX,0012 ; partir du segment de code
0114 MOV ES,AX ; ES : segment BASIC
0116 XOR AX,AX ; AX = 0
0118 XOR BX,BX ; BX : offset BASIC
011A IRET ; Retour d'interruption
011B JMP 0000:0000 ; Ira à l'anc. vect. int 15h
0120 (BASIC de ROM ; Débute à un nouveau paragraphe (offset avec
...) ; quartet de droite nul, xxxx:yyy0)
8120 MOV AX,3515 ; Fonction "obtenir vecteur" (int 15h ici)
8123 INT 21 ; ES:BX : vecteur de l'int 15h
8125 MOV [11C],BX ; Stocker d'abord l'offset
8129 MOV [11E],ES ; puis le segment
812D MOV AX,2515 ; Fonction "modifier vecteur" (int 15h ici)
8130 MOV DX,107 ; Offset du nouveau vecteur
8133 INT 21 ; DS:DX donne le nouveau vecteur de l'int 15h
8135 LEA DX,[120] ; DS:DX : adresse de la ROM BASIC
8139 MOV AX,DS ; AX = DS en vue d'une opération arithmétique
813B MOV CL,4 ; CL : nb de bits à décaler à droite
813D SHR DX,CL ; Offset / 16 (le quartet de droite disparaît)
813F ADD AX,DX ; Ajouter le résultat au segment
8141 XOR DX,DX ; DX = 0
8143 MOV ES,DX ; ES = 0
8145 MOV ES:[60],DX ; Offset du vecteur de l'int 18h nul
814A MOV ES:[62],AX ; Segment de l'int 18h ("lancer ROM BASIC")
814E MOV DX,8120 ; Nb d'octets à réserver + 1
8151 INT 27 ; Laisser les DX premiers octets résidents
8153 ; et terminer
|
Maintenant, après l'avoir lancé, vous pouvez extraire le fichier BASICA.CO_ des images des disquettes de PC/DOS 5 qui se trouvent sur le site, le décompresser avec l'utilitaire EXPAND pour obtenir une version de BASICA utilisable sur compatible :
EXPAND BASICA.CO_ BASICA.COM |
Attention toutefois, les interpréteurs IBM ne supportent pas les changements de tâches de Windows ; mieux vaut les lancer sous DOS.
Avec le temps, vous remarquerez les points forts et les points faibles de l'IBM BASICA par rapport à GW-BASIC :
- BASICA permet un changement de pages d'écran en mode graphique réellement utilisable pour des animations (se référer à mes remarques, http://www.win3x.org/win3board/viewtopic.php?f=24&t=5047&start=67);
- BASICA permet l'interception de Ctrl+Pause via le détournement de l'interruption correspondante du BIOS (1Bh) ;
- un programme lancé par GW-BASIC peut se comporter différement entre les différentes versions, même équivalentes, des constructeurs ;
- il arrive que GW-BASIC perturbe l'horloge système du DOS ;
- BASICA possède un peu moins de fonctions (VIEW PRINT par ex.) ;
- BASICA est globalement plus lent ;
- BASICA supporte mal d'être en tâche de fond sous Windows ;
- BASICA nécessite en théorie un micro IBM et non un compatible -- ce n'est plus le cas ici ;
- BASICA ne permet pas de renuméroter les lignes en mode AUTO ;
- le curseur de BASICA passe toujours à la ligne lorsqu'un caractère est inscrit en dernière colonne ;
- sous BASICA, on ne peut définir soi-même une interception via KEY impliquant
la pression d'une touche de curseur ;
- la fonction INKEY$ de BASICA peut faire planter le PC en mode graphique lorsque le gestionnaire DISPLAY.SYS des dernières versions de PC/DOS est installé.
A propos du dernier point, avec certaines cartes VGA, lorsque DISPLAY.SYS est chargé, BASICA et GW-BASIC peuvent ne pas supporter le passage d'un mode graphique 40 colonnes au mode texte 0 (MODE BW40) si la page de codes matérielle n'est pas utilisée (850 au lieu de 437 par ex.). Le plantage semble plus fréquent sous DR DOS.
P.S. : comme je l'ai écrit, le vecteur de l'interruption 18h pointe sur le
BASIC de ROM. Sur les micros IBM, cette interruption était enclenchée lorsque le système ne trouvait pas de disque avec secteur d'amorce -- c'est-à-dire, pas de disquette système dans le lecteur ou pas de secteur de démarrage sur le disque dur. Sur le PC original, on utilisait le BASIC de ROM conjointement au lecteur (ou enregistreur) de cassettes, d'où son autre appelation de
BASIC cassette. Le port cassette disparut des modèles suivants, mis à part le PC Junior, et ce BASIC ne servit alors que pour le diagnostic et comme base pour le
BASIC disque (BASIC.COM) et le
BASIC avancé (BASICA.COM). On pouvait éventuellement l'appelait sous DOS mais le retour n'était pas prévu -- excepté avec l'utilitaire POPBASIC.COM accompagnant RUNBASIC.COM au lien cité plus haut.
Par analogie, BASICTSR.COM fait que ce vecteur pointe une copie en mémoire de ce BASIC après le démarrage du DOS. La seule utilité de cette interruption pour l'utilisateur est de pouvoir lancer ce vieux BASIC par curiosité. Cela ne justifie pas les 33 Ko qu'occupe le TSR. Or, j'ai signalé précédemment que la version 3.40 de BASICA est plus grosse que les autres et qu'elle copie la ROM BASIC en haut de la mémoire conventionnelle. En fait, il s'agit d'une version 4.00 -- celle livrée avec PC/DOS 4 -- qui reconstitue le BASIC C1.10 dont elle inclut une partie des 32 Ko. Il lui manque ainsi les 5120 premiers octets (1400h en hexadécimal) du fait de la limite de taille du format COM. Pour s'en convaincre, modifions BASICTSR.COM :
Avec DEBUG BASICTSR.COM Avec SID BASICTSR.COM
a8150
MOV DX,1520
w wbasictsr.com,100,8154
q q
|
Lançons le TSR modifié sur un compatible : il n'occupe plus que 6 Ko et BASICA 3.40 peut toujours être utilisé. Le seul hic, qui n'en est pas vraiment un, est qu'il n'est plus possible de lancer la copie du BASIC cassette via l'interruption 18h.
Dernier point. Lorsque BASICA est lancé sous Windows 9x, il risque de planter s'il passe en tâche de fond avant de redevenir actif. Pour prévenir cela, créez un raccourci à COMMAND.COM et modifiez ses
Propriétés :
- sélectionnez l'onglet
Divers ;
- mettez la
Sensibilité à l'attente sur
Basse ;
- acceptez et fermez la fenêtre
Propriétes Commandes MS-DOS avec
OK.
Veillez ensuite à utiliser BASICA depuis la fenêtre ouverte par ce raccourci-là et ne tentez pas de lancer une seconde fenêtre avec BASICA simultanément. GW-BASIC n'impose pas toutes ces restrictions.