Win3x.Org

Windows & DOS Community

Documentation ASM

Répondre   Page 1 sur 1  [ 8 messages ]
Auteur Message
alex7812
Sujet du message : Documentation ASM
Publié : 25 juil. 2010 12:21
Membre d'honneur
Hors-ligne
 
Messages : 157
Inscription : 28 juin 2009 14:32
 
Bonjour à tous,

Je propose un petit sujet pour partager vos connaissances en assembleur.
L'idée ici n'est pas de donner des liens vers des sites extérieurs, mais de mettre des bouts de code en les décrivants pour aider les membres à apprendre ce langage (utile, on est sur win3x et y'a une section de bidouillage d'OS :p).

Geler l'ordinateur :
cli
hlt

Bonne participation ! :D


Haut
Profil Citer
gm86
Sujet du message : Re: Documentation ASM
Publié : 27 juil. 2010 16:57
Membre inscrit
Avatar de l’utilisateur
Hors-ligne
 
Messages : 465
Inscription : 01 sept. 2008 19:07
 
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.


Dernière modification par gm86 le 22 août 2011 19:20, modifié 10 fois.

_________________

C:\ONGRTLNS.W95


Haut
Profil Citer
gm86
Sujet du message : Re: Documentation ASM
Publié : 06 oct. 2010 17:13
Membre inscrit
Avatar de l’utilisateur
Hors-ligne
 
Messages : 465
Inscription : 01 sept. 2008 19:07
 
OBTENIR LA POLICE D'ANCIENNES CARTES VIDÉO À L'ÉCRAN


Je vais vous exposer comment, à partir d'une carte VGA, donner au mode texte un aspect EGA ou CGA.
Il faut savoir que la première carte vidéo d'IBM pour son PC est la MDA suivie de la CGA.
La carte MDA ne propose que le mode texte standard, 80 colonnes et 25 lignes, avec les couleurs remplacées par des attributs de texte (soulignement, vidéo inverse, surbrillance et clignotement). Cependant, sa matrice de caractère de 9x14 et la longue persistance du phosphore du moniteur monochrome à accès direct rendent son affichage net -- mis à part un défilement fantomatique.
La carte CGA propose le texte en 16 couleurs, le mode texte 40 colonnes et des modes graphiques moyenne et haute résolutions pauvres en couleurs -- la basse résolution n'étant pas standardisée. L'écran qui exploite au mieux ses capacités est le moniteur RGB. Si on fait abstraction de la couleur, il est possible d'utiliser un moniteur monochrome composite. Il existe aussi un moniteur composite couleur mais seules certaines combinaisons de couleurs rendent le texte lisible et il vaut mieux parfois désactiver la couleur (MODE BW80). Sa matrice de 8x8 rend la lecture de l'écran fatigante à la longue. Cette carte peut raccorder sa sortie composite à un adaptateur RF mais seules les modes 40 colonnes restent acceptables sur un téléviseur.
Il est possible d'installer les deux cartes dans une même machine car les ports utilisés sont différents et leurs segments de mémoire ne se chevauchent pas : ports 3Dxh et segment B800h pour le matériel couleur, ports 3Bxh et segment B000h pour le matériel monochrome.
La venue de la carte EGA concilia ces deux mondes. D'abord, elle accepte le moniteur du MDA et le moniteur RGB du CGA tout en apportant la gestion 16 couleurs aux modes graphiques. Ensuite, connectée à un moniteur ECD, sa matrice de 8x14 est comparable à celle du MDA. De plus, elle propose alors une résolution graphique de 640x350 avec une palette de 16 couleurs (4 si seulement 64 ko de mémoire sur la carte) choisies sur 64 nuances.
Les circuits VGA et MCGA furent inaugurés sur les PS/2. Ils préfèrent un signal analogique car le signal numérique restreint le nombre de couleurs. La carte VGA fut disponible séparément par la suite.

Une carte VGA peut utiliser ces anciennes résolutions d'écran. Toutefois, le mode monochrome requiert que rien n'empiète sa zone mémoire située au segment B000. Deux fonctions du BIOS sont utiles :
- la fct 00h de l'interruption 10h qui sélectionne le mode graphique ;
- le sous-service 30h de la fct 12h du BIOS VGA.
Voilà leurs détails concernant le mode texte :
INT 10h
Fct 00h
Appel : AH = 00h
        AL = mode vidéo
             00h : 40x25 car., 16 gris si écran composite
             01h : 40x25 car., 16 couleurs
             02h : 80x25 car., 16 gris si écran composite
             03h : 80x25 car., 16 couleurs

INT 10h
Fct 12h - Sous-fct 30h
Appel : AH = 12h
        AL = code du nb de lignes de balayage
             00h : 200 lignes
             01h : 350 lignes
             02h : 400 lignes
        BL = 30h
Retour : AL = 12h si VGA active sinon 00h
Je vous propose de créer quatre fichiers sources à destination de DEBUG pour obtenir quatre utilitaires. Les utilisateurs de SID devront s'inspirer de mon message précédent pour apporter les quelques modifications nécessaires.
D'abord MONO :
N MONO.COM
A
MOV AX,1201
MOV BL,30
INT 10
MOV AX,7
INT 10
RET

R CX
D
W
Q
Ensuite, les trois autres.
CGA80 :
N CGA80.COM
A
MOV AX,1200

A 107
MOV AX,3

W
Q
CGA40 :
N CGA40.COM
A
MOV AX,1200

A 107
MOV AX,1

W
Q
EGA80 :
N EGA80.COM
A 107
MOV AX,3

W
Q
Pour finir, créez un fichier batch ayant ce contenu (ou entrez directement en ligne de commande les lignes concernant DEBUG) :
DEBUG < MONO
IF NOT EXIST MONO.COM GOTO FIN
DEBUG MONO.COM < CGA80
DEBUG MONO.COM < CGA40
DEBUG MONO.COM < EGA80
:FIN
Si tout ce passe bien, vous obtenez les petits utilitaires MONO.COM, CGA80.COM, CGA40.COM et EGA80.COM.
MONO.COM : mode monochrome avec la résolution MDA, 720x350 pixels. Il faut se rappeler que l'écran du MDA a un rapport largeur/hauteur de 1,45 alors que celui du VGA est de 1,33 (4/3).
CGA80.COM : caractères grossiers (au pluriel, bien sûr).
CGA40.COM : gros caractères bien adaptés à la faible résolution de 200 lignes de balayage ; d'ailleurs, ils n'ont pas l'aspect écrasé de ceux d'un affichage EGA ou VGA en mode 40 colonnes.
EGA80.COM : résolution proche du mode MDA et de l'affichage VGA 80 colonnes.
Déduisons le tableau suivant :
                   MDA   CGA   EGA   VGA   MCGA
Modes couleurs
40x25, 320x200            x     r     x      x
40x25, 320x350                  e     x
80x25, 320x400                               x
40x25, 360x400                        x

80x25, 640x200            x     r     x      x
80x25, 640x350                  e     x
80x25, 640x400                               x
80x25, 720x400                        x

Mode monochrome
80x25, 720x350      x           m     x
80x25, 720x400                        x

r : si écran RGB (Red, Green, Blue)
e : si écran ECD (Enhanced Color Display)
m : si écran monochrome à accès direct
Je tiens à souligner que la matrice standard d'un caractère fait 8 pixels de large car chaque ligne qui la constitue tient dans un octet (8 bits). Or, les affichages textes monochrome et VGA ont une matrice de 9 pixels de larges. Le circuit vidéo des cartes MDA, EGA et VGA duplique le 8ème pixel des caractères nécessitant un raccord (C0h à DFh) et utilise la couleur d'arrière-plan dans les autres cas.

Un dernier point.
A part la curiosité, il existe une raison importante de pouvoir modifier le nombre de lignes de balayage : faire que le matériel VGA puisse profiter des modes 43 lignes permis par une carte EGA affichant la police CGA 8x8 sur un moniteur ECD. Ainsi, l'utilitaire MODE43.COM de QuickBASIC 3.0 prévu pour l'EGA affiche 50 lignes de texte sur un moniteur raccordé à un circuit VGA ou MCGA.


P.S. : je n'ai pas voulu encombrer le texte en faisant référence aux cartes professionnelles et non-IBM ainsi qu'à la compatibilité des matériels avec le stylet optique.
De plus, je n'ai pas pris en compte un éventuel gestionnaire d'affichage actif, tel DISPLAY.SYS sous DR DOS 6. Ainsi, pour éviter que moins de 25 lignes soient affichées, il faudra peut-être entrer cette commande :
CHCP 437


Dernière modification par gm86 le 22 mars 2013 12:22, modifié 2 fois.

_________________

C:\ONGRTLNS.W95


Haut
Profil Citer
gm86
Sujet du message : Re: Documentation ASM
Publié : 27 août 2011 21:02
Membre inscrit
Avatar de l’utilisateur
Hors-ligne
 
Messages : 465
Inscription : 01 sept. 2008 19:07
 
UTILISER L'INTERPRÈTE BASIC MICROSOFT STANDARD SOUS DR DOS 6


Première chose, cet interprète BASIC Microsoft pour MS/DOS est un programme au format COM issu de la version disque 5.2x pour le système d'exploitation 8 bits CP/M. Il imite donc l'appel aux fonctions 0 à 24h de la BDOS en mettant le numéro de fonction dans le registre CL avant de procéder à un appel proche à la routine débutant à l'offset 5 (CALL 5). Sous DOS, il s'y trouve un appel lointain dont l'offset de l'adresse indique la mémoire disponible dans le segment du programme (CALL Fxxx:FEF0h le plus souvent). Sous CP/M, cet offset était le point d'entrée du système chargé en haut de la mémoire.
Or cette adresse boucle sur le segment 0 dans le cas d'un processeur 8086 ou 80186 mais continue sur la mémoire étendue (> 1 Mio) dans la cas d'un 80286 ou supérieur avec la ligne d'adressage A20 activée. Dans ce dernier cas, il est impératif que DOS soit chargé en HMA, la zone de mémoire haute qui représente les 64 premiers Kio de mémoire étendue. Cela signifie que FFFFh:10h représente dorénavant le début de cette mémoire et non celui de la mémoire conventionnelle (1er Mio).
Cf. http://blogs.msdn.microsoft.com/larryos ... -of-memory

Seconde chose, je remarque que l'interprète est mal renseigné sur la ligne de commande par DR DOS. Ainsi, si on le lance, il a grande chance de se terminer aussitôt en spécifiant que le programme BASIC — même non spécifié — n'a pu être trouvé :
BASIC-86 Rev. 5.27
[MS-DOS Version]
Copyright 1977-1982 (C) by Microsoft
Created:  8-Nov-82
62025 Bytes free
File not found
Par conséquent, impossible de charger un programme BASIC depuis la ligne de commande voire de lancer l'interprète lui-même.

Sachant que les paramètres de la ligne de commande DOS sont inscrits dans la DTA du logiciel BASIC, il reste à savoir si ce dernier examine bien celle se situant dans son PSP. Pour information, le PSP d'un programme va de l'offset 0 à FFh (255) à partir du segment de code initial et sa DTA débute à l'offset 80h. Il est créé par DOS pour remplir le rôle de la page zéro sous CP/M.
En désassemblant le programme, l'appel à la fonction 26h doit nous mettre la puce à l'oreille. Elle crée un nouveau PSP. Une lecture de la liste de Ralf Brown nous renseigne que DR DOS 6 copie le PSP depuis un mauvais segment :
BUG: DR DOS 6.0 original releases 05/1991 & 08/1991 had a problem where the
     segment from which the PSP was copied was incorrect so that the PSP
     was not filled correctly and did not contain the command tail.  The
     DR DOS 6.0 BDOS patch "PAT312" English (1992/01/07, XDIR /C: A0C6h)
     and later "full" rebuilds fix this problem (see INT 21/AX=4452h).
Un test de cette fonction sous la mise à jour d'avril 92 de DR DOS 6 pour Windows 3.1 nous démontre que la DTA du PSP actif est copiée depuis un segment pointé par le registre FLAG au lieu du registre CS (segment de code) ! Concluons alors que l'interprète BASIC n'examine que la copie.

Remédions à ce problème par un petit programme résident sans prétention, FCT26H.ASM :
; Assemblage :
;       MASM FCT26H;
;       LINK FCT26H;
;       EXE2BIN FCT26H FCT26H.COM
;

CODE    SEGMENT
        ASSUME  CS:CODE, DS:CODE

;------------------;
; Partie résidente ;
;------------------;
        ORG     100h

Depart:
        jmp     Installe

Int21h          dd      (?)             ; Vecteur original de l'int 21h

TSR:
        cmp     ah,26h                  ; Fct créer PSP ?
         je     Suite
         jmp    dword ptr cs:Int21h     ; Se branche à l'int 21h
Suite:
        pushf                           ; Appelle l'int 21h
        call    dword ptr cs:Int21h     ; DX : seg. du PSP suppl.

        push    ax                      ; Sauve les registres modifiés
        push    bx
        push    cx
        push    ds
        push    es

        mov     es,dx                   ; ES : seg. du PSP suppl.
        mov     ah,62h                  ; Obtenir seg. du PSP actif dans BX
        int     21h
        mov     ds,bx
        mov     bx,80h                  ; Adresse normale de la DTA dans un PSP
        mov     cx,[bx]                 ; Le premier octet indique sa longueur
        inc     cx
Copie_DTA:
        mov     ax,[bx]
        mov     es:[bx],ax
        inc     bx
        loop    Copie_DTA

        pop     es                      ; Restitue les registres
        pop     ds
        pop     cx
        pop     bx
        pop     ax


        iret                            ; Retour d'interruption
        
;----------------;
; Partie externe ;
;----------------;
Installe:
        mov     ax,3521h
        int     21h
        mov     word ptr Int21h+0,bx
        mov     word ptr Int21h+2,es
        mov     ah,25h
        mov     dx,offset TSR
        int     21h
        mov     dx,offset Installe
        int     27h

CODE    ENDS

        END     Depart

Une fois ce patch lancé, le programme BASIC peut être lancé depuis la ligne de commande.
Une meilleure solution est de corriger l'erreur toute bête directement dans la BDOS.

Revenant à l'interprète en question, du fait qu'il s'agit d'un logiciel pour DOS 1, il gère les fichiers du répertoire courant via les FCB comme à l'époque du CP/M, et de ce fait, est compatible avec la FAT32 dans une fenêtre DOS de Windows 9x mais pas en mode MS/DOS.
Une version est facilement disponible sur Internet mais semble rechigner à utiliser les fonctions USR : Microsoft BASIC Version 5.28. Préférez donc la première :
http://poisk-pc.narod.ru/basic-86.rar
Je pense que ces outils mériteraient leur propre sujet.



P.S. : une courte notice en anglais de MBASIC se trouve aux liens suivants.
http://www.pldos.pl/bogus/hardware/komp ... sbasic.htm
http://gopherproxy.meulie.net/gopher.fl ... MBASIC.HLP
Une méthode pour pouvoir lister un programme protégé (SAVE"...",P) est présentée ici :
http://maben.homeip.net/static/S100/vic ... ii/APQ.txt
Le guide du BASIC-80 version 5.x vaut pour le BASIC-86, mis à part l'interface avec les routines en code machine qui fonctionne comme celle du BASIC IBM et du GW/BASIC (du moins, sous CP/M-86 et MS/DOS, Xenix étant un cas plus complexe) :
http://www.classiccmp.org/cini/pdf/Microsoft/mbasic.pdf (quelques chapitres sont manquants)
ftp://bitsavers.informatik.uni-stuttgar ... r_1980.pdf
http://www.bitsavers.org/pdf/microsoft/ ... e_1979.pdf
Ainsi, l'architecture du microprocesseur 8086 ou 8088 impose au BASIC-86 l'emploi de l'instruction DEF SEG pour définir le segment de données aux instructions CALL, PEEK et POKE :
DEF SEG [=segment] 'Par défaut, le segment de données du BASIC
D'ailleurs, le BASIC-86 pour MS/DOS apporte quelques extensions :
- les instructions BSAVE et BLOAD qui servent respectivement à enregistrer dans un fichier le contenu d'une zone de mémoire située dans le segment défini par DEF SEG et à effectuer l'opération inverse (en-tête de ce fichier binaire : FDh, segment, offset, longueur) :
BSAVE fichier.ext$, adresse, longueur
BLOAD fichier.ext$[, adresse]

- l'instruction CALLS qui, à la différence de CALL, transmet l'adresse complète des paramètres aux routines en code machine destinés à un autre langage (FORTRAN, par ex.) en déposant le segment après chaque offset sur la pile ;
- le mode ajout (append) aux fichiers séquentiels (chose non permise, de tout façon, sur bande) ;
OPEN "A", [#]tampon, filename.ext$
- une syntaxe alternative de l'instruction OPEN avec l'accès direct comme mode par défaut (random) ;
OPEN filename.ext$ AS [#]tampon [LEN=longueur_enregistrement] (accès direct)
OPEN filename.ext$ FOR {OUTPUT|INPUT|APPEND} AS [#]tampon (accès séquentiel)
- les fonctions DATE (jour de l'année) et TIME (nombre de secondes écoulées depuis minuit) qui ne sont pas reconnues par le compilateur*, ainsi que DATE$ (date au format américain, m/j/a) et TIME$ (heure au format 24h) qui sont aussi des variables :
? TIME$
13:40:06
Ok
? DATE$
01-01-1980
Ok
DATE$="6/26/11"
Ok
? "C'est le"; STR$(DATE); "ième jour de l'année."
C'est le 117ième jour de l'année.
Ok
10 REM Initialise la liste des nombres pseudo-aléatoires
20 RANDOMIZE TIME * 512 / 675 - 32768
- l'usage des caractères codés sur 8 bits (ASCII étendu IBM sur PC) qui évite l'emploi d'un des dérivés codés sur 7 bits de l'ISO/IEC 646 pour représenter les caractères nationaux.
De plus, la fonction LOF(tampon) ne renvoie plus la taille d'un fichier en enregistrements de 128 octets mais en octets seuls. Cependant, l'écriture de blocs de 128 octets perdurent vu que MS-DOS 1 hérite des FCB du CP/M. Ainsi, les fichiers séquentiels comporte obligatoirement le caractère 26 (EOF, End Of File) après le dernier enregistrement.
Cf. http://support.microsoft.com/kb/25996
Les fichiers créés par BSAVE l'ont aussi, bien qu'il faut se fier à la taille donnée dans l'en-tête (mot situé au sixième octet).

Voici deux aides utiles :
Caractères spéciaux dont caractères de contrôle (^touche pour Ctrl+touche) :

^A        Édite la ligne du mode direct en incluant la dernière lecture
^C        Arrête le programme ou le mode AUTO (Ctrl+Attn sinon Arrêt.défil)
^G        Sonne
^H        Place le curseur sur le caractère précédent et le supprime (Ret.arr)
^I        Tabulation toutes les huit colonnes à partir de la première (Tab)
^J        Insère un saut de ligne, car. de continuation, dans une ligne BASIC
^M        Idem que la touche <ENTRÉE>
^O        Désactive les sorties sur la console jusqu'au prochain Ok ou ^O
^R        Réécrit la ligne actuellement tapée avec les modifications en cours
^S        Suspend l'exécution du programme (Pause sinon Ctrl+Verr.num)
^Q        Reprend son exécution après ^S (touche quelconque du PC)
^U,^X     Passe à la ligne suivante sans valider l'actuelle
<ENTRÉE>  Passe à la ligne en validant l'actuelle
?         Équivaut à l'instruction PRINT
.         Indique aux instructions gérant les lignes numérotées la dernière
          lue : AUTO, EDIT, RENUM, DELETE, LIST et LLIST


Commandes du mode édition (EDIT ou ^A) :

n<ESPACE>               Avance le curseur de n caractères
n<RET.ARR>              Le recule de n car. et affiche à rebours ceux rencontrés
<RET.ARR>               Lors de l'écriture d'une chaîne, recule le curseur et
                        supprime le dernier caractère
A             (Abort)   Annule et recommence l'édition d'une ligne numérotée
nCcar1...carn (Change)  Modifie n caractères
nD            (Delete)  Efface n caractères
E             (End)     Termine l'édition en validant la ligne modifiée
Hchaîne<ESC>  (Hull)    Équeute la ligne et entre une chaîne
Ichaîne<ESC>  (Insert)  Insère une chaîne à la position courante
nKc           (Kill)    Efface les caractères jusqu'au énième caractère c
L             (List)    Affiche la ligne avec les modifications en cours
Q             (Quit)    Quitte sans éditer et valide la ligne en cours
nSc           (Search)  Cherche la position du énième caractère c
Xchaîne<ESC>  (eXtend)  Entre une chaîne à la fin de la ligne
_                       Indique un retour arrière lors d'une insertion de chaîne
<ENTRÉE>                Comme E en plus d'afficher au préalable la ligne

Le nombre n est optionnel et vaut 1 par défaut.

Remarque : l'enregistrement des modifications par EDIT entraîne la suppression
des variables de la mémoire. Or, en cas d'erreur de syntaxe lors de l'exécution
du programme, la ligne fautive est passée en mode édition. Il faut alors sortir
avec Q pour conserver ces variables et leur contenu.
MBASIC possède aussi des paramètres de ligne de commande :
MBASIC [fichier BAS]
       [/F:nombre de tampons de fichiers disponibles]
       [/M:octets réservés aux données du BASIC]
       [/S:taille maximale d'enregistrement dans un fichier à accès direct]
Par défaut, /F:3 & /S:128 (en octets).
Au maximum, /F:15.
Par défaut, sous une version antérieure à DOS 3, plus de mémoire est disponible :
BASIC-86 Rev. 5.27
[MS-DOS Version]
Copyright 1977-1982 (C) by Microsoft
Created:  8-Nov-82
62281 Bytes free
Autre curiosité, le BASIC force la passage à la ligne lorsque le nombre de caractères envoyés dépasse la limite définie par l'instruction WIDTH (largeur standard : 80). Or, DOS l'effectue dès que la dernière colonne est atteinte. La solution est d'entrer WIDTH 255. Cependant, l'affichage de l'instruction FILES (ou PRINT suivie de plusieurs virgules) sera désordonné. Reste l'usage d'un paramètre inférieur au nombre de colonnes affichées.
Une autre solution, à utiliser conjointement à WIDTH 80, est de supprimer le retour à la ligne automatique du DOS. Cela est possible depuis DOS 2, en installant le gestionnaire ANSI et en émettant la séquence ESC[7l (contraire de ESC[7h)via la commande PROMPT ou l'instruction PRINT du BASIC :
C:\BASIC>prompt $p$g$e[7l
PRINT CHR$(27);"[7l";


* Cf. http://maben.homeip.net/static/S100/vic ... ii/CH5.txt


Dernière modification par gm86 le 14 août 2016 16:08, modifié 92 fois.

_________________

C:\ONGRTLNS.W95


Haut
Profil Citer
gm86
Sujet du message : Re: Documentation ASM
Publié : 31 oct. 2011 00:35
Membre inscrit
Avatar de l’utilisateur
Hors-ligne
 
Messages : 465
Inscription : 01 sept. 2008 19:07
 
ÉCRIRE EN ESPÉRANTO AVEC UNE CONFIGURATION DE CLAVIER CLASSIQUE



La langue internationale Espéranto comporte six lettres accentuées qui ne figurent pas sur les configurations classiques de clavier : Ĉ, Ĝ, Ĥ , Ĵ, Ŝ et Ŭ (U bref). La solution qui permettra leur entrée ne devra ni dépendre de la nationalité de la disposition du clavier ni interférer avec.
Dans un premier temps, je vais vous présenter un TSR remplissant son rôle au strict minimum.
Je me suis inspiré pour cela du programme EKLAVO de Byrial Jensen. Il exploite le service 4Fh de l'interruption 15h et le service 5 de l'interruption 16h. Il s'agit d'obtenir les lettres accentuées avec l'appui simultanée de la touche AltGr (Alt gauche) ou la combinaison Ctrl+Alt (gauche) et de la touche correspondante. Ainsi, ĝ est introduit soit par AltGr (Alt droite)+g soit par Ctrl+Alt (gauche)+g. Le programme requiert la page de codes 853.
Je suis parti de deux constats.
La touche Maj sert de préfixe. Elle indique toujours le contraire de l'état du verrouillage majuscule — sur le clavier français, elle le désactive aussi.
Ensuite, la touche AltGr de la plupart des claviers correspond à l'Alt droite du clavier américain. Normalement, elle peut indiquer qu'une touche Alt est enfoncée via l'octet 17h du segment de données du BIOS (40h). Cependant, le gestionnaire KEYB de DR DOS n'agit pas ainsi (ce que le programme EKLAVO ne prévoit pas). Or, c'est sous DR DOS que la page de codes 853 est disponible (bien que non supportée officiellement).

La version suivante met en lumière ce problème accompagné d'un autre : le service 12h de l'interruption 16h du clavier ne permet plus d'indiquer l'actionnement de la touche Alt droite du clavier étendu.
; Assemblage :
;       MASM    ESPKLAVO;
;       LINK    ESPKLAVO;
;       EXE2BIN ESPKLAVO ESPKLAVO.COM


VerrMaj         equ     100b * 16
Alt             equ     1000b
Ctrl            equ      100b
MajG            equ       10b
MajD            equ        1
AltD            equ     1000b


NUL     SEGMENT AT 0
Adresse_nulle   label   far
NUL     ENDS

CODE    SEGMENT
        ASSUME  CS:CODE, DS:CODE
        ORG     100h

Depart:
        jmp     Installe
; Données --------------------------------------------------------------------
Drapeau         db      (0)             ; 1 : code étendu attendu ; 2 : AltGr

Touches         db      2Eh,22h,23h,24h,1Fh,16h ; c, g, h, j, s, u

Esperanto       db      134,143         ; c circonflexe min & maj
                db      155,157         ; g circonflexe     "
                db      169,168         ; h circonflexe     "
                db      159,172         ; j circonflexe     "
                db      199,198         ; s circonflexe     "
                db      237,236         ; u brève           "
; Saut vers le vecteur précédent ---------------------------------------------
Int_orig:
        jmp     Adresse_nulle
Vect_orig       equ     $-4

RESIDANT        PROC    FAR
         jnc    Int_Orig                ; Bit de retenue positionné ?
        cmp     ah,4Fh                  ; Fct interception clavier ?
         jne    Int_Orig

        push    ax
        push    bx
        push    cx
        push    di
        push    ds
        push    es

        push    cs
        pop     es                      ; ES = CS
        mov     cx,6                    ; 6 touches concernées
        mov     di,offset Touches
        cld                             ; Incrémentation
        repne   scasb                   ; Répète tant que CX<>0, [ES:DI]<>AL
         jne    Retour                  ; Si aucune touche correspondante, ret.
        sub     di,offset Touches + 1   ; Obtient un index
        shl     di,1                    ; DI x 2

; Sauve code touche dans CH en vue la fct 5 de l'int 16h
        mov     ch,al
        mov     ah,12h                  ; Obtient état du clavier std ou étendu
        int     16h
        xor     bx,bx                   ; Drapeau BX à 0
        test    al,VerrMaj              ; Verrouillage majuscule actif ?
         jz     Maj?                    ; Non, Maj ?
        inc     bx                      ; Drapeau BX à 1
Maj?:
        test    al,MajG + MajD          ; Touche Maj (gauche ou dr.) enfoncée ?
         jz    AltGr?                   ; Non, AltGr ?
        xor     bl,1                    ; Bascule le drapeau BX
AltGr?:
        test    ah,AltD                 ; Touche AltGr enfoncée ?
         jnz    Tampon_clavier          ; Oui, écrit caractère dans tampon
        not     al                      ; Inverse les bits de l'octet d'état
        test    al,Ctrl + Alt           ; Ctrl+Alt ?
         jnz    Retour                  ; Non, retour

Tampon_clavier:
        mov     ah,5                    ; Place 1 code & 1 car. dans le tampon
        mov     cl,byte ptr es:[Esperanto + di + bx]    ; Caractère dans CL
        int     16h
        or      al,al                   ; Tampon plein ?
         jnz    Retour                  ; Oui, retour
        clc                             ; Bit de retenue effacé :
                                        ; code de touche consommé
        jmp     short Code_efface
Retour:
        stc                             ; Bit de retenue positionné :
                                        ; code de touche disponible
Code_efface:
        pop     es
        pop     ds
        pop     di
        pop     cx
        pop     bx
        pop     ax

        ret 2                           ; Retour d'int.
RESIDANT        ENDP


Installe:
        mov     ax,3515h                ; Sauve ancien vecteur
        int     21h
        mov     word ptr Vect_orig+0,bx
        mov     word ptr Vect_orig+2,es
        mov     ax,2515h                ; Instaure nouveau vecteur
        mov     dx,offset Residant
        int     21h
        mov     dx,offset Installe      ; Laisse la partie résidente
        int     27h

CODE    ENDS

        END     Depart

On remarque que je n'ai pas interdit l'usage de Ctrl avec AltGr (qui, sur les claviers non américains, remplace la combinaison Ctrl+Alt pour taper le troisième caractère de touche) afin de simplifier le code et de démontrer que KEYB fourni avec DR DOS n'interprète pas AltGr comme une touche Alt ordinaire. Par contre, j'ai illustré l'emploi de l'instruction TEST :
- pour savoir si la touche Maj gauche ou droite était enfoncée, j'ai appliqué un masque sur l'octet d'état du clavier avec seulement les deux bits correspondant positionnés puis vérifier si le résultat était non nul ;
- pour savoir si la combinaison Ctrl et Alt était pressée, j'ai d'abord inversé les bits de l'octet recueilli avant d'appliquer le masque afin de vérifier si le résultat était nul.

Description des services clavier utilisés :
INT 15h - INTERCEPTION CLAVIER (service appelé par le BIOS lors d'une INT 9)
(BIOS du PC/XT postérieur au 8/11/82 — modèle FBh —, du PC/AT après le 10/01/84
— sous-modèle 00 & 01 — et du PS/2 ; cf. service C0h).
Appel :
AH = 4Fh
AL = code de touche
Bit de retenue (carry flag) positionné.

Retour :
Si bit de retenue positionné,
AL = code de touche (modifié ou pas) à faire traiter par la routine de l'interruption 9.
Si bit de retenue effacé, le code n'est plus à traiter.


INT 16h - ÉCRITURE CLAVIER
(BIOS supportant le claviers étendu : celui du PC/AT depuis le 15/11/85 — sous-modèle 01 — et du PS/2).
Appel :
AH = 5
CH = code de la touche
CL = caractère

Retour :
AL = 0 si succès
     1 si tampon plein
AH détruit


INT 16h - OBTENTION DE L'OCTET D'ÉTAT DU CLAVIER STANDARD (à l'instar du service 2) ET ÉTENDU
Appel :
AH = 12h

Retour :
AL = octet d'état standard (lu en 40:17h) :
76543210  bit
x.......  Etat Inser : 1|0
.x......  Etat Verr maj : 1, actif ; 0, inactif
..x.....  Etat Verr num : 1, actif ; 0, inactif
...x....  Etat Arrêt défil : 1, actif ; 0, inactif
....x...  1 : Alt enfoncée
.....x..  1 : Ctrl enfoncée
......x.  1 : Maj gauche enfoncée
.......x  1 : Maj droite enfoncée

AH = octet d'état étendu :
76543210  bit
x.......  Sys Req enfoncée (1)
.x......  Verr maj    "
..x.....  Verr num    "
...x....  Arrêt défil "
....x...  Alt droite  "    (2)
.....x..  Ctrl droite "    (2)
......x.  Alt gauche  "
.......x  Ctrl gauche "

(1) ne peut être positionné que par un BIOS supportant le clavier AT.
(2) ne peut être positionné que par un BIOS supportant le clavier étendu :
celui du PC/AT depuis le 15/11/85 — sous-modèle 01 — et du PS/2.

_____________________
Version fonctionnelle



En testant le programme précédent sans charger KEYB de DR DOS, on remarque qu'il est plutôt aisé d'entrer les caractères accentués des touches C, G et S avec AltGr ou la combinaison Maj+AltGr. En revanche, si on souhaite garder la main droite pour les touches G, H et U, l'autre main appuyera sur Ctrl+Alt voire Maj+Ctrl+Alt ; ce qui représente trois doigts en action.
En s'inspirant d'autres claviers proposant quatre caractères par touche, il devient envisageable d'adopter la combinaison Maj+Alt.
On suppose que le verrouillage majuscule est inactif (ce qui est normalement le cas sur le clavier français lorsque la touche Maj est pressée), on obtient :
Ctrl + Alt     minuscule
Maj  + Alt     MAJUSCULE
AltGr          minuscule
Maj  + AltGr   MAJUSCULE
Voici la logique de programme pour déterminer s'il a affaire à une majuscule ou une minuscule :
          Maj ?
            |
     +------+------+
     |             |
   BX=1          BX=0
     |             |
     |           Ctrl ?
     |             |
   Alt ?-----------+----+
     |                  |
  +--+---------------Alt Gr ?
  |                     |
  |                     +-------+
  |                     |       |
  |                     |  CF=1, sortie
  +----------Verr.maj ?-+
                 |
         +-------+---+
         |           |
   BX <-BX xor 1     |
         |           |
         +---Majuscule si BX=1
             Minuscule si BX=0

Se lit de haut en bas.
Issue d'une condition :
- positive : gauche ;
- négative : droite.
En réécrivant le programme, j'ai fait en sorte qu'il tourne sous le maximum de configurations. L'adapter pour DOS 1 n'a été ni une nécessité (il est destiné au DR DOS) ni une contrainte (lignes en majuscules dans la partie externe). Plus important est le fait d'enlever le service d'écriture clavier de l'interruption 16h car trop récent. Il faut prendre en compte aussi, hormis le fait que KEYB soit chargé, qu'un clavier étendu puisse être branché sur un PC/XT ou un PC/AT, or les touches supplémentaires, telle Alt droite, ne seront pas forcément gérées par le BIOS. D'où la nécessité de connaître le code de la touche AltGr, tout en sachant qu'un code BREAK correspond au code MAKE majoré de 80h (cf. viewtopic.php?f=24&t=5047&start=59) :
                                                MAKE (appui)    BREAK (relâchement)

Touche Alt classique (gauche) :                 38h             B8h

Touche Alt droite du clavier étendu (AltGr) :   E0h 38h         E0h B8h
Enfin, il est bon de vérifier que l'interception du clavier soit supportée par le BIOS. Pour ce faire, on emploie le service C0h :
INT 15h - DEMANDE LA CONFIGURATION DU SYSTÈME
Appel.
AH = C0h

Retour.
ES :BX = adresse de la table de configuration fixée en ROM
Format de la table :
Octets      Contenu
00-01       longueur de la table en octets
02          modèle du système (octet situé en F000:FFFEh)
03          modèle du sous-système
04          niveau de révision du BIOS
05          drapeaux de configuration :
            Bit      Signification (si positionné)
            0        jadis réservé (système à bus MCA et ISA)
            1        architecture MCA implémentée
            2        zone de données complémentaires du BIOS (EBDA) allouée
            3        attente d'un événement externe (Int 15h, fct 41h) disponible
            4        interception du clavier (Int 15h, fct 4Fh) disponible
            5        horloge sauvegardée (RTC) sur la carte mère
            6        8259 présent (mode cascadé)
            7        canal DMA 3 destiné au BIOS du disque dur
Signification des octets de modèles, de sous-modèles et de révision du BIOS :
Machine     Date		Modèle      Sous-mod.	Révision du BIOS
PC          24/04/81    FFh         -           00
            19/10/81                            01 (quelques bugs arrangés)
            27/10/82                            02 (mise à jour au niveau du XT)

PC/XT       08/11/82    FEh         -           00
XT/2*       10/01/86    FBh         00          01 (drapeaux de config. faux)
            09/05/86                            02

PCjr        01/06/83    FDh         -           00

PC/AT       10/01/84    FCh         -           00 (80286-6)
            10/06/85                00          01 (lecteur de disquette 720 Ko)
            15/11/85                01          00 (80286-8)
XT-286      21/04/86    FCh         02          00

Convertible 13/09/85    F9h         00          00

PS/2 8525   26/06/87    FAh         01          00
     8530   02/09/86                00          00
            12/12/86                            01
     8550   13/02/87    FCh         04          00
     8560   idem                    05          00
     8580   ?  ?  ?     F8h         00          00 (80386-16)

* XT/2 : PC/XT 256/640 Ko
Le bit 4 de l'octet 5 de la table nous est nécessaire. Cet octet n'est pas fiable dans le BIOS 01 du XT/2 (50h au lieu de 90h) mais cela n'influe pas la valeur du bit concerné. Les fichiers de la ROM fautive sont disponibles à l'adresse suivante :
http://www.minuszerodegrees.net/bios/BI ... 0JAN86.zip
En bref, les machines IBM qui supportent cette interception du clavier sont les suivantes :
- les AT mais pas l'original ;
- le XT/2 ;
- le XT-286 ;
- le PC Convertible ;
- les PS/2.

Tout est bon pour créer un TSR qui se donne la peine de reconnaître le matériel.
Toutefois, il faut empêcher son chargement multiple. Ainsi, lors d'un appel au service 4Fh de l'interruption 15h avec le code de touche inexistant FFh, le TSR renvoie AL nul (AX=5000h) pour indiquer sa présence.
Voici le programme obtenu :
;       MASM    ESPKLAVO;
;       LINK    ESPKLAVO;
;       EXE2BIN ESPKLAVO ESPKLAVO.COM


MAKE_Alt        equ      38h            ; Code de pression des touches Alt
BREAK_Alt       equ     0B8h            ; Code de relâchement des touches Alt
Code_etendu     equ     0E0h            ; Précède le code d'une touche étendue

VerrMaj         equ     100b * 16
Alt             equ     1000b
Ctrl            equ      100b
MajG            equ       10b
MajD            equ        1


BDA     SEGMENT AT 40h                  ; BDA : zone de données du BIOS
Adresse_bidon   label   far
        org     17h
Etat_clav       equ     this byte

        ORG     1AH                     ; Tampon circulaire du clavier
TETE            DW      (?)             ; Prochaine lecture (2nd octet nul)
TAILLE          DW      (?)             ; Prochaine entrée  (idem)
LIM_INF         LABEL   FAR             ; Car., scancode, car., scancode...
        ORG     3EH
LIM_DEPASSEE    LABEL   FAR

BDA     ENDS


CODE    SEGMENT
        ASSUME  CS:CODE, DS:BDA

; PARTIE RESIDANTE **********************************************************

        ORG     100h

Depart:
        jmp     Installe
; Données --------------------------------------------------------------------
Drapeau         db      (0)     ; 0 : aucun code étendu ; 1 : code étendu reçu
                                ; 2 : AltGr enfoncée    ; 3 : id. + code étendu
Touches         db      2Eh,22h,23h,24h,1Fh,16h ; c, g, h, j, s, u

Esperanto       db      134,143         ; c circonflexe min & maj
                db      155,157         ; g circonflexe     "
                db      169,168         ; h circonflexe     "
                db      159,172         ; j circonflexe     "
                db      199,198         ; s circonflexe     "
                db      237,236         ; u brève           "
; Saut vers le vecteur précédent ---------------------------------------------
Int_orig:
        jmp     Adresse_bidon
Vect_orig       equ     $-4

RESIDANT        PROC    FAR
        cmp     ah,4Fh                  ; Fct interception clavier ?
         jne    Int_orig
        cmp     al,0FFh                 ; Test de présence du TSR ?
         jne    Bonne_fct
        inc    ax                       ; Signature : AL nul
        iret                            ; Retour d'interruption
Bonne_fct:
        cmp     ah,4Fh                  ; Fct interception clavier ?
         jne    Int_orig
        push    ax                      ; Sauve les registres
        push    bx
        push    cx
        push    di
        push    ds
        push    es

        cmp     cs:Drapeau,2
         ja     Code_BREAK?             ; 3 ; AltGr pressée et code étendu
         je     Code_etendu?            ; 2 ; AltGr pressée
         jnp    Code_etendu?            ; 0 ; aucun code étendu
        cmp     al,MAKE_Alt             ; 1 ; code étendu : AltGr pressée ?
         jne    Drapeau_nul
Inc_drapeau:
        inc     cs:Drapeau              ; Drapeau dans {1;3}
         jmp    short Retour
Code_BREAK?:
        cmp     al,BREAK_Alt            ; Touche AltGr relâchée ?
         je     Drapeau_nul
        dec     cs:Drapeau              ; Drapeau = 2
         jmp    short Retour
Drapeau_nul:
        mov     cs:Drapeau,0            ; Drapeau = 0
         jmp    short Retour
Code_etendu?:
        cmp     al,Code_etendu
         je     Inc_drapeau

        push    cs
        pop     es                      ; ES = CS
        mov     cx,6                    ; 6 touches concernées
        mov     di,offset Touches
        cld                             ; Incrémentation
        repne   scasb                   ; Répète tant que CX<>0, [ES:DI]<>AL
         jne    Retour                  ; Si aucune touche correspondante, ret.
        sub     di,offset Touches + 1   ; Obtient un index
        shl     di,1                    ; DI x 2

; Sauve code touche dans CH en vue de l'écriture dans le tampon du clavier
        mov     ch,al

        mov     ax,BDA                  ; Segment de données du BIOS
        mov     ds,ax

        mov     al,Etat_clav            ; Recueille le 1er octet d'état clavier
        xor     bx,bx                   ; Drapeau BX à 0
        test    al,MajG + MajD          ; Touche Maj enfoncée (gauche ou dr.) ?
         jz     Ctrl?                   ; Non, Ctrl ?
        inc     bx                      ; Drapeau BX à 1
Alt?:
        test    al,Alt                  ; Touche Alt ?
         jz     AltGr?                  ; Non, AltGr ?
         jmp    short VerrMaj?          ; Oui, va vérifier Verr. maj.
Ctrl?:
        test    al,Ctrl                 ; Touche Ctrl ?
         jnz    Alt?                    ; Oui, Alt aussi ?
AltGr?:
        cmp     cs:Drapeau,2            ; Touche AltGr (Alt de droite) ?
         jne    Retour                  ; Non, retour
VerrMaj?:
        test    al,VerrMaj              ; Verr. maj. actif ?
         jz     Tampon_clavier          ; Non
        xor     bx,1                    ; Oui, bascule le drapeau BX

Tampon_clavier:
        mov     cl,byte ptr es:Esperanto[di + bx]    ; Caractère dans CL

        CLI                             ; Inhibe les interruptions
        MOV     AX,TAILLE               ; AL pointe la taille du tampon & AH=0
        MOV     BX,AX                   ; BX pointe aussi la taille actuelle
        INC     AX
        INC     AX                      ; Nouvelle taille dans AL + 2
        CMP     AL,OFFSET LIM_DEPASSEE  ; Au-delà du tampon circulaire ?
         JB     TAMPON_PLEIN?
        MOV     AL,OFFSET LIM_INF       ; Limite inférieure du tampon
TAMPON_PLEIN?:
        CMP     BYTE PTR TETE,AL        ; Tampon clavier plein ?
         JE     Retour                  ; Oui, retour
AJOUT_CAR:
        MOV     [BX],CX                 ; Car. & code dans tampon
        MOV     BYTE PTR TAILLE,AL      ; Indique 1 car. à traiter
        clc                             ; Bit de retenue effacé :
                                        ; code de touche consommé
        jmp     short Code_efface
Retour:
        stc                             ; Bit de retenue positionné :
                                        ; code de touche disponible
Code_efface:
        STI                             ; Autorise les interruptions
        pop     es                      ; Restitue les registres
        pop     ds
        pop     di
        pop     cx
        pop     bx
        pop     ax

        ret 2                           ; Retour d'int.
RESIDANT        ENDP


; PARTIE EXTERNE *************************************************************

        ASSUME  DS:CODE

Non_compatible$ db      'Interception clavier (Int 15h, fct 4Fh) '
                db      'non supportée par le BIOS',13,10,'$'
Deja_la$        db      'Déjà chargé$'
Charge$         db      13,10,'ESPKLAVO chargé',13,10,'$'
;-----------------------------------------------------------------------------
Sortie:
        mov     ah,9                    ; Afficher un message
        int     21h
        ret                             ; Fin
Installe:
        mov     ah,0C0h                 ; Demande configuration système
        int     15h
         jc     Non_compatible
        mov     al,es:[bx+5]            ; Pointe drapeaux de config. (octet 5)
        test    al,10000b               ; INT 15h Fct 4Fh supportée ?
         jne     Deja_la?               ; Oui, CF = 0
Non_compatible:
        mov     dx,offset Non_compatible$
         jmp    Sortie
Deja_la?:
        mov     ax,4FFFh                ; Teste présence TSR
        int     15h
        or      al,al                   ; Signature AL nulle ?
         jnz    Sauve_vecteur
        mov     dx,offset Deja_la$
         jmp    Sortie
Sauve_vecteur:
        XOR     AX,AX
        MOV     ES,AX                   ; ES = 0
        MOV     BX,ES:[4*15h]           ; Offset
        MOV     ES,ES:[4*15h+2]         ; Segment
        mov     word ptr Vect_orig+0,bx
        mov     word ptr Vect_orig+2,es
        mov     ax,2515h                ; Instaure nouveau vecteur
        mov     dx,offset Residant
        int     21h
        mov     ah,49h                  ; Libère environnement
        mov     es,ds:2Ch
        int     21h
        mov     dx,offset Charge$       ; Sort la confirmation de chargement
        call    Sortie
        mov     dx,offset Installe      ; Laisse la partie résidante
        int     27h

CODE    ENDS

        END     Depart

Les lignes en majuscules dans la partie résidante remplacent l'appel au service 5 de l'interruption 16h du clavier. Les adresses du tampon circulaire du clavier se trouvent dans le segment BDA_SEG. Il est situé au segment 40h :
Offset  Description
001Ah   Offset de la tête du tampon (lieu de la prochaine lecture)
001Ch   Offset de la taille du tampon (lieu de la prochaine écriture)
002Eh   Tampon circulaire de 16 mots (un mot : caractère suivi de code de touche)
003Eh   ...
Lorsque les mots en 1Ah & 1Ch sont égaux, le tampon clavier est considéré comme vide.
La tête du tampon peut rattraper la taille mais pas l'inverse (tampon plein).
Dans le même segment, se trouvent les octets d'état du clavier (cf. : viewtopic.php?f=24&t=5047&start=67) :
Octet 0040:0017h

76543210  bit
x.......  Etat Inser : 1|0
.x......  Etat Verr maj : 1, actif ; 0, inactif
..x.....  Etat Verr num : 1, actif ; 0, inactif
...x....  Etat Arrêt défil : 1, actif ; 0, inactif
....x...  1 : Alt enfoncée
.....x..  1 : Ctrl enfoncée
......x.  1 : Maj gauche enfoncée
.......x  1 : Maj droite enfoncée


Octet 0040:0018h

76543210  bit
x.......  1 : Ins enfoncée
.x......  1 : Verr maj enfoncée
..x.....  1 : Verr num enfoncée
...x....  1 : Arrêt défil enfoncée
....x...  1 : Etat Pause actif (Ctrl-Verr num ou Pause)
.....x..  1 : Sys Req enfoncée
......x.  1 : Alt gauche enfoncée
.......x  1 : Ctrl gauche enfoncée
Pour les curieux, un BIOS positionne le bit 4 de l'octet 40:96h lorsqu'il détecte un clavier étendu.

_________________

C:\ONGRTLNS.W95


Haut
Profil Citer
gm86
Sujet du message : Documentation ASM (liens)
Publié : 01 août 2012 13:58
Membre inscrit
Avatar de l’utilisateur
Hors-ligne
 
Messages : 465
Inscription : 01 sept. 2008 19:07
 
Je conseille chaudement la consultation de cette page de liens :
http://www.oopweb.com/Assembly/Files/Assembly.html

_________________

C:\ONGRTLNS.W95


Haut
Profil Citer
gm86
Sujet du message : Re: Documentation ASM
Publié : 03 févr. 2018 13:34
Membre inscrit
Avatar de l’utilisateur
Hors-ligne
 
Messages : 465
Inscription : 01 sept. 2008 19:07
 
Quatre routines différentes pour afficher un quartet au format hexadécimal sous DOS.
 0100	 	 	 	 	ORG	100h
 	 	 	 	
 0100	 	 	 	SortChiffreHex1	PROC
 	 	 	 	; Affiche un chiffre hexa stocké dans AL.
 	 	 	 	; "La programmation en assembleur sur PC et PS", Peter Norton & John Socha
 	 	 	 	; Editions P.S.I., 1990
 	 	 	 	; Entrée :	AL	chiffre hexa (quartet fort nul)
 0100  50	 	 	 	push	ax
 0101  52	 	 	 	push	dx
 	 	 	 	 	
 0102  3C 0A	 	 	 	cmp	al,10	 	 	; AL<10 ?
 0104  73 04	 	 	 	 jae	LettHex	 	 	; Non, lettre
 0106  04 30	 	 	 	add	al,'0'	 	 	; Oui, chiffre
 0108  EB 02	 	 	 	 jmp	short SortChiffre
 010A  04 37	 	 	LettHex:add	al,'A'-10
 010C	 	 	 	SortChiffre:
 010C  92	 	 	 	xchg	dx,ax	 	 	; DL <- AL
 010D  B4 02	 	 	 	mov	ah,2	 	 	; Affiche caractère
 010F  CD 21	 	 	 	int	21h
 	 	 	 	 
 0111  5A	 	 	 	pop	dx
 0112  58	 	 	 	pop	ax
 0113  C3	 	 	 	ret
 0114	 	 	 	SortChiffreHex1	ENDP
 	 	 	 	
 0200	 	 	 	 	ORG	200h
 	 	 	 	
 0200	 	 	 	SortChiffreHex2	PROC
 	 	 	 	; Affiche un chiffre hexa stocké dans AL.
 	 	 	 	; http://trixter.oldskool.org/2013/01/11/optimizing-for-the-8088-and-8086-cpu-part-2/
 	 	 	 	; Naive way...
 	 	 	 	; Entrée :	AL	chiffre hexa (quartet fort nul)
 0200  50	 	 	 	push	ax
 0201  52	 	 	 	push	dx
 	 	 	 	 	
 0202  3C 0A	 	 	 	cmp	al,10	 	 	; AL<10 ?
 0204  72 02	 	 	 	 jb	ASCII	 	 	; Oui, chiffre
 0206  04 07	 	 	 	add	al,7	 	 	; Ajuste pour la lettre
 0208  04 30	 	 	ASCII:	add	al,'0'
 	 	 	 	
 020A  92	 	 	 	xchg	dx,ax	 	 	; DL <- AL
 020B  B4 02	 	 	 	mov	ah,2	 	 	; Affiche caractère
 020D  CD 21	 	 	 	int	21h
 	 	 	 	 
 020F  5A	 	 	 	pop	dx
 0210  58	 	 	 	pop	ax
 0211  C3	 	 	 	ret
 0212	 	 	 	SortChiffreHex2	ENDP

 0300	 	 	 	 	ORG	300h
 	 	 	 	
 0300	 	 	 	SortChiffreHex3	PROC
 	 	 	 	; Affiche un chiffre hexa stocké dans AL.
 	 	 	 	; Magazine DEBUG N°1, juin 89, p.44 :
 	 	 	 	; http://download.abandonware.org/magazines/DEBUG%20magazine/debugmagazine_numero01/Debug%20001%20-
	 	 	 	%20Page%20048(1989-06).jpg
 	 	 	 	; Entrée :	AL	chiffre hexa (quartet fort nul)
 0300  50	 	 	 	push	ax
 0301  52	 	 	 	push	dx
 	 	 	 	 	 	 	 	 	; Ex. :	0A	|	00
 0302  04 90	 	 	        add	al,90h	 	 	;	9A	|	90
 0304  27	 	 	 	daa	 	 	 	;    (1)00	|	90
 0305  14 40	 	 	 	adc	al,40h	 	 	;	41	|	D0
 0307  27	 	 	 	daa	 	 	 	;	41 = 'A'|    (1)30 = '0'
 	 	 	 	
 0308  92	 	 	 	xchg	dx,ax	 	 	; DL <- AL
 0309  B4 02	 	 	 	mov	ah,2	 	 	; Affiche caractère
 030B  CD 21	 	 	 	int	21h
 030D  5A	 	 	 	pop	dx
 030E  58	 	 	 	pop	ax
 030F  C3	 	 	 	ret
 0310	 	 	 	SortChiffreHex3	ENDP
 	 	 	 	
 0400	 	 	 	 	ORG	400h
 	 	 	 	
 0400	 	 	 	SortChiffreHex4	PROC
 	 	 	 	; Affiche un chiffre hexa stocké dans AL.
 	 	 	 	; http://trixter.oldskool.org/2013/01/11/optimizing-for-the-8088-and-8086-cpu-part-2/
 	 	 	 	; Norbert Juffa...
 	 	 	 	; Entrée :	AL	chiffre hexa (quartet fort nul)
 0400  50	 	 	 	push	ax
 0401  52	 	 	 	push	dx
 	 	 	 	 	 	 	 	 	; Ex. :	0A	|	00
 0402  3C 0A	 	 	 	cmp	al,10	 	 	;	0A	|	00(CF=1)
 0404  1C 69	 	 	 	sbb	al,69h	 	 	;   (FF)A1	|   (FF)96
 0406  2F	 	 	 	das	 	 	 	;	41(CF=1)|	30(CF=1)
 	 	 	 	
 0407  92	 	 	 	xchg	dx,ax	 	 	; DL <- AL
 0408  B4 02	 	 	 	mov	ah,2	 	 	; Affiche caractère
 040A  CD 21	 	 	 	int	21h
 040C  5A	 	 	 	pop	dx
 040D  58	 	 	 	pop	ax
 040E  C3	 	 	 	ret
 040F	 	 	 	SortChiffreHex4	ENDP
 	 	 	 	
SORTCHIFFREHEX1. . . . . . . . .	N PROC	0100	CODE	Length =0014
SORTCHIFFREHEX2. . . . . . . . .	N PROC	0200	CODE	Length =0012
SORTCHIFFREHEX3. . . . . . . . .	N PROC	0300	CODE	Length =0010
SORTCHIFFREHEX4. . . . . . . . .	N PROC	0400	CODE	Length =000F
Il s'agit de transformer un chiffre hexadécimal en caractère ASCII.


Dernière modification par gm86 le 04 févr. 2018 18:33, modifié 2 fois.

_________________

C:\ONGRTLNS.W95


Haut
Profil Citer
Deksor
Sujet du message : Re: Documentation ASM
Publié : 03 févr. 2018 13:46
Modérateur
Avatar de l’utilisateur
Hors-ligne
 
Messages : 3052
Inscription : 23 mai 2011 13:33
PC Rétro : 486DX 33 8mo SB Pro 2, P2 450 128mo Voodoo 2 SLI
 
Tiens j'avais jamais vu ce sujet, c'est très intéressant :approve:

_________________

Laptop hater


Haut
Profil Citer
Afficher : Trier par : Ordre :
Répondre   Page 1 sur 1  [ 8 messages ]
Revenir à « Documentations et tutoriels »
Aller :