Fonctionnement et Programmation du Clavier
Fonctionnement et Programmation du Clavier
Le clavier
Nous allons étudier ici l’implémentation du périphérique le plus utilisé, à savoir le clavier,
avec une description fonctionnelle de l’aspect matériel mais surtout son étude du point de vue
de la programmation système.
149
150 CHAPITRE 6. LE CLAVIER
Parcours et identification des touches pressées.- La figure 6.1 montre une matrice 4 × 4 reliée à
deux ports. Les lignes sont reliées à un port sortant et les colonnes à un port entrant. Si on n’a
appuyé sur aucune touche, lire le port entrant donnera 1 pour toutes les colonnes, puisqu’elles
sont toutes reliées au niveau haut (VCC ). Si toutes les lignes sont reliées à la terre et qu’on
appuie sur une touche, une des colonnes sera à 0 puisque la touche pressée permet au courant
de s’écouler.
Le microprocesseur doit continuellement examiner le clavier pour détecter et identifier la
touche qui est pressée. Nous allons voir comment on effectue ceci.
Mise à la terre des lignes et lecture des colonnes.- Pour détecter la touche pressée, le micropro-
cesseur met à la terre toutes les lignes, en appliquant 0 au loquet (latch) de sortie, puis lit les
colonnes. Si la donnée lue sur les colonnes est D3 – D0 = 1111, c’est qu’aucune touche n’est
pressée. On continue ainsi jusqu’à ce qu’une touche soit pressée.
Si un des bits de colonnes est à zéro, c’est qu’une touche est pressée. Par exemple, si D3 –
D0 = 1101, ceci signifie qu’une touche de la colonne D1 est pressée. Lorsque le microprocesseur
détecte qu’une touche est pressée, il passe à l’identification de celle-ci. Pour cela, il met à la terre
la seule ligne du haut et lit les colonnes. Si la donnée lue n’est constituée que de 1, c’est que
la touche pressée ne se situe pas sur cette ligne et on passe à la ligne suivante. Ce processus
continue jusqu’à ce que la ligne soit identifiée.
Après identification de la ligne, la tache suivante consiste à trouver à quelle colonne appartient
la touche pressée.
Bien entendu ce processus en deux temps ne fonctionne que parce que la durée d’appui sur
la touche est bien plus long que le cycle du microprocesseur.
Exemple.- À partir du dispositif de la figure 6.1, déterminer quelle est la touche pressée lorsque :
(a) D3 – D0 = 1110 pour la ligne, D3 – D0 = 1011 pour la colonne.
(b) D3 – D0 = 1101 pour la ligne, D3 – D0 = 0111 pour la colonne.
Réponse. (a) La ligne est D0 et la colonne est D2, donc la touche ‘2’ est pressée.
(b) La ligne est D1 et la colonne est D3, donc la touche ‘7’ est pressée.
152 CHAPITRE 6. LE CLAVIER
6.1.1.3 Un programme
Le programme suivant permet la détection et l’identification des touches pressées, en sup-
posant que les constantes PORT A et PORT B soient initialisées et que le sous-programme DELAY
permette un délai (ici de 20 ms) :
;scan codes des touches (a placer dans le segment des donnees)
KCOD_0 DB 0,1,2,3 ; codes des touches de la premiere ligne
KCOD_1 DB 4,5,6,7 ; codes des touches de la seconde ligne
KCOD_2 DB 8,9,0AH,0BH ; codes des touches de la troisieme ligne
KCOD_3 DB OCH,ODH,OEH,OFH ; codes des touches de la quatrieme ligne
Commentaires.- 1o ) Pour être sûr que la touche précédente a été relâchée, des 0 sont envoyés à
toutes les lignes et les colonnes sont lues et vérifiées jusqu’à ce que toutes les colonnes soient à
un niveau haut.
Lorsque la touche est relâchée, le programme attend un peu (20 ms) avant de passer à l’étape
suivante, c’est-à-dire attendre qu’une touche soit pressée.
- 2o ) Pour voir si une touche est pressée, les colonnes sont examinées encore et
encore jusqu’à ce que l’une d’entre elles ait un niveau bas. Lorsqu’une touche pressée est détectée,
on attend un petit peu pour être sûr qu’il ne s’agit pas d’un simple effleurement de la part de
l’utilisateur et on recommence. Si après ce délai de 20 ms, une touche est encore pressée, on passe
à l’étape suivante de détection de la ligne à laquelle appartient cette touche.
- 3o ) Pour détecter à quelle ligne appartient la touche pressée, on met à la terre
une ligne à la fois (et non plus toutes en même temps). Si on trouve que toutes les colonnes sont
à un niveau haut, ceci signifie que la touche pressée n’appartient pas à cette ligne. On passe donc
à la ligne suivante et on continue ainsi jusqu’à ce qu’on trouve la ligne à laquelle appartient la
touche pressée.
Il se peut qu’aucune ligne ne soit trouvée, par exemple si l’appui sur la touche n’est pas
suffisamment longue. Dans ce cas, on revient à l’interrogation.
Lorsqu’on trouve la ligne à laquelle appartient la touche pressée, on initialise l’adresse du
début de la table contenant les scan codes de la ligne en question.
154 CHAPITRE 6. LE CLAVIER
Il y a trois groupes principaux de touches : à gauche dix touches dites de fonction, étiquetées
de F1 à F10 ; au milieu les touches d’une machine à écrire ordinaire, en particulier les lettres et
les chiffres ainsi que certains caractères spéciaux tels que le changement de mode, des symboles
spéciaux, le verrouillage majuscules et chiffres, le retour arrière et la recopie d’écran ; à droite
un pavé numérique de 15 touches qui selon la position de la touche ‘NumLock’ constituent un
clavier de type calculatrice ou gère le curseur.
Du point de vue ergonomique, ce clavier avait des défauts importants : la touche hh entrée ii
et les deux touches hh Majuscule ii étaient beaucoup trop petites.
6.2. ASPECT MATÉRIEL 157
Le micro-contrôleur utilisé à l’origine est un 8042 d’Intel. Le programme stocké dans l’EPROM
a pour principales fonctions :
— la réalisation d’un diagnostic de vérification lors de la mise sous tension,
— l’examen continuel du clavier et l’identification des touches appuyées et relâchées,
— la gestion d’une zone tampon (buffer) permettant de mémoriser jusqu’à vingt touches de
clavier,
— la gestion de la communication bidirectionnelle en série avec la carte mère lors du transfert
de chaque code de recherche.
158 CHAPITRE 6. LE CLAVIER
6.2.3 Câble
Pour permettre au clavier d’être détaché de l’unité centrale, il est relié à la carte mère grâce
à un câble.
Pour éviter la déperdition des données, le transfert des données entre le clavier (plus exacte-
ment le micro-contrôleur du clavier) et l’unité centrale (plus exactement le bus des données de
la carte mère) s’effectue en série.
Le câble se termine par le connecteur de clavier, qui est un connecteur DIN à cinq broches.
Différence entre majuscule et minuscule.- Le code clavier d’une lettre minuscule est le même que
celui de la majuscule correspondante. Nous verrons que c’est la routine de service de l’interruption
9h du BIOS qui fait la différence en vérifiant qu’on a appuyé sur la touche majuscule et qu’on
ne l’a pas relâchée.
Répétition des touches.- Une fonction de répétition est implémentée sur le micro-contrôleur du
clavier, qui répète le transfert du code d’appui de la touche sur laquelle on appuie jusqu’à ce
qu’on n’en ait plus besoin. Cela évite, par exemple, d’appuyer 80 fois sur la touche ‘-’ pour
remplir une ligne.
Sur le PC/XT, le taux de répétition est fixé à 10 caractères par seconde. C’est le micro-
contrôleur du clavier qui s’occupe de déterminer cette répétition, le programmeur du PC propre-
ment dit n’a pas à s’en occuper.
160 CHAPITRE 6. LE CLAVIER
Pour les dernières touches, cela dépend si on a appuyé ou non sur ‘NumLock’ plutôt que sur
‘Majuscule’ :
Structure du tampon du clavier.- Chaque caractère est stocké dans le tampon sous la forme de
deux octets : l’octet de poids fort est le code clavier et celui de poids faible le code ASCII
correspondant sur le clavier qwerty américain. Le tampon peut donc stocker temporairement 16
caractères.
Seuls les caractères ASCII sont placés dans le tampon. Les touches spéciales servent seulement
à déterminer ceux-ci, de même que les codes de relâchement.
Code clavier étendu.- La plupart des touches ou combinaison de touches donnent lieu à un ca-
ractère ASCII. Dans ce cas les deux octets placés dans le tampon sont, comme nous venons de
le dire, le code clavier et le code ASCII. Cependant ce n’est pas toujours possible : par exemple
si on a appuyé sur la touche de fonction F1, il n’existe pas de code ASCII correspondant. Dans
ce cas on place 0 dans l’octet de poids faible (qui devrait contenir le code ASCII) et ce qu’on
appelle un code clavier étendu dans l’octet de poids fort. Cela ne permet pas de mettre 0 pour
le code ASCII 0, qui se retrouvera comme code clavier étendu :
50 Alt + M
59 F1
60 F2
61 F3
62 F4
63 F5
64 F6
65 F7
66 F8
67 F9
68 F10
71 Home
72 Cursor Up ↑
73 Page Up ⇑
75 Cursor Left ←
77 Cursor Right →
79 End
80 Cursor Down ↓
81 Page Down ⇓
82 Ins (Insert)
83 Del (Delete)
84 Shift + F1
85 Shift + F2
86 Shift + F3
87 Shift + F4
88 Shift + F5
89 Shift + F6
90 Shift + F7
91 Shift + F8
92 Shift + F9
93 Shift + F10
94 Ctrl + F1
95 Ctrl + F2
96 Ctrl + F3
97 Ctrl + F4
98 Ctrl + F5
99 Ctrl + F6
100 Ctrl + F7
101 Ctrl + F8
102 Ctrl + F9
103 Ctrl + F10
104 Alt + F1
105 Alt + F2
106 Alt + F3
107 Alt + F4
108 Alt + F5
109 Alt + F6
110 Alt + F7
111 Alt + F8
6.3. ASPECT LOGICIEL 167
112 Alt + F9
113 Alt + F10
114 Ctrl + PrtSc (Start/Stop Echo to Printer)
115 Ctrl + Cursor Left (Reverse Word)
116 Ctrl + Cursor Right (Advance Word)
117 Ctrl + End [Erase to End of Line (EOL)]
118 Ctrl + PgDn [Erase to End of Screen (EOS)]
119 Ctrl + Home (Clear Screen and Home)
120 Alt + 1
121 Alt + 2
122 Alt + 3
123 Alt + 4
124 Alt + 5
125 Alt + 6
127 Alt + 7
128 Alt + 9
129 Alt + 0
130 Alt + ‘-’
132 Alt + ‘=’
133 Ctrl + PgUp (Top 25 Mines of Text and Home Cursor)
Gestion du tampon du clavier.- Le tampon du clavier est organisé comme un tampon circulaire
géré grâce à deux index. Les valeurs de ces index sont stockées dans la zone de données du
BIOS aux adresses 40:1Ah et 40:1Ch, d’un mot chacun. Le premier, l’index d’écriture (head
pointer KB HEAD), indique la position libre suivante dans le tampon du clavier, là où le prochain
caractère sera stocké. Le second index, l’index de lecture (tail pointer KB TAIL), indique la
position du prochain caractère à lire dans le tampon, c’est-à-dire le premier caractère à fournir à
un programme. En raison du caractère circulaire du tampon, il se peut que la valeur de l’index
de lecture soit supérieure à celle de l’index d’écriture.
Dans le cas où l’index de lecture est strictement inférieur à l’index d’écriture, les mots pointés
par une valeur située entre l’index de lecture strictement inférieure à celle de l’index d’écriture
sont des caractères provenant du clavier.
Dans le cas où l’index de lecture est strictement plus grand que l’index d’écriture, les mots
compris entre l’index de lecture et la fin du tampon (40:3Dh) et ceux compris entre le début du
tampon (40:1Eh) et l’index d’écriture sont des caractères provenant du clavier.
Le tampon est vide si les index de lecture et d’écriture coı̈ncident.
Le tampon est plein si l’index d’écriture vient juste avant l’index de lecture. Ceci a pour
conséquence que, bien que le tampon ait une capacité de 32 octets, il peut seulement stocker 15
caractères de deux octets chacun.
L’index d’écriture est mis à jour par la routine de service de l’interruption 09h alors que
l’index de lecture est mis à jour par celle de l’interruption 16h.
Lorsqu’on lit un caractère dans le tampon grâce à l’interruption INT 16h du BIOS, le pointeur
d’écriture est mis à jour. Le caractère est ainsi retiré logiquement du tampon, bien que le code
ASCII et le code de recherche soient encore présents physiquement, tant qu’ils n’ont pas été
remplacés par une écriture.
168 CHAPITRE 6. LE CLAVIER
Dépassement de capacité du tampon du clavier.- Lorsque le tampon est plein et qu’on appuie à
nouveau sur une touche du clavier, on se trouve dans la situation d’un dépassement de capacité
du tampon du clavier (keyboard overrun).
Le BIOS émet alors un bip sonore. Si aucune application ne récupère de caractères dans le
tampon, le système est bloqué.
La circuiterie du clavier possède son propre tampon pour stocker un maximum de 20 touches.
Lorsque ce tampon est plein, il ne prend plus en compte aucune touche et envoie un octet spécial,
appelé octet de dépassement de capacité (overrun byte) à la carte mère (qui est FFh pour
le PC/XT et 00h pour le PC/AT).
Après avoir récupéré le code de recherche, la routine de service de INT 09h verifie s’il s’agit
de l’octet de dépassement de capacité. Si c’est le cas, elle émet un bip. Sinon elle teste s’il s’agit
d’une touche majuscule, etc.
Exemple.- Si l’on tape au début ‘abc<enter>’, INT 09h stocke les caractères de la façon suivante :
- ‘a’ dans le tampon à l’adresse 41Eh et son scan code 1Eh à l’adresse 41Fh ;
- ‘b’ à l’adresse 420h et son scan code 30h à l’adresse 421h ;
- ‘c’ à l’adresse 422h et son scan code 2Eh à l’adresse 423h ;
- ‘<Enter>’ à l’adresse 424h et son scan code E0h à l’adresse 425h.
La valeur de l’index d’écriture est alors 426h :
Lorsque le programme a fait appel quatre fois à INT 16h, tous les caractères sont lus et l’origine
est aussi à l’adresse 426h, donc le tampon est vide.
Supposons maintenant que l’utilisateur tape ‘fghijklmnopqrs<Enter>’. INT 09h stocke les
caractères en commençant avec comme ’index d’écriture l’adresse 426h :
r s Ent * f g h i j k l m n o p q
41E 420 422 424 426 428 42A 42C 42E 430 432 434 436 438 43A 43C
Lı́ndex d’écriture a alors comme valeur l’adresse 424h, immédiatement devant l’origine d’adresse
426h.
6.3. ASPECT LOGICIEL 169
Principe.- Pour lire un code de recherche, on scrute l’arrivée d’un 1 pour le bit OUTB du registre
de statut du contrôleur de clavier. Lorsqu’il apparaı̂t, on peut récupérer la valeur du code de
recherche dans le tampon de sortie du contrôleur de clavier.
Dans la configuration de l’IBM-PC, ceci est effectué par la routine de service associée à l’inter-
ruption IRQ1, soit INT 09h, comme nous l’avons vu. Elle est implémentée dans le BIOS ; si on
veut la court-circuiter, il faut commencer par l’annihiler.
Un programme.- Le programme suivant affiche les codes de recherche des touches sur lesquelles
on appuie jusqu’à ce qu’on appuie sur la touche d’échappement (de code de recherche 1). Nous
écrivons ce programme en langage C pour nous faciliter la vie en ce qui concerne l’affichage. Pour
désactiver IRQ1, il suffit de masquer le bit 1 du registre IMR du PIC 8259A (port d’adresse 21h).
#include <conio.h>
#include <stdio.h>
void main()
{
int statut; /* statut du controleur de clavier */
int scancode; /* valeur du code de recherche recupere */
On voit bien que lorsqu’on appuie sur une touche, cela donne lieu à au moins deux codes de
recherche : le code d’appui et le code de relâchement correspondant. Il peut même y en avoir
plus pour certaines touches spéciales.
170 CHAPITRE 6. LE CLAVIER
On utilise les deux ports d’adresses 60h et 64h pour accéder aux quatre registres du contrôleur
de clavier, à savoir le tampon d’entrée, le tampon de sortie, le registre de contrôle et
le registre de statut. Il suffit de deux ports puisque chacun de ces registres est seulement
accessible soit en écriture (W), soit en lecture (R), comme l’indique le tableau suivant :
Le contrôleur de clavier du PX/XT est seulement capable de transférer les codes de recherche
via le port d’adresse 60h et de produire une interruption matérielle.
6.3. ASPECT LOGICIEL 171
7 6 5 4 3 2 1 0
OUTB
AUXB
KEYL
PARE
SYSF
INPB
TIM
C/D
— le bit 7 PARE (pour PARity Error) indique si une erreur de parité est intervenue lors du
dernier transfert du clavier (ou du périphérique auxiliaire, à partir du PS/2).
— 1 : dernier octet avec erreur de parité ;
— 0 : dernier octet sans erreur de parité.
— le bit 6 TIM (pour TIMing) est à 1 lorsque le clavier (ou la souris) n’ont pas répondu à une
requête dans la période de durée prédéfinie. Dans ce cas, on doit reformuler la requête en
utilisant la commande Resend que nous verrons plus loin.
— 1 : erreur ;
— 0 : pas d’erreur.
— le bit 5 AUXB (pour AUXiliary B, c’est-à-dire la souris) dit si un octet de données de la
souris est disponible dans le tampon de sortie (uniquement à partir du PS/2).
— 1 : données pour le périphérique auxiliaire ;
— 0 : pas de données.
— le bit 4 KEYL (pour KEYboard LOck) donne le statut de verrouillage du clavier.
— 1 : clavier libre ;
— 0 : clavier vérouillé.
— le bit 3 C/D (pour Command/Data) spécifie si le dernier octet écrit est un octet de com-
mande, transféré par le microprocesseur via le port d’adresse 64h, ou un octet de données,
écrit par le microprocesseur via le port d’adresse 60h.
— 1 : octet de commande écrit via le port 64h ;
— 0 : octet de données écrit via le port 60h.
— le bit 2 SYSF (pour SYStem Flag, soit indicateur système) spécifie des indications sur le
système.
— 1 : auto-test satisfaisant ;
— 0 : réinitialisation.
— le bit 1 INPB (pour INPut keyBoard) spécifie le statut du tampon d’entrée, à savoir si
un caractère est encore présent dans le tampon d’entrée ou si le microprocesseur peut en
envoyer un autre.
— 1 : données de la CPU dans le tampon d’entrée ;
— 0 : tampon d’entrée vide.
— le bit 0 OUTB (pour OUTput keyBoard) donne l’état du tampon de sortie. S’il est à 1, un
octet de données provenant du clavier est disponible dans le tampon de sortie :
— 1 : données du contrôleur de clavier dans le tampon de sortie ;
— 0 : tampon de sortie vide.
172 CHAPITRE 6. LE CLAVIER
Lorsqu’un octet de données est présent, provenant soit du clavier (OUTB à 1), soit de la souris
(AUXB à 1), le bit AUXB ou OUTB est mis automatiquement à 0 lorsque le microprocesseur lit cet
octet. Avant de lire le tampon de sortie du contrôleur, en utilisant une instruction IN, il faut
toujours vérifier, via OUTB et AUXB, que le contrôleur a bien transféré un octet dans le tampon
d’entrée. Ceci peut en effet prendre du temps. Le contrôleur de clavier ne peut pas accepter
d’autre caractère via son tampon d’entrée tant que le microprocesseur n’a pas récupéré le dernier
caractère lu, situé dans le tampon de sortie.
6.4. COMMENTAIRE DU BIOS : ISR DE L’INTERRUPTION 16H 173
Commentaires.- 1o ) Le code de cette routine est placé à l’adresse E82Eh de la mémoire vive (ligne
1726), adresse donnée pour l’interruption 16h dans le tableau des vecteurs des interruptions par
le BIOS (voir par ailleurs), comme on peut le vérifier.
- 2o ) Comme toute routine de service d’interruption, elle est considérée comme
un sous-programme lointain (ligne 1727), pour permettre de passer outre la limitation des 64
KiO. Les interruptions de priorité plus élevée prendront le pas (ligne 1728). Enfin le segment des
données utilisé est celui de la zone de communication du BIOS (lignes 1729 à 1731, qui renvoient
au sous-programme de la ligne 5488, déjà étudié).
- 3o ) Selon la valeur de AH, on renvoie à la partie concernée (lignes 1732 à 1737).
Si AH est différent de 0, 1 et 2, on renvoie à la ligne 1773 qui termine le sous-programme de
façon propre.
- 4o ) Dans le cas AH = 0, c’est-à-dire pour la lecture d’un caractère dans le
tampon, on permet à une interruption de priorité plus élevée de prendre la main pendant un
très court instant, puis on interdit toute autre interruption masquable (lignes 1743 à 1745). Si
le tampon du clavier est vide (lignes 1746 à 1748), on attend qu’il y ait au moins un caractère
dans celui-ci (instruction bloquante). Sinon, on place le premier caractère du tampon dans AX,
comme désiré (ligne 1749), on avance l’index de lecture (lignes 1750 et 1751 ; la procédure K4 a
déjà été étudiée) et on termine proprement la routine de service.
- 5o ) Dans le cas AH = 1, c’est-à-dire pour regarder si un caractère est présent,
on interdit toute autre interruption masquable (lignes 1757). On place l’index de lecture dans
le registre BX (ligne 1758) et on le compare à l’index d’écriture (ligne 1759), ce qui donne la
valeur voulue de l’indicateur ZF. Dans les deux cas, on place le caractère pointé par l’index de
lecture dans AX, même si cela n’a d’intérêt que lorsque le tampon est non vide (ligne 1760). On
ne termine pas la routine de la façon habituelle (lignes 1761 à 1764), puisqu’on veut prendre en
compte l’éventuel changement du registre des indicateurs.
- 6o ) Dans le cas AH = 1, c’est-à-dire pour obtenir le masque de statut du clavier,
il suffit de placer celui-ci dans AX (ligne 1769).
- 7o ) La terminaison propre de la routine de service (lignes 1770 à 1774) consiste
à restaurer les valeurs de BX et de DS et de renvoyer à l’appelant.
6.5. COMMENTAIRE DU BIOS : ISR DE L’INTERRUPTION 9 175
6.5.1 Principe
Le clavier communique avec la carte mère à travers l’interruption matérielle IRQ1 du 8259,
qui est configurée comme INT 09. La routine de service de INT 09 est implémentée dans le BIOS.
Le micro-contrôleur du clavier examine en permanence la matrice du clavier. Lorsqu’une touche
est pressée, elle est identifiée et son code de recherche d’appui est envoyé par liaison série à la
carte mère à travers le câble du clavier. La circuiterie de la carte mère reçoit les bits un par un
comme trame de bits et en retire un octet (le code de recherche) à l’aide d’un registre à décalage
qu’elle présente au port A du 8255 à l’adresse d’entrée-sortie 60h. Le micro-contrôleur déclenche
alors une interruption dont la routine de service effectue les actions suivantes :
— 1. Le code de recherche est lu sur le port 60h.
— 2. Ce code de recherche est testé pour voir s’il appartient à l’une des touches majuscule
(RightShift et LeftShift), Alt, Ctrl,...
— a) Si c’est le cas, le bit approprié des octets de statut du clavier (aux emplacements
mémoire 40:17h et 40:18h) est positionné. Le code de recherche n’est, dans ce cas,
pas écrit dans le tampon du clavier.
— b) Sinon, la routine recherche le code ASCII de la touche. S’il en existe un, celui-ci
ainsi que le code de recherche sont écrits dans le tampon du clavier. Sinon elle écrit
00h (à la place du code ASCII) et le code de recherche dans le tampon du clavier.
— 3. La routine engendre un EOI pour retirer le masque de IRQ1, de façon à pouvoir accepter
un nouvel appel à IRQ1 et termine par un IRET.
Nous venons de voir ce qui se passe dans le cas d’un code d’appui. Lorsqu’une touche est
relâchée, le micro-contrôleur du clavier envoie de la même façon un code de relâchement. L’étape
2 est alors différente :
— 2’. La routine regarde s’il y a une différence de 80h entre le dernier code recherche et
celui-ci. Si c’est le cas, ceci signifie que la touche a été appuyée et relâchée, ce qui est le
comportement normal, et ce second code de recherche est ignoré. Si la touche est tenue
appuyée durant plus de 0,5 secondes, elle est interprétée comme une nouvelle touche et
écrite une nouvelle fois dans le tampon du clavier (comportement appelé typematic par
IBM.
176 CHAPITRE 6. LE CLAVIER
il n’en est pas de même pour l’interruption 9h, qui commence à la ligne 1846, après la fin de
l’interruption 16h et des tableaux de caractères qui suivent :
1845
1846 ;----- KEYBOARD INTERRUPT ROUTINE
1847
E987 1848 ORG 0E987H
E987 1849 KB_INT PROC FAR
E987 FB 1850 STI ; ALLOW FURTHER INTERRUPTS
E988 50 1851 PUSH AX
E989 53 1852 PUSH BX
E98A 51 1853 PUSH CX
E98B 52 1854 PUSH DX
E98C 56 1855 PUSH SI
E98D 57 1856 PUSH DI
E98E 1E 1857 PUSH DS
E98F 06 1858 PUSH ES
E990 FC 1859 CLD ; FORWARD DIRECTION
E991 E8C510 1860 CALL DDS
E994 E460 1861 IN AL,KB_DATA ; READ IN THE CHARACTER
E996 50 1862 PUSH AX ; SAVE IT
E997 E461 1863 IN AL,KB_CTL ; GET THE CONTROL PORT
E999 8AE0 1864 MOV AH,AL ; SAVE VALUE
E99B 0C80 1865 OR AL,80H ; RESET BIT FOR KEYBOARD
E99D E661 1866 OUT KB_CTL,AL
E99F 86E0 1867 XCHG AH,AL ; GET BACK ORIGINAL CONTROL
E9A1 E661 1868 OUT KB_CTL,AL ; KB HAS BEEN RESET
E9A3 58 1869 POP AX ; RECOVER SCAN CODE
E9A4 8AE0 1870 MOV AH,AL ; SAVE SCAN CODE IN AH ALSO
1871
1872 ;----- TEST FOR OVERRUN SCAN CODE FOR KEYBOARD
1873
Commentaires.- 1o ) Le code de cette routine est placé à l’adresse E967h de la mémoire vive (ligne
1848), adresse donnée comme début de la routine de service de l’interruption 9h dans le tableau
des vecteurs des interruptions par le BIOS (voir chapitre 10).
6.5. COMMENTAIRE DU BIOS : ISR DE L’INTERRUPTION 9 177
Le code ASCII (ou 00h dans le cas d’un code étendu) est obtenu à partir du contenu de AH,
c’est-à-dire du code de la touche, et placé dans AL, d’une façon que nous détaillerons ensuite.
Ainsi AX finit par contenir ce qu’il faut placer dans le tampon du clavier. On place donc son
contenu dans le tampon :
2214
2215 ;----- PUT CHARACTER INTO BUFFER
2216
EBD5 2217 K57: ; BUFFER-FILL
EBD5 3CFF 2218 CMP AL,-1 ; IS THIS AN IGNORE CHAR
EBD7 741F 2219 JE K59 ; YES, DO NOTHING WITH IT
EBD9 80FCFF 2220 CMP AH,-1 ; LOOK FOR -1 PSEUDO SCAN
EBDC 741A 2221 JE K59 ; NEAR_INTERRUPT_RETURN
2222
2223 ;----- HANDLE THE CAPS LOCK PROBLEM
2224
EBDE 2225 K58: ; BUFFER-FILL-NOTEST
EBDE F606170040 2226 TEST KB_FLAG,CAPS_STATE ; ARE WE IN CAPS LOCK STATE
EBE3 7420 2227 JZ K61 ; SKIP IF NOT
2228
2229 ;----- IN CAPS LOCK STATE
2230
EBE5 F606170003 2231 TEST KB_FLAG,LEFT_SHIFT+RIGH_SHIFT ; TEST FOR SHIFT STATE
EBEA 74DF 2232 JZ K60 ; IF NOT SHIFT, CONVERT LOWER TO UPPER
2233
2234 ;----- CONVERT ANY UPPER CASE TO LOWER CASE
2235
EBEC 3C41 2236 CMP AL,’A’ ; FIND OUT IF ALPHABETIC
EBEE 7215 2237 JB K61 ; NOT_CAPS_STATE
EBF0 3C5A 2238 CMP AL,’Z’
EBF2 7711 2239 JA K61 ; NOT_CAPS_STATE
EBF4 D420 2240 ADD AL,’a’-’A’ ; CONVERT TO LOWER CASE
EBF6 EB0D 2241 JMP SHORT K61 ; NOT_CAPS_STATE
EBF8 2242 K59: ; HEAR-INTERRUPT-RETURN
EBF8 E95EFE 2243 JMP K26 ; INTERRUPT_RETURN
178 CHAPITRE 6. LE CLAVIER
2244
2245 ;----- CONVERT ANY LOWER CASE TO UPPER CASE
2246
EBFB 2247 K60: ; LOWER-TO-UPPER
EBFB 3C61 2248 CMP AL,’a’ ; FIND OUT IF ALPHABETIC
EBFD 7206 2249 JB K61 ; NOT_CAPS_STATE
EBFF 3C7A 2250 CMP AL,’z’
EC01 7702 2251 JA K61 ; NOT_CAPS_STATE
EC03 2C20 2252 SUB AL,’a’-’A’ ; CONVERT TO UPPER CASE
EC05 2253 K61: ; NOT_CAPS_STATE
EC05 8B1E1C00 2254 MOV BX,BUFFER_TAIL ; GET THE END POINTER TO THE BUFFER
EC09 8BF3 2255 MOV SI,BX ; SAVE THE VALUE
EC0B E863FC 2256 CALL K4 ; ADVANCE THE TAIL
EC0E 3B1E1A00 2257 CMP BX,BUFFER_HEAD ; HAS THE BUFFER WRAPPED AROUND
EC12 7413 2258 JE K62 ; BUFFER_FULL_BEEP
EC14 89D4 2259 MOV [SI],AX ; STORE THE VALUE
EC16 891E1C00 2260 MOV BUFFER_TAIL,BX ; MOVE THE POINTER UP
EC1A E93CFE 2261 JMP K26 ; INTERRUPT_RETURN
2262
Commentaires.- 6o ) S’il s’agit d’une combinaison de touches non prévue (lignes 2218 à 2221), on
indique ce fait en mettant -1 dans AL ou dans AH. Dans ce cas, on ignore tout simplement le
caractère, on va donc directement à la fin de la routine de service (K59 qui, ligne 2243, renvoie
à K26) que nous étudierons ci-dessous.
- 7o ) Si l’état ‘CapsLock’ est actif (lignes 2226 et 2227) ou si l’une des touches
majuscules est appuyée (lignes 2231 et 2232), on convertit les lettres majuscules en minuscule
(lignes 2236 à 2241) et les lettres minuscules en majuscule (lignes 2248 à 2252).
- 8o ) Après ces transformations éventuelles, on place l’index d’écriture dans le
registre BX, on le sauvegarde dans le registre SI pour pouvoir placer le contenu de AX dans le
tampon et on appelle le sous-programme K4 pour mettre à jour cet index (lignes 2254 à 2256).
- 9o ) Le sous-programme K4 incrémente deux fois BX (puisque l’index d’écriture
occupe deux octets). Si on est arrivé à la fin de la zone du tampon, on passe au début de celle-ci
puisqu’il s’agit d’un tampon circulaire.
1775
1776 ;----- INCREMENT A BUFFER POINTER
1777
E871 1778 K4 PROC NEAR
E871 43 1779 INC BX ; MOVE TO NEXT WORD IN LIST
E872 43 1780 INC BX
E873 3B1E8200 1781 CMP BX,BUFFER_END ; AT END OF BUFFER?
E877 7504 1782 JNE K5 ; NO. CONTINUE
E879 8B1E8000 1783 MOV BX,BUFFER_START ; YES, RESET TO BUFFER BEGINNING
E87D 1784 K5:
E87D C3 1785 RET
1786 K4 ENDP
1787
- 10o ) On regarde ensuite si le tampon du clavier est plein. S’il en est ainsi, on
émet un bip en faisant appel à K62 (lignes 2257 et 2258), étudié dans la section suivante.
6.5. COMMENTAIRE DU BIOS : ISR DE L’INTERRUPTION 9 179
A0 D7 D6 D5 D4 D3 D2 D1 D0
0 R SL EOI 0 0 L2 L1 L0
R et SL sont nuls et EOI est égal à 1, on a donc un EOI non spécifique, c’est-à-dire que le
bit IS est mis à 1 (dans le mode fully nested du PC), permettant la prise en compte d’une
interruption de niveau inférieur,
— et enfin à restaurer les valeurs des registres aynt été sauvegardées telles qu’elles étaient
avant l’entrée dans la routine de service et à sortir de celle-ci.
180 CHAPITRE 6. LE CLAVIER
La partie de la routine qui fait biper commence, quant à elle, à la ligne 2275 :
2274
2275 ;-----BUFFER IS FULL, SOUND THE BEEPER
2276
EC27 2277 K62: ; BUFFER-FULL-BEEP
EC27 B020 2278 MOV AL,EOI ; END OF INTERRUPT COMMAND
EC29 E620 2279 OUT 20H,AL ; SEND COMMAND TO INT CONTROL PORT
EC2B B88000 2280 MOV BX,080H ; NUMBER OF CYCLES FOR 1/12 SECOND TONE
EC2E E461 2281 IN AL,KB_CTL ; GET CONTROL INFORMATION
EC30 50 2282 PUSH AX ; SAVE
EC31 2283 K65: ; BEEP-CYCLE
EC31 24FC 2284 AND AL,DFCH ; TURN OFF TIMER GATE AND SPEAKER DATA
EC33 E661 2285 OUT KB_CTL,AL ; OUTPUT THE CONTROL
EC35 B94800 2286 MOV CX,48H ; HALF CYCLE TIME FOR TONE
EC38 2287 K66:
EC38 E2FE 2288 LOOP K66 ; SPEAKER OFF
EC3A 0C02 2289 OR AL,2 ; TURN ON SPEAKER BIT
EC3C E661 2290 OUT KB_CTL,AL ; OUTPUT THE CONTROL
EC3E B94800 2291 MOV CX,48H ; SET UP COUNT
EC41 2292 K67:
EC41 E2F2 2293 LOOP K67 ; ANOTHER HALF CYCLE
EC43 4B 2294 DEC BX ; TOTAL TIME COUNT
EC44 75EB 2295 JNZ K65 ; DO ANOTHER CYCLE
EC46 58 2296 POP AX ; RECOVER CONTROL
EC47 E661 2297 OUT KB_CTL,AL ; OUTPUT THE CONTROL
EC49 E912FE 2298 JMP K27
2299
6.5. COMMENTAIRE DU BIOS : ISR DE L’INTERRUPTION 9 181
Commentaires.- 1o ) Les lignes 1788 à 1795 sont occupées par la table des codes des touches de
décalage et par la longueur de celle-ci.
Rappelons que symboles pour les codes des touches de décalage (NUM KEY, SCROLL KEY,
ALT KEY, CTL KEY, CAPS KEY, LEFT KEY, RIGHT KEY, INS KEY) ont été définis aux
lignes 122 à 130 de la zone de communication du BIOS.
- 2o ) Les lignes 1796 à 1802 sont occupées par la table des masques correspondants
à ces touches tels qu’ils apparaissent dans les octets de statut du clavier.
Rappelons que les masques INS SHIFT, CAPS SHIFT, NUM SHIFT, SCROLL SHIFT ainsi
que ALT SHIFT, CTL SHIFT, LEFT SHIFT et RIGHT SHIFT ont été définis aux lignes 101 à
111 de la zone de communication du BIOS.
182 CHAPITRE 6. LE CLAVIER
Nous avons vu que lorsqu’il ne s’agit pas du pseudo-code de tampon plein, la routine de
service renvoie à K16, qui commence ligne 1878 :
1877
1878 ;----- TEST FOR SHIFT KEYS
1879
E9AD 1880 K16: ; TEST_SHIFT
E9AD 247F 1881 AND AL,07FH ; TURN OFF THE BREAK BIT
E9AF 0E 1882 PUSH CS
E9B0 07 1883 POP ES ; ESTABLISH ADDRESS OF SHIFT TABLE
E9B1 BF7EE8 1884 MOV DI,OFFSET K6 ; SHIFT KEY TABLE
E9B4 B9D800 1885 MOV CX,K61 ; LENGTH
E9B7 F2 1886 REPNE SCASB ; LOOK THROUGH THE TABLE FOR A MATCH
E9B8 AE
E9B9 8AC4 1887 MOV AL,AH ; RECOVER SCAN CODE
E9BB 7403 1888 JE K17 ; JUMP IF MATCH FOUND
E9BD E98500 1889 JMP K25 ; IF NO MATCH, THEN SHIFT NOT FOUND
1890
1891 ;----- SHIFT KEY FOUND
1892
E9C0 81EF7FE8 1893 K17: SUB DI,OFFSET K6+1 ; ADJUST PTR TO SCAN CODE MTCH
E9C4 2E8AA586E8 1894 MOV AH,CS:K7[DI] ; GET MASK INTO AH
E9C9 A880 1895 TEST AL,80H ; TEST FOR BREAK KEY
E9CB 7403 1896 JMP K23 ; BREAK_SHIFT_FOUND
1897
1898 ;----- SHIFT MAKE FOUND, DETERMINE SET OR TOGGLE
1899
E9CD 80DF10 1900 CMP AH,SCROLL_SHIFT
E9D0 7307 1901 JAE K18 ; IF SCROLL SHIFT OR ABOVE, TOGGLE KEY
1902
1903 ;----- PLAIN SHIFT KEY, SET SHIFT ON
1904
E9D2 D8261700 1905 OR KB_FLAG,AH ; TURN ON SHIFT BIT
E9D6 E98000 1906 JMP K26 ; INTERRUPT_RETURN
1907
1908 ;----- TOGGLED SHIFT KEY, TEST FOR 1ST MAKE OR NOT
1909
E9D9 1910 K18: ; SHIFT-TOGGLE
E9D9 F606170004 1911 TEST KB_FLAG, CTL_SHIFT ; CHECK CTL SHIFT STATE
E9DE 7565 1912 JNZ K25 ; JUMP IF CTL STATE
E9E0 3C52 1913 CMP AL,INS_KEY ; CHECK FOR INSERT KEY
E9E2 7522 1914 JNZ K22 : JUMP IF NOT INSERT KEY
E9E4 F606170008 1915 TEST KB_FLAG, ALT_SHIFT ; CHECK FOR ALTERNATE SHIFT
E9E9 755A 1916 JNZ K25 ; JUMP IF ALTERNATE SHIFT
E9EB F606170020 1917 K19: TEST KB_FLAG, NUM_STATE ; CHECK FOR BASE STATE
E9F0 750D 1918 JNZ K21 ; JUMP IF NUM LOCK IS ON
E9F2 F606170003 1919 TEST KB_FLAG, LEFT_SHIFT+RIGHT_SHIFT
E9F7 740D 1920 JZ K22 ; JUMP IF BASE STATE
1921
E9F9 1922 K20: ; NUMERIC ZERO, NOT INSERT KEY
E9F9 B83052 1923 MOV AX, 5230H ; PUT OUT AN ASCII ZERO
E9FC E90601 1924 JMP K57 ; BUFFER_FILL
E9FF 1925 K21: ; MIGHT NUMERIC, NOT INSERT
E9FF F606170003 1926 TEST KB_FLAG, LEFT_SHIFT+RIGHT_SHIFT
EA04 74F3 1927 JZ K20 ; JUMP NUMERIC, NOT INSERT
1928
EA06 1929 K22: ; SHIFT TOGGLE KEY IT; PROCESS IT
EA06 84261800 1930 TEST AH,KB_FLAG_1 ; IS KEY ALREADY DEPRESSED
EA0A 7540 1931 JNZ K26 ; JUMP IF KEY ALREADY DEPRESSED
EA0C 08261800 1932 OR KB_FLAG_1,AH ; INDICATE THAT THE KEY IS DEPRESSED
EA10 30261700 1933 XOR KB_FLAG,AH ; TOGGLE THE SHIFT STATE
EA14 3C52 1934 CMP AL,INS_KEY ; TEST FOR 1ST MAKE OF INSERT KEY
EA16 7541 1935 JNE K26 ; JUMP IF NOT INSERT KEY
EA18 B80052 1936 MOV AX,INS_KEY*256 ; SET SCAN CODE INTO AH, 0 INTO AL
EA1B E98701 1937 JMP K57 ; PUT INTO OUTPUT BUFFER
1938
1939 ;----- BREAK SHIFT FOUND
1940
EA1E 1941 K23: ; BREAK-SHIFT-FOUND
EA1E 80FC10 1942 CMP AH,SCROLL_SHIFT ; IS THIS A TOGGLE KEY
EA21 731A 1943 JAE K24 ; YES, HANDLE BREAK TOGGLE
EA23 F6D4 1944 NOT AH ; INVERT MASK
EA25 20261700 1945 AND KB_FLAG,AH ; TURN OFF SHIFT BIT
EA29 3CB8 1946 CMP AL,ALT_KEY+80H ; IS THIS ALTERNATE SHIFT RELEASE
6.5. COMMENTAIRE DU BIOS : ISR DE L’INTERRUPTION 9 183
- 8o ) S’il s’agit d’une touche de verrouillage et qu’on avait déjà appuyé dessus, on
termine proprement la routine de service (lignes 1930 et 1031). Sinon on indique qu’on a appuyé
sur cette touche dans le deuxième octet de statut du clavier (ligne 1932) et on bascule l’état
de cette touche dans le premier octet de statut du clavier (ligne 1933). S’il ne s’agit pas de la
première fois que l’on appuie sur la touche ‘Insert’, on place le code de recherche dans AH, 0
dans AL et on place le tout dans le tampon (lignes 1934 à 1937).
- 9o ) Dans le cas d’un code de relâchement, s’il ne s’agit pas d’une touche de
verrouillage (lignes 1942 et 1943), on inverse le masque (ligne 1944) de façon à prendre en
compte le basculement dans le premier octet de statut du clavier (ligne 1945).
- 10o ) S’il ne s’agit pas du code de relâchement de la touche ‘Alt’, on termine
proprement la routine de service (lignes 1946 et 1947).
- 11o ) Rappelons que ALT INPUT est un emplacement d’un octet de la zone de
communication du BIOS, défini à la ligne 112, servant à former un nombre de 1 à 255, représentant
un code ASCII. Celui-ci est obtenu en appuyant sur la touche ‘Alt’ et sur les touches de chiffres de
‘0’ à ‘9’ du clavier numérique de façon à spécifier ce nombre en numération décimale. Lorsqu’on
relâche le touche ‘Alt’, le code ASCII désiré se trouve donc (nous verrons comment plus loin)
dans ALT INPUT ; on le place donc dans AL (ligne 1951). On réinitialise ALT INPUT à 0 pour la
prochaine fois (lignes 1952 et 1953). Si le code ASCII est 0 (ligne 1954), ce qu’il n’est pas permis
d’obtenir de cette façon, on termine proprement la routine de service (ligne 1955). Sinon on place
le caractère (avec code de recherche égal à 0) dans le tampon (ligne 1956).
- 12o ) Dans le cas où on relâche une touche de verrouillage, on indique qu’elle
n’est plus enfoncée dans le second octet de statut du clavier (lignes 1958 et 1959) et on termine
proprement la routine de service (ligne 1960).
Commentaires.- 1o ) S’il s’agit d’un code de relâchement (ligne 1965), on passe directement à la
terminaison propre de la routine de service (ligne 1966), déjà étudiée.
- 2o ) Si on a appuyé sur ‘Pause’, c’est-à-dire sur ‘Ctrl’ (ligne 1967) et sur ‘Numlock’
(ligne 1969), on bascule éventuellement le fait d’avoir appuyé sur la touche ‘Ctrl’ (ligne 1971)
et on termine proprement la routine de service (lignes 1970 et à partir de la ligne 1972, déjà
étudiées). Sinon on continuera notre recherche (ligne 1968).
6.5. COMMENTAIRE DU BIOS : ISR DE L’INTERRUPTION 9 185
Nous avons vu que si nous ne sommes pas dans le cas de la touche pause, on est renvoyé à
K28, qui commence à la ligne 1987 :
1987
1988 ;----- NOT IN HOLD STATE, TEST FOR SPECIAL CHARS
1989
EA67 1990 K28: ; NO-HOLD-STATE
EA67 F606170008 1991 TEST KB_FLAG,ALT_SHIFT ; ARE WE IN ALTERNATE SHIFT ALSO
EA6C 7503 1992 JNZ K29 ; JUMP IF ALTERNATE SHIFT
EA6E E99100 1993 JMP K38 ; JUMP IF NOT ALTERNATE
1994
1995 ;----- TEST FOR RESET KEY SEQUENCE (CTL ALT DEL)
1996
EA71 1997 K29: ; TEST-RESET
EA71 F606170004 1998 TEST KB_FLAG,CTL_SHIFT ; ARE WE IN CONTROL SHIFT ALSO
EA76 7433 1999 JZ K31 ; NO_RESET
EA78 3C53 2000 CMP AL,DEL_KEY ; SHIFT STATE IS THERE, TEST KEY
EA7A 752F 2001 JNE K31 ; NO_RESET
2002
2003 ;----- CTL-ALT-DEL HAS BEEN FOUND, DO I/O CLEANUP
2004
EA7C C70672003412 2005 MOV RESET_FLAG, 1234H ; SET FLAG FOR RESET FUNCTION
EA82 EA5BE000F0 2006 JMP RESET ; JUMP TO POWER ON DIAGNOSTICS
2007
2008 ;----- ALT-INPUT-TABLE
EA87 2009 K30 LABEL BYTE
EA87 52 2010 DB 82,79,80,81,75,76,77
EA88 4F
EA89 50
EA8A 51
EA8B 4B
EA8C 4C
EA8D 4D
EA8E 47 2011 DB 71,72,73 ; 10 NUMBERS ON KEYPAD
EA8F 48
EA90 49
2012 ;----- SUPER-SHIFT-TABLE
EA91 10 2013 DB 16,17,18,19,20,21,22,23 ; A-Z TYPEWRITER CHARS
186 CHAPITRE 6. LE CLAVIER
EA92 11
EA93 12
EA94 13
EA95 14
EA96 15
EA97 16
EA98 15
EA99 18 2014 DB 24,25,30,31,32,33,34,35
EA9A 19
EA9B 1E
EA9C 1F
EA9D 20
EA9E 21
EA9F 22
EAA0 23
EAA1 24 2015 DB 36,37,38,44,45,46,47,48
EAA2 25
EAA3 26
EAA4 2C
EAA5 2D
EAA6 2E
EAA7 2F
EAA8 30
EAA9 31 2016 DB 49,50
EAAA 32
2017
2018 ;----- IN ALTERNATE SHIFT, RESET NOT FOUND
2019
EAAB 2020 K31: ; NO-RESET
EAAB 3C39 2021 CMP AL,57 ; TEST FOR SPACE KEY
EAAD 7505 2022 JNE K32 ; NOT THERE
EAAF B020 2023 MOV AL,’ ’ ; SET SPACE CHAR
EAB1 E92101 2024 JMP K57 ; BUFFER_FILL
2025
2026 ;----- LOOK FOR KEY PAD ENTRY
2027
EAB4 2028 K32: ; ALT_KEY-PAD
EAB4 BF87EA 2029 MOV DI,OFFSET K30 ; ALT-INPUT-TABLE
EAB7 B90A00 2030 MOV CX,10 ; LOOK FOR ENTRY USING KEYPAD
EABA F2 2031 REPNE SCASB ; LOOK FOR MATCH
EABB AE
EABC 7512 2032 JNE K33 ; NO_ALT_KEYPAD
EABE 81EF88EA 2033 SUB DI,OFFSET K30+1 ; DI NOW HAS ENTRY VALUE
EAC2 A01900 2034 MOV AL,ALT_INPUT ; GET THE CURRENT BYTE
EAC5 B40A 2035 MOV AH,10 ; MULTIPLY BY 10
EAC7 F6E4 2036 MUL AH
EAC9 03C7 2037 ADD AX,DI ; ADD IN THE LATEST ENTRY
EACB A2190D 2038 MOV ALT_INPUT,AL ; STORE IT AWAY
EACE EB89 2039 JMP K26 ; THROW AWAY THAT KEYSTROKE
2040
2041 ;----- LOOK FOR SUPERSHIFT ENTRY
2042
EAD0 2043 K33: ; NO-ALT-KEYPAD
EAD0 C606190000 2044 MOV ALT_INPUT,0 ; ZERO ANY PREVIOUS ENTRY INTO INPUT
EAD5 B91A00 2045 MOV CX,26 ; DI,ES ALREADY POINTING
EAD8 F2 2046 REPNE SCASB ; LOOK FOR MATCH IN THE BUFFER
EAD9 AE
EADA 7505 2047 JNE K34 ; NOT FOUND, FUNCTION KEY OR OTHER
EADC 8000 2048 MOV AL,0 ; ASCII CODE OF ZERO
EADE E9F400 2049 JMP K57 ; PUT IT IN THE BUFFER
2050
2051 ;----- LOOK FOR TOP ROW OF ALTERNATE SHIFT
2052
EAE1 2053 K34: ; ALT-TOP-ROW
EAE1 3C02 2054 CMP AL,2 ; KEY WITH ’1’ ON IT
EAE3 7503 2055 JB K35 ; NOT ONE OF INTERESTING KEYS
EAE5 3C0E 2056 CMP AL,14 ; IS IT IN THE REGION
EAE7 7508 2057 JAE K35 ; ALT-FUNCTION
EAE9 80C476 2058 ADD AH,118 ; CONVERT PSEUDO SCAN CODE TO RANGE
EAEC B000 2059 MOV AL,0 ; INDICATE AS SUCH
EAEE E9E400 2060 JMP K57 ; BUFFER_FILL
2061
2062 ;----- TRANSLATE ALTERNATE SHIFT PSEUDO SCAN CODES
2063
6.5. COMMENTAIRE DU BIOS : ISR DE L’INTERRUPTION 9 187
Commentaires.- 1o ) Si la touche ‘Alt’ est pressée (lignes 1991–1992), nous sommes dans le cas
des combinaisons de touches faisant intervenir ‘Alt’, que nous allons maintenant étudier. Sinon
on poursuit notre recherche (ligne 1993).
- 2o ) On commence par le cas de l’appui simultané sur les touches ‘Ctrl’, ‘Alt’
et ‘Del’, spécifiant un redémarrage. On regarde si on a appuyé sur la touche ‘Ctl’ (lignes 1998
et 1999) et sur la touche ‘Del’ (lignes 2000 et 2001). S’il en est ainsi, signifiant que l’on veut
un redémarrage à chaud du PC, on place donc ‘1234’ à l’emplacement voulu de la zone de
communication du BIOS (ligne 2005) et on revient à la partie du BIOS consacrée au démarrage
(ligne 2006), que nous étudierons plus tard.
- 3o ) Rappelons que les chiffres de ‘0’ à ‘9’ du clavier numérique ont pour codes
de touche respectifs 82, 79, 80, 81, 75, 76, 77, 71, 72 et 73. C’est ce que rappelle la table des
lignes 2008 à 2011.
- 4o ) Rappelons que l’appui sur ‘Alt’ et sur l’une des touches de lettres ‘A’ à ‘Z’
donne lieu à un code étendu compris entre 16 et 25, 30 et 38, 44 et 50. Il s’agit tout simplement
du code de la touche correspondante. Ces codes sont rappelés sur la table des lignes 2012 à 2017.
- 5o ) Nous avons vu que lorsque la touche ‘Alt’ est pressée, sans que ce soit
Ctl-Alt-Del, on est renvoyé en K31, qui commence ligne 2020.
S’il s’agit de la barre d’espacement (touche de code 57), on place le code ASCII correspondant
(32 ou 20h) dans AL. Ainsi AH contient le code de recherche et AL le code ASCII. On peut
donc aller à l’étiquette BUFFER FILL pour placer ceux-ci dans le tampon du clavier (lignes 2021
à 2024).
- 6o ) Si la touche appuyée se trouve sur la partie clavier numérique (lignes 2029
à 2032), on place la valeur de la touche dans le registre DI (ligne 2033), en jouant sur le fait
que pour un chiffre x sa valeur est x - ‘0’. On place la valeur conservée dans ALT INPUT dans
AL (ligne 2034), que l’on multiplie par 10 (lignes 2035 et 2036), puis on lui ajoute la valeur du
chiffre placée dans DI (ligne 2037), on stocke le tout dans ALT INPUT (ligne 2038), et on termine
proprement la routine de service (ligne 2039).
Autrement dit on a utilisé la méthode de Hörner pour placer un nombre (et pas seulement
un chiffre) dans ALT INPUT.
- 7o ) Si on ne se trouve pas sur le pavé numérique, on réinitialise ALT INPUT à 0
pour une prochaine fois (ligne 2044) puis on recherche si la touche appuyée est celle d’une lettre
de ‘A’ à ‘Z’ (lignes 2045 à 2047). Si on a appuyé sur une telle touche, on place 0 dans AL pour
indiquer qu’il s’agit d’un code étendu, le code de la touche se trouvant dans AH correspond au
code étendu, il suffit donc de placer le contenu de AX dans le tampon (lignes 2048 et 2049).
- 8o ) S’il s’agit des touches de code 2 à 13 (lignes 2054 à 2057), c’est-à-dire de la
première ligne du clavier (les chiffres ‘1’ à ‘0’, ‘-’, ‘=’ et PgUp), cela donne lieu à un code étendu
de 120 à 133, c’est-à-dire le code de la touche plus 118. On translate donc le code de la touche
de 118 (ligne 2058), on place 0 dans AL et le tout dans le tampon du clavier.
- 9o ) S’il s’agit d’un code de recherche compris entre 59 et 71, on l’ignore, c’est-
à-dire qu’on termine proprement la routine de service (lignes 2065 à 2071).
188 CHAPITRE 6. LE CLAVIER
- 10o ) Il reste le cas de l’appui simultané sur ‘Alt’ et d’une touche de fonction.
On transforme le code de la touche en code étendu (lignes 2072 et 2073) grâce à la table définie
lignes 1836 et 1837. Pour cela on saute à la partie du BIOS commençant ligne 2263 :
2263 ;----- TRANSLATE SCAN FOR PSEUDO SCAN CODES
2264
EC1D 2265 K63: ; TRANSLATE-SCAN
EC1D 2C38 2266 SUB AL,59 ; CONVERT ORIGIN TO FUNCTION KEYS
EC1F 2267 K64: ; TRANSLATE-SCAN-ORGO
EC1F 2ED7 2268 XLAT CS:K9 ; CTL TABLE SCAN
EC21 8AE0 2269 MOV AH,AL ; PUT VALUE INTO AH
EC23 B000 2270 MOV AL,0 ; ZERO ASCII CODE
EC25 EBAE 2271 JMP K57 ; PUT IT INTO THE BUFFER
2272
2273 KB_INT ENDP
2274
Les codes étendus 94 à 103 correspondent à l’appui simultané sur ‘Ctrl’ et l’une des touches
de fonction (de codes 59 à 68), pas de code (donc -1) pour les touches 69 et 70 (c’est-à-dire
‘NumLock’ et ‘ScrollLock’), puis aux touches du pavé numérique (de codes 71 à 83).
Nous avons vu que si nous ne sommes pas dans le cas d’une combinaison de touches avec
‘Alt’, on est renvoyé en K38, qui commence ligne 2075 :
2075 ;----- NOT IN ALTERNATE SHIFT
2076
EB02 2077 K38: ; NOT-ALT-SHIFT
EB02 F606170004 2078 TEST KB_FLAG,CTL_SHIFT ; ARE WE IN CONTROL SHIFT
EB07 7458 2079 JZ K44 ; NOT-CTL-SHIFT
2080
2081 ;----- CONTROL SHIFT, TEST SPECIAL CHARACTERS
2082 ;----- TEST FOR BREAK AND PAUSE KEYS
2083
EB09 3C46 2084 CMP AL,SCROLL_KEY ; TEST FOR BREAK
EB0B 7518 2085 JNE K39 ; NO-BREAK
EB0D 8B1E8000 2086 MOV BX,BUFFER_START ; RESET BUFFER TO EMPTY
EB11 891E1A00 2087 MOV BUFFER_HEAD,BX
EB15 891E1A00 2088 MOV BUFFER_TAIL,BX
EB19 C606710080 2089 MOV BIOS_BREAK,80H ; TURN ON BIOS_BREAK BIT
EB1E CD1B 2090 INT 1BH ; BREAK INTERRUPT VECTOR
EB20 2BC0 2091 SUB AX,AX ; PUT OUT DUMMY CHARACTER
EB22 E98088 2092 JMP K57 ; BUFFER_FILL
EB25 2093 K39: ; NO-BREAK
EB25 3C45 2094 CMP AL,NUM_KEY ; LOOK FOR PAUSE KEY
EB27 7521 2095 JNE K41 ; NO-PAUSE
EB29 80DE180008 2096 OR KB_FLAG_1,HOLD_STATE ; TURN ON THE HOLD FLAG
EB2E B020 2097 MOV AL,EOI ; END OF INTERRUPT TO CONTROL PORT
EB30 E620 2098 OUT 020H,AL ; ALLOW FURTHER KEYSTROKE INTS
190 CHAPITRE 6. LE CLAVIER
2099
2100 ;----- DURING PAUSE INTERVAL, TURN CRT BACK ON
2101
EB32 803E490007 2102 CMP CRT_MODE,7 ; IS THIS BLACK AND WHITE CARD
EB37 7407 2103 JE K40 ; YES, NOTHING TO DO
EB39 BAD803 2104 MOV DX,D308H ; PORT FOR COLOR CARD
EB3C A06500 2105 MOV AL,CRT_MODE_SET ; GET THE VALUE OF THE CURRENT MODE
EB3F EE 2106 OUT DX,AL ; SET THE CRT MODE, SO THAT CRT IS ON
EB40 2107 K40: ; PAUSE-LOOP
EB40 F606180008 2108 TEST KB_FLAG_1,HOLD_STATE
EB45 75F9 2109 JNZ K40 ; LOOP UNTIL FLAG TURNED OFF
EB47 E914FF 2110 JMP K27 ; INTERRUPT_RETURN_NO_EOI
EB4A 2111 K41: ; NO-PAUSE
2112
2113 ;----- TEST SPECIAL CASE KEY 55
2114
EB4A 3C37 2115 CMP AL,55
EB4C 7506 2116 JNE K42 ; NOT-KEY-55
EB4E B80072 2117 MOV AX,114*256 ; START/STOP PRINTING SWITCH
EB51 E98100 2118 JMP K57 ; BUFFER_FILL
2119
2120 ;----- SET UP TO TRANSLATE CONTROL SHIFT
2121
EB54 2122 K42: ; NOT-KEY-55
EB54 BB8EE8 2123 MOV BX,OFFSET K8 ; SET UP TO TRANSLATE CTL
EB57 3C3B 2124 CMP AL,59 ; IS IT IN TABLE
2125 ; CTL-TABLE-TRANSLATE
EB59 7276 2126 JB K56 ; YES, GO TRANSLATE CHAR
EB5B 2127 K43: ; CTL-TABLE-TRANSLATE
EB5B BBC8E8 2128 MOV BX,OFFSET K9 ; CTL TABLE SCAN
EB5E E9BC00 2129 JMP K63 ; TRANSLATE_SCAN
2130
Commentaires.- 1o ) Si la touche ‘Ctrl’ est pressée (lignes 2078), nous sommes dans le cas des
combinaisons de touches faisant intervenir ‘Ctrl’ (sauf ‘Ctrl-Alt-DEl’ déjà traité), que nous allons
maintenant étudier. Sinon on poursuit notre recherche (ligne 2079).
- 2o ) Si on est en train d’appuyer sur la touche ‘ScrollLock’, c’est qu’on veut passer
à la fonction ‘Break’. C’est le premier cas qui est traité (lignes 2084 et 2085). Pour cela on vide le
tampon du clavier (lignes 2086 à 2088), on fait appel à l’interruption 1Bh (interruption du BIOS
chargée de la fonction ‘Break’ ; ligne 2090), on place 0 dans AX (ligne 2091), correspondant au
code ASCII de numéro 0, que l’on place dans le tampon du clavier (ligne 2092).
- 3o ) Si on est en train d’appuyer sur la touche ‘NumLock’, c’est qu’on veut une
‘Pause’ (lignes 2094 et 2095). Dans ce cas, on l’indique dans le second octet d’état du clavier
(ligne 2096). On permet à une autre interruption de prendre la main (lignes 2097 et 2098). On
gèle l’écran (lignes 2102 à 2106) et on attend jusqu’à ce qu’on appuie sur une autre touche (lignes
2107 à 2110).
- 4o ) Si on est en train d’appuyer sur la touche ‘PrtSc’ (de code 55 ; lignes 2115 et
2116), on place le code spécial de début/fin d’impression dans le tampon du clavier (lignes 2117
et 2118).
6.5. COMMENTAIRE DU BIOS : ISR DE L’INTERRUPTION 9 191
- 5o ) On place (ligne 2123) dans BX le début de la table des codes ASCII cor-
respondants aux codes des touches dans le cas où on a appuyé sur la touche ‘Ctrl’ pour les
58 premiers codes de touches (ce que l’on peut vérifier avec le tableau des caractères donné
antérieurement) :
1802
1803 ;----- SCAN CODE TABLES
1804
E88E 1B 1805 K8 DB 27,-1,0,-1,-1,-1,30,-1
E88F FF
E890 00
E891 FF
E892 FF
E893 FF
E894 1E
E895 FF
E896 FF 1806 DB -1,-1,-1,31,-1,127,-1,17
E897 FF
E898 FF
E899 1F
E89A FF
E89B 7F
E89C FF
E89D 11
E89E 17 1807 DB 23,5,18,20,25,21,9,15
E89F 05
E8A0 12
E8A1 14
E8A2 19
E8A3 15
E8A4 09
E8A5 0F
E8A6 10 1808 DB 16,27,29,10,-1,1,19
E8A7 1B
E8A8 1D
E8A9 0A
E8AA FF
E8AB 01
E8AC 13
E8AD 04 1809 DB 4,6,7,8,10,11,12,-1,-1
E8AE 06
E8AF 07
E8B0 08
E8B1 0A
E8B2 0B
E8B3 0C
E8B4 FF
E8B5 FF
E8B6 FF 1810 DB -1,-1,28,26,24,3,22,2
E8B7 FF
E8B8 1C
E8B9 1A
E8BA 18
E8BB 03
E8BC 16
E8BD 02
E8BE 0E 1811 DB 14,13,-1,-1,-1,-1,-1,-1
E8BF 0D
E8C0 FF
E8C1 FF
E8C2 FF
E8C3 FF
E8C4 FF
E8C5 FF
E8C6 20 1812 DB ’ ’,-1
E8C7 FF
Si le code de touche est inférieur à 58, on utilise cette table (ligne 2124) pour obtenir le code
ASCII puis on place le caractère correspondant dans le tampon du clavier (ligne ligne 2128) :
on prend comme origine la table suivante car on décrit les tables à l’envers. On va donc en K63
(ligne 2129), partie déjà étudiée.
192 CHAPITRE 6. LE CLAVIER
On traduit le code clavier en code ASCII et on place le contenu de AX dans le tampon (ligne
2159 qui renvoie à K63, partie déjà étudiée).
6.5. COMMENTAIRE DU BIOS : ISR DE L’INTERRUPTION 9 195
- 5o ) Si aucune des touches majuscule n’est pressée, nous sommes dans le cas des
minuscules. On se positionne à la fin de la table K10 (ligne 2161, c’est-à-dire le décalage de la
table K11 car on décrit les tables à l’envers) des codes ASCII correspondant aux codes lorsque
la majuscule n’est pas activée :
1819 ;----- LC TABLE
E8E1 1820 K10 LABEL BYTE
E8E1 1B 1821 DB 01BH,’1234567890-=’,08H,09H
E8E2 31323334353637
3839302D3D
E8EE 08
E8EF 09
E8F0 71776572747975 1822 DB ’qwertyuiop[]’,0DH,-1,’asdfghjkl;’,027H
696F705B5D
E8FC 0D
E8FD FF
E8FE 6173646667686A
6B6C3B
E908 27
E909 60 1823 DB 60H,-1,5CH,’zxcvbnm,./’,-1,’*’,-1,’ ’
E90A FF
E90B 7A786376626E60
2C2E2F
E916 FF
E917 2A
E918 FF
E919 20
E91A FF 1824 DB -1
On traduit le code clavier en code ASCII et on place le contenu de AX dans le tampon (ligne
2162 qui renvoie à K56, partie déjà étudiée).
- 6o ) On teste ensuite si la touche appuyée appartient au clavier numérique, ce
qui nous a renvoyé en K48, c’est-à-dire à la ligne 2166. On distingue (lignes 2167 à 2170) deux
cas suivant que ‘NumLock’ est actif ou que l’on a appuyé sur une touche majuscule (dans ce cas
on a le clavier numérique proprement dit) ou non (dans ce cas on a le clavier de changement de
position du curseur).
- 7o ) Dans le cas où il s’agit du clavier numérique proprement dit, on commence
par traiter les deux cas particuliers du ‘-’ (lignes 2175 et 2175), pour lequel on place le code
clavier et le code ASCII dans le tampon du clavier (lignes 2183 et 2184) et du ‘+’ (lignes 2176
à 2178), pour lequel on fait la même chose, mais évidemment avec des valeurs différentes (lignes
2185 à 2187).
Sinon on soutrait 71 (ligne 2179) pour que le premier code soit 0, on cherche le code ASCII
grâce à la table K15 (lignes 2180 et 2181, renvoyant à une partie déjà étudiée). La table K15 est
définie à partir de la ligne 1841 :
1841 ;----- BASE CASE TABLE
E976 1842 K15 LABEL BYTE
E976 43 1843 DB 71,72,73,-1,75,-1,77
E977 48
E978 49
E979 FF
E97A 4B
E97B FF
E97C 4D
E97D FF 1844 DB -1,79,80,81,82,83
E97E 4F
E9FF 5D
E97F 51
E980 52
E981 53
1845
- 8o ) Dans le cas où l’état ‘NumLock’ n’est pas actif mais que l’une des touches
majuscules est enfoncée, on est ramené au cas précédent (lignes 2191 à 2192).
196 CHAPITRE 6. LE CLAVIER
- 10o ) Dans le cas des touches de fonction (lignes 2201 à 2203), il suffit de placer
0 dans AL (ligne 2204) pour indiquer qu’il s’agit d’un code étendu et le code de la touche dans
AH, puisqu’il s’agit du code étendu, ce qui est déjà fait, puis de placer AX dans le tampon du
clavier (ligne 2205).
- 11o) Le dernier cas à traiter est celui des touches minuscules. On détermine le
code ASCII grâce à la table K10 et on place AX dans le tampon du clavier (lignes 2206 et 2207,
les lignes suivantes consistant à placer le tampon dans le clavier).
6.6. ÉVOLUTION DU CLAVIER 197
Mais comme les dimensions de l’ensemble n’ont pas varié, d’autres touches ont dû réduire
leur encombrement : c’est le cas des touches de verrouillage numérique (‘NumLock’) et d’arrêt
de défilement (‘ScrollLock’) qui ne sont pas d’un usage intensif et qui n’ont pas de raison d’être
plus grande que les touches hh Majuscule ii ; le même sort frappe la touche ‘+’ située à droite du
pavé numérique.
Une nouvelle touche apparaı̂t : la touche ‘Sys’, plus tard rebaptisée ‘SysReq’. Elle devait
constituer une sorte de touche de fonction spécialisée dans les appels au système ou aux pro-
grammes résidents, mais elle n’a jamais été exploitée par les concepteurs de logiciels.
Les touches de blocage possèdent maintenant un indicateur LED indiquant leur état.
Clavier étendu.- IBM décida de rompre avec le design de son clavier classique en introduisant le
clavier étendu (advanced keyboard ou enhanced keyboard), conçu à l’origine pour le PC/AT.
Le clavier étendu (figure 6.10) présente des caractéristiques remarquables qui lui ont assuré
une percée rapide :
6.6.2 Câble
Le signal de réinitialisation du clavier (broche 3) permet une réinitialisation du clavier
(sic) avec certaines interfaces.
200 CHAPITRE 6. LE CLAVIER
Les touches correspondantes ont le même code de recherche que sur le PC/XT, bien qu’elles
ne soient pas placées au même endroit. La nouvelle touche ‘Sys Req’ se voit tout naturellement
attribuer le code de recherche 84.
Cas du clavier étendu.- La figure 6.12 montre les codes de recherche associés aux touches du
clavier PC/MF II à 102 touches.
Pour des raisons de compatibilité, le code de recherche des touches correspondantes est le mê-
me. Ceci ne permet pas a priori de distinguer les touches qui ont été dédoublées l’une de l’autre :
elles ont le même code de recherche et donc un programme ne peut pas distinguer si on a appuyé,
par exemple, sur la touche ‘Alt’ gauche ou droite. Les concepteurs du clavier étendu ont résolu
ce problème de la façon suivante : lorsqu’on appuie ou qu’on relâche une touche dédoublée, un
précode est d’abord envoyé, suivi par le code d’appui ou le code de relâchement. Il s’agit de E0h
pour la touche ‘PAUSE’ et de E1h pour toutes les autres nouvelles touches.
Le tableau suivant donne les codes de recherche de combinaisons de touches [IBM-83] :
Et enfin le tableau suivant donne les codes de recherche supplémentaires du clavier étendu
[IBM-83] :