%define INTGATE 0x8E00 %define IDTBASE 0x800 ;addr. physique où doit resider la IDT %define IDTSIZE 0xFF ;nombre max. de descripteurs dans la table %define INTERRUPTION_PIC_MAITRE 0x20 %define INTERRUPTION_PIC_ESCLAVE 0x70 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; Initialisation du PIC ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; init_pic: mov al, 0x11 ; Initialisation de ICW1 out 0x20, al ; maître out 0xA0, al ; esclave mov al, INTERRUPTION_PIC_MAITRE ; Initialisation de ICW2 out 0x21, al ; maître, vecteur de départ = 32 mov al, INTERRUPTION_PIC_ESCLAVE out 0xA1, al ; esclave, vecteur de départ = 96 mov al, 0x04 ; initialisation de ICW3 out 0x21, al mov al, 0x02 ; esclave out 0xA1, al mov al, 0x05 ; initialisation de ICW4 out 0x21, al mov al, 0x01 out 0xA1, al xor al, al ; masquage des interruptions out 0x21, al out 0xA1, al ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; Fin de l'initialisation du PIC ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; Création d'une table des vecteurs d'interruption pointant sur un simple EOI (End Of Interrupt) ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; IDT : Interrupt Descriptor Table ;; ;; Structure : http://fr.wikipedia.org/wiki/Interrupt_Descriptor_Table ;; mot : les 16 bits les plus faibles de l'offset de la fonction (gestionnaire d'interruption ou d'exception) associée à l'interruption ;; mot : le sélecteur du segment de code, donc l'adresse du descripteur de code dans la GDT ;; 1 bit : drapeau IF (sur "1" pour activer le masquage des interruptions masquables) ;; 2 bits : DPL, de 0 à 3 inclus, qui indique le niveau de privilèges requis pour appeler l'interruption (0 est le plus élevé) ;; 1 bit : doit être mis à 0 ;; 4 bits : le type d'interruption (porte d'interruption, de trappe ou de tâche) ;; 8 bits : réservé pour un futur usage (doit être à 0) ;; mot : les 16 bits les plus hauts de l'offset de la fonction associée à l'interruption ;; ;; 7 0 ;;+---+---+---+---+---+---+---+---+ ;;| P | DPL | S | GateType | ;;+---+---+---+---+---+---+---+---+ ;;P 7 Present can be set to 0 for unused interrupts or for Paging. ;;DPL 6,5 Descriptor Privilege Level Gate call protection. Specifies which privilege Level the calling Descriptor minimum should have. So hardware and CPU interrupts can be protected from beeing called out of userspace. ;;S 4 Storage Segment = 0 for interrupt gates. ;;Typ 0..3 Gate Type 0..3 Possible IDT gate types : ;;0b0101 0x5 5 80386 32 bit Task gate ;;0b0110 0x6 6 80286 16-bit interrupt gate ;;0b0111 0x7 7 80286 16-bit trap gate ;;0b1110 0xE 14 80386 32-bit interrupt gate ;;0b1111 0xF 15 80386 32-bit trap gate ;; Pour nous : les bits indiqués seront 00000000(forcément)10001110, à passer en bigendian ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; mov eax, IDTBASE ; Adresse de l'IDT mov ebx, interruptionParDefaut ; On va remplir toute la table avec l'interruption par défaut : bx contient les bits de poids faible mov ecx, IDTSIZE ; Nombre de vecteurs d'interruption call metInterruptionNFois ; On remplace les vecteurs qui nous intéressent par leur vraie adresse de fonction. mov eax, IDTBASE + (INTERRUPTION_PIC_MAITRE * 8) ; L'adresse dans la table est égale à AdresseDeBase + NuméroDeL'interruption * TailleD'unDescripteur. mov ebx, interruptionPICMaitreParDefaut mov ecx, 8 call metInterruptionNFois mov eax, IDTBASE + (INTERRUPTION_PIC_ESCLAVE * 8) ; L'adresse dans la table est égale à AdresseDeBase + NuméroDeL'interruption * TailleD'unDescripteur. mov ebx, interruptionPICEsclaveParDefaut mov ecx, 8 call metInterruptionNFois ; On remplace les vecteurs qui nous intéressent par leur vraie adresse de fonction. mov eax, IDTBASE + 0x21*8;(INTERRUPTION_PIC_MAITRE + 1) * 8 ; Le clavier a l'IRQ1. mov ebx, interruptionClavier mov ecx, 1 call metInterruptionNFois mov eax, IDTBASE + INTERRUPTION_PIC_MAITRE * 8 ; L'IRQ0, un timer. mov ebx, interruptionTimer mov ecx, 1 call metInterruptionNFois lidt [idtptr] ; charge l'idt sti ret ;;Met l'interruption n fois dans l'idt metInterruptionNFois: mov edx, ebx shr edx, 16 mov [descripteurInterruption], bx ;bx contient les bits de poids faible mov [descripteurInterruption + 6], dx; et dx ceux de poids fort mov edi, eax .remplitIDTPIC: mov esi, descripteurInterruption movsd movsd loop .remplitIDTPIC ret interruptionPICMaitreParDefaut: mov al,0x20 ; EOI (End Of Interrupt) out 0x20,al ; qu'on envoie au PIC interruptionParDefaut: iret interruptionPICEsclaveParDefaut: mov al,0x20 ; EOI (End Of Interrupt) out 0xA0,al ; qu'on envoie au PIC iret ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; Gestion des interruptions clavier ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; interruptionClavier: cli push ecx xor eax, eax xor ebx, ebx .attendBuffer: in al, 0x64 ; lire statut test byte al,1 ; bus de sortie prêt ? jz .attendBuffer ; non => boucler in al, 0x60 ;Lit la touche pressée cmp al, 224 ;224 est un code spécial, ça veut dire qu'il y a autre chose derrière, mais pour l'instant on s'en fiche je .attendBuffer ;On va donc lire la suite mov bl, al shr bl, 3; On divise le code par 8 pour savoir dans quel octet il se situe push eax ; On sauve le caractère dans la pile mov cl, 8 div cl ; On le divise par 8 mov cl, ah ; Pour une division par 8 bits, le reste est dans AH pop eax mov edx, 1 shl dl, cl add ebx, touchesActives ;C'est l'adresse de l'octet contenant ce qui nous intéresse cmp al, 128 ;Les touches appuyées ont un code inférieur à 128, les touches relâchées, c'est le même code qu'appuyées plus 128 jb .stockeActif sub al, 128 sub ebx, 128/8 not dl and byte[ebx], dl jmp .suite .stockeActif: or byte[ebx], dl ; Un OU met le bit à 1, un NOT AND le mettra à 0 mov [derniereTouche], al .suite: in al, 0x61 or al, 130 out 0x61, al ;Dit à l'ordi qu'une touche a été pressée and al, 127 out 0x61, al ;Reinitialisation terminée sti pop ecx jmp interruptionPICMaitreParDefaut touchesActives: ;Il me faut 128 bits (à la louche) pour stocker les touches actives, soit, 128/8 = 16 octets, soit 4 doubles mots dd 0, 0, 0, 0 derniereTouche: db 0 traductionASCII: ; db Inconnu,Echap,'1','2','3','4','5','6','7','8','9','0','.','+',Espace arrière,Tab ; db 'a','z','e','r','t','y','u','i','o','p','^','$',Entrée,Ctrl,'q','s' ; db 'd','f','g','h','j','k','l','m','%','²',demiShiftGauche,'*','w','x','c','v' ; db 'b','n',',',';',':','!',demiShiftDroit,ImprEcran,Alt&AltGr,' ',Verr.Maj.,F1,F2,F3,F4,F5 ; db F6,F7,F8,F9,F10,Verr.Num.&Pause,Arretdéfil,home,Haut,PgUp,-,Gauche,5,Droite,+,Fin ; db Bas,PgDw,Inser,Suppr,Inconnu,Inconnu,'<',F11,F12; 89 caractères gérés db 00, 48, 02, 03, 04, 05, 06, 07, 08, 09, 10, 01, 37, 38,110,111 db 11, 36, 15, 28, 30, 35, 31, 19, 25, 26, 39, 40,112,113, 27, 29 db 14, 16, 17, 18, 20, 21, 22, 23, 41, 47,114, 42, 33, 34, 13, 32 db 12, 24, 43, 44, 45, 46,115, 70, 50, 51,116, 52, 49, 53, 54, 55 db 56, 57, 58, 59, 60, 61, 62, 63,117, 65, 64,118, 66,119, 67, 68 db 120, 69,121,122, 00, 00, 71, 72, 73;89 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; Fin gestion interruptions clavier ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; interruptionTimer: push eax push ecx push ebx push es mov bl, [.courant] dec bl or bl, bl jnz .depile mov ax, 8*3 ;En route pour le 3ème segment mov es, ax ;clignotement curseur xor eax, eax mov al, [.prochainCaractere] mov ecx, [curseur] call afficheCaractere mov [curseur], ecx mov bl, [.vitesse] or al, al jnz .plein mov byte [.prochainCaractere], 51 jmp .depile .plein: mov byte [.prochainCaractere], 0 .depile: mov [.courant], bl pop es pop ebx pop ecx pop eax jmp interruptionPICMaitreParDefaut .prochainCaractere: db 0 .vitesse: db 5 .courant: db 5 ;-------------------------------------------------------------------- idtptr: dw IDTSIZE << 3 ; limite dd IDTBASE ; base descripteurInterruption: dw 0, 1 * 8, INTGATE, 0