IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Assembleur Discussion :

Comment détourner l'interruption matérielle clavier (09h) ?


Sujet :

Assembleur

  1. #1
    Membre habitué Avatar de Nico*3-3
    Inscrit en
    Octobre 2004
    Messages
    164
    Détails du profil
    Informations forums :
    Inscription : Octobre 2004
    Messages : 164
    Points : 145
    Points
    145
    Par défaut Comment détourner l'interruption matérielle clavier (09h) ?
    Bonjour à tous !

    Voilà j'ai commencé un petit jeu où il ya besoin du clavier et il faut pouvoir appuyer plusieurs touches à la fois.

    Comme avec l'interruption 16h c'est pas possible, j'ai cherché et j'ai trouvé quelque chose mais c'était pas super bien expliqué et il n'y avait aucun exemple...

    Donc si quelqu'un veut bien me dire comment on fait et me donner un petit exemple, je serai ravi.

    Merci d'avance.

  2. #2
    Membre éclairé
    Profil pro
    Inscrit en
    Juillet 2002
    Messages
    842
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2002
    Messages : 842
    Points : 696
    Points
    696
    Par défaut
    J'vais être gentil, j'vais pas le rapporter à Smortex, mais chut hein, parce que sinon, il va se facher, parce que c'est dans la FAQ : )

    http://asm.developpez.com/faq/?page=...fx86_int_creer

    Il ne vous manque pas grand chose sinon comment coder votre propre INT :

    Pour lire le code de la touche pressé et le mettre dans al.

    C'est une interruption, et parce qu'il faut dire au PIC que vous avez traité l'interruption et qu'il peut donc continuer à traiter les interruption de priorité inférieures ou égales, vous devez écrire en fin d'interruption :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
                    mov al, 20h
                    out 20h, al
    Enfin, il vaut mieux sauvegarder quelque part (dans la pile, pourquoi pas ?)les registres que vous modifiez. L'intteruption peut survenir n'importe quand, et si vous ne sauvegardez pas les registres, l'execution en cours sera faussée ! Imaginez que dans un morceau de code, une boucle, vous incrémentiez cx de 0 à 300, et que quelqu'un, un chat ou un humanoïde quelconque appuie sur une touche du clavier, l'int se déclanche, et si elle modifie cx, la boucle est fichue ! Saleté de chat va !


    Blustuff.

  3. #3
    Membre habitué Avatar de Nico*3-3
    Inscrit en
    Octobre 2004
    Messages
    164
    Détails du profil
    Informations forums :
    Inscription : Octobre 2004
    Messages : 164
    Points : 145
    Points
    145
    Par défaut
    Merci, mais j'ai essayé de l'appliquer et ça me donne un gros bug !
    J'ai dû me tromper quelque part mais je trouve pas où ...

    Voilà le code ( la syntaxe est celle de FASM ) :

    J'ai réservé 128 bytes pour le buffer clavier ( BufferClavier ).
    Et j'ai déclaré un double mot ( Vecteur ) pour pouvoir restaurer le vecteur
    à la fin.

    Il y a plusieurs segments ( dont DATA_SEG )

    J'ai déclaré l'interruption comme suit :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    intclavier09h:
     
                             push           ds di ax
                             mov            ax, DATA_SEG
                             mov            ds, ax
                             in             al, 60h
                             mov            di, ax
                             mov            [BufferClavier+di], 1
                             mov            al, 20h
                             out            20h, al
                             pop            ax di ds
                             iret

    J'ai initialisé le vecteur d'interruption :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    InitintClavier:
     
                             xor            ax, ax
                             mov            es, ax
                             mov            eax, [es:09h*4]
                             mov            [Vecteur], eax
                             mov            word [es:09h*4], intclavier09h
                             mov            [es:09h*4+2], cs
    Avant chaque nouvelle image, j'efface le buffer clavier :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    ClearKeyboard:
     
                             mov            ax, DATA_SEG
                             mov            es, ax
                             mov            cx, 128
                             mov            di, BufferClavier
                             xor            eax, eax
                             rep            stosb
    Après je teste si Echap à été appuyée :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    TestClavier:
     
                             mov            si, BufferClavier
                             cmp            byte [si+1], 1
                             je             Fin
    Et à la fin je restaure le vecteur :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    RestaurerVecteur:
     
                             xor            ax, ax
                             mov            es, ax
                             mov            ax, DATA_SEG
                             mov            ds, ax
     
                             mov            eax, [Vecteur]
     
                             mov            [es:09h*4], eax
     
     Fin:
     
                             mov            ax, 4C00h
                             int            21h
    Le programme est sensé afficher un point au milieu de l'écran et le déplacer au fur et à mesure qu'on appuie sur I, J, K, L.

    Ca marche très bien bien quand j'utilise l'int 16h mais en essayant de détourner l'interruption 09h comme ça, le point s'affiche tout à gauche de l'écran et on ne peut plus rien faire...

    Voilà... Je sais pas du tout où est-ce que je me suis trompé.

    Merci beaucoup à tous ceux où celles qui voudront bien m'aider.

  4. #4
    Membre éclairé
    Profil pro
    Inscrit en
    Juillet 2002
    Messages
    842
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2002
    Messages : 842
    Points : 696
    Points
    696
    Par défaut
    Très rapidement, il me semble voir deux erreurs, mais je ne sais pas si elles sont en relations avec le problème :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    intclavier09h: 
     
                             push           ds di ax 
                             mov            ax, DATA_SEG 
                             mov            ds, ax 
                             [b]in             al, 60h 
                             mov            di, ax[/b]
                             mov            [BufferClavier+di], 1
                             mov            al, 20h 
                             out            20h, al 
                             pop            ax di ds 
                             iret
    ah contient encore la partie haute de DATA_SEG, ce qui n'est pas terrible pour faire une index ^^ utilise

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    in al, 60h
    movzx di, al
    ou

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    xor ax, ax
    in al, 60h
    mov di, ax
    Pour être certain que l'index ne désigne pas n'importe où ^^


    Ensuite :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    ClearKeyboard: 
     
                             mov            ax, DATA_SEG 
                             mov            es, ax 
                             mov            cx, 128 
                             mov            di, BufferClavier 
                             xor            eax, eax 
                             rep            stosb
    Même si ca m'étonnerait qu'il en soit autrement, il faudrait fixer le Direction Flag avec CLD ou STD, au cas où stosb irait en arrière ^^


    Blustuff.

  5. #5
    Membre habitué Avatar de Nico*3-3
    Inscrit en
    Octobre 2004
    Messages
    164
    Détails du profil
    Informations forums :
    Inscription : Octobre 2004
    Messages : 164
    Points : 145
    Points
    145
    Par défaut
    Merci pour ces remarques, mais j'ai corrigé mon code et ça ne marche toujours pas...

    Je me demande si ce ne serait pas à l'initialisation du vecteur que j'ai fait une erreur.

    Enfin je me demande bien ce que ça peut être.

    Merci.

  6. #6
    Membre éclairé
    Profil pro
    Inscrit en
    Juillet 2002
    Messages
    842
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2002
    Messages : 842
    Points : 696
    Points
    696
    Par défaut
    J'ai jamais programmé pour le mode réel, donc je suis mal placé pour t'aider. Mais en attendant que quelqu'un plus doué que moi te vienne en aide, tu peux essayer d'utiliser un débugueur, ou de faire à l'ancienne : par exemple rajoute un code dans l'iterruption qui écrit "L'int 09 a été déclanchée", ou qui donne carréement le code retourné par le port 60h. Essaie, donc, d'insérer quelques repères pour vérifier que l'execution se déroule bien comme tu l'attendais.

  7. #7
    Membre habitué Avatar de Nico*3-3
    Inscrit en
    Octobre 2004
    Messages
    164
    Détails du profil
    Informations forums :
    Inscription : Octobre 2004
    Messages : 164
    Points : 145
    Points
    145
    Par défaut
    Oui merci je vais essayer...

  8. #8
    Membre habitué Avatar de Nico*3-3
    Inscrit en
    Octobre 2004
    Messages
    164
    Détails du profil
    Informations forums :
    Inscription : Octobre 2004
    Messages : 164
    Points : 145
    Points
    145
    Par défaut
    J'ai enfin trouvé !


    J'ai fait plusieurs tests et...

    C'était bien ce tu m'avais dit mais j'avais aussi fait une erreur dans mon code.

    Mais maintenant que ça marche j'ai un autre problème, je ne peux toujours pas lire plusieurs touches en même temps avec la structure de mon programme.

    Parce que je lis le port 60h dans mon interruption et ce port ne me donne qu'une touche, normal. Mais j'ai lu quelque part que la structure du port 60h était la suivante:

    -Les 7 premiers bits représentent le N° de la touche
    -Le bit de poids fort donne l'état ( 1 = Relachée 0 = Appuyée )

    Si j'efface tout le buffer du clavier à chaque image, on ne peut pas prendre en compte plusieurs touches.
    Donc j'ai modifié l'interruption :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    intclavier09h:
     
                             push           di ax dx cx bx
     
                             in             al, 60h
     
                             test           al, 10000000b
                             jne            Relachee
     
                             movzx          di, al
     
                             mov            [BufferClavier+di], 1
                             jmp            next
         Relachee:
     
                             sub            al, 128
                             movzx          di, al
     
                             mov            [BufferClavier+di], 0
         next:
     
                             mov            al, 20h
                             out            20h, al
                             pop            bx cx dx ax di
     
                             iret
    Mais ça marche pas...
    Et je pense que j'ai pas fait d'erreur dans mon code.

    Je crois que c'est ma doc...
    Elle est pas assez complète, ou imprécise.

    Je vais assyer d'étendre mes recherches, mais si quelqu'un
    sais comment on fait, ça me simplifierait la vie...

    Merci d'avance.

  9. #9
    Responsable Pascal, Lazarus et Assembleur


    Avatar de Alcatîz
    Homme Profil pro
    Ressources humaines
    Inscrit en
    Mars 2003
    Messages
    7 963
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 57
    Localisation : Belgique

    Informations professionnelles :
    Activité : Ressources humaines
    Secteur : Service public

    Informations forums :
    Inscription : Mars 2003
    Messages : 7 963
    Points : 59 646
    Points
    59 646
    Billets dans le blog
    2
    Par défaut
    Je pense que ton problème n'est pas lié au fait de vider le buffer du clavier mais plutôt à la manière dont du gardes l'information lue sur le port 60h.

    Tu devrais tenir à jour en permanence une liste des touches pressées et non encore relâchées (par exemple, un bit à 0 ou à 1 dans une variable dont les différents bits correspondent à une touche reconnue par ton programme).

    Exemple : si les touches reconnues par ton programme sont A B C et D, tu peux créer une variable de type byte dont le bit 0 correspond à la touche A, le bit 1 à la touche B et ainsi de suite.
    Si, pendant l'exécution de ton programme, les événements suivants surviennent :
    - Touche A pressée -> Bit 0 à 1
    - Touche C pressée -> Bit 2 à 1
    - Touche A relâchée -> Bit 0 à 0
    ... etc.

    De cette manière, tu pourrais tester si plusieurs touches sont pressées.

    Mais ce n'est qu'une idée. Je ne sais pas s'il est possible d'inclure ce principe dans ton prog.

  10. #10
    Membre habitué Avatar de Nico*3-3
    Inscrit en
    Octobre 2004
    Messages
    164
    Détails du profil
    Informations forums :
    Inscription : Octobre 2004
    Messages : 164
    Points : 145
    Points
    145
    Par défaut
    Bonjour et désolé pour cette absence prolongée, je ne pouvais pas répondre...

    En fait je crois que le problème ne vient pas de mon buffer mais plutôt de la façon dont j'utilise le port 60h.

    Quelqu'un pourrait-il essayer mon code et le modifier pour voir ce que ça donne et me répondre s'il trouve une solution ?

    Merci d'avance.

  11. #11
    Membre éclairé
    Profil pro
    Inscrit en
    Juillet 2002
    Messages
    842
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2002
    Messages : 842
    Points : 696
    Points
    696
    Par défaut
    Ce qui ne marche pas c'est plusieures touches en même temps ? Il faut savoir que si c'est prévu d'un point de vue programmation, il n'est quand même pas possible de presser 24 touches à la fois. Sinon, petite remarque sans interêt : ton code peut se passer de saut

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
     
                             test           al, 10000000b 
                             jne            Relachee 
     
                             movzx          di, al 
     
                             mov            [BufferClavier+di], 1 
                             jmp            next 
         Relachee: 
     
                             sub            al, 128 
                             movzx          di, al 
     
                             mov            [BufferClavier+di], 0 
         next:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
      movzx di, al
      not al                        ; Inversion des bits en particulier du plus fort
      shr al, 7                     ; Décalage logique, il ne reste plus que le bit de poid fort, à la position du bit de poid faible
      and di, 7fh                   ; Supression du bit de poid fort
      mov [BufferClavier+di], al

  12. #12
    Membre habitué
    Avatar de TangiX
    Profil pro
    Inscrit en
    Juin 2003
    Messages
    139
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2003
    Messages : 139
    Points : 168
    Points
    168
    Par défaut
    Citation Envoyé par Blustuff
    Ce qui ne marche pas c'est plusieures touches en même temps ? Il faut savoir que si c'est prévu d'un point de vue programmation, il n'est quand même pas possible de presser 24 touches à la fois.
    tu te fait vieux blustuff, il est posible de presser 24 et meme 51 touches en meme temps puisque le controlleur du clavier envoie un code d'appui (et meme plusieurs pour la repetition) et un code de relachement, il suffit donc d'avoir un tableau dans lequel sont stocké l'etat des touches au lieu d'un buffer.
    par contre on perd l'information d'ordre si le progamme gere mal ce systeme
    don c c bien quand tu fait un jeu avec 4 joueurs sur le clavier mais pour le traitement de texte c pas l'ideal ^^

  13. #13
    Membre éclairé
    Profil pro
    Inscrit en
    Juillet 2002
    Messages
    842
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2002
    Messages : 842
    Points : 696
    Points
    696
    Par défaut
    Ouais, mais ca revient au même ! On ne pourra pas presser 24 touches en même temps dans le test de ce programme.

  14. #14
    Membre habitué Avatar de Nico*3-3
    Inscrit en
    Octobre 2004
    Messages
    164
    Détails du profil
    Informations forums :
    Inscription : Octobre 2004
    Messages : 164
    Points : 145
    Points
    145
    Par défaut
    Cette fois ça marche pour de bon !

    Dans mon programme de test, j'avais fait une boucle pour tester
    les touches et afficher lesquelles étaient appuyéés simultanément.

    Mais la console du DOS n'arrivait pas à suivre le rythme tellement ma boucle écrivait vite les messages.
    Donc quand j'appuyais sur Entrée, il m'écrivait : "Entrée a été appuyé !"
    Mais quand j'appuyais sur une autre touche, il fallait attendre 15 secondes
    pour voir un message s'afficher, et de même lorsqu'on relachait une touche...

    Donc voilà c'était ma faute j'ai fait trop vite mon programme.

    Mais merci beaucoup pour tous ces conseils !

    J'ai corrigé et amélioré mon code et ça marche impécablement.

    Maintenant si quelqu'un a le même problème que moi,
    il peut m'envoyer un MP en me donnant son e-mail pour que je lui
    envoie mon code...

    Salut.

  15. #15
    Membre habitué Avatar de Nico*3-3
    Inscrit en
    Octobre 2004
    Messages
    164
    Détails du profil
    Informations forums :
    Inscription : Octobre 2004
    Messages : 164
    Points : 145
    Points
    145
    Par défaut
    Ooops j'ai failli oublier...

    Si quelqu'un veut la liste des numéros des touches, voici
    un lien :

    http://www.alrj.org/docs/hardware/clavier/clavier.htm

    Et pour préciser mon code est écrit avec FASM.

    Voilà c'est tout.

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Detourner l'interruption clavier 09h
    Par Emelio dans le forum x86 16-bits
    Réponses: 1
    Dernier message: 24/11/2014, 21h09
  2. comment masquer les interruption clavier
    Par clubinfo dans le forum Langage
    Réponses: 3
    Dernier message: 22/06/2008, 04h10
  3. Comment détourner l'interruption d'erreur critique ?
    Par megataraji dans le forum Assembleur
    Réponses: 1
    Dernier message: 14/01/2007, 10h36
  4. Réponses: 3
    Dernier message: 04/02/2004, 18h35
  5. Bouquins d'Assembleur - interruptions matérielles
    Par Stef784ever dans le forum x86 16-bits
    Réponses: 4
    Dernier message: 12/11/2002, 21h23

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo