Le fichier bootsect.asm contient le programme du secteur de boot decrit dans les chapitres precedents :
%define CS_ACCES 10011011b %define DS_ACCES 10010011b %define BASE 0x100 ; 0x0100:0x0 = 0x1000 [BITS 16] [ORG 0x0] jmp start %include "../kernel/UTIL.INC" %include "../kernel/GDT.INC" start: mov [bootdrv],dl ; recuparation de l'unite de boot ; initialisation des segments en 0x07C0 mov ax,0x07C0 mov ds,ax mov es,ax mov ax,0x8000 ; stack en 0xFFFF mov ss,ax mov sp, 0xf000 ; affiche un msg mov si,msgDebut call afficher ; charger le noyau xor ax,ax int 0x13 push es mov ax,BASE mov es,ax mov bx,0 mov ah,2 mov al,KSIZE mov ch,0 mov cl,2 mov dh,0 mov dl,[bootdrv] int 0x13 pop es ; ouverture de la porte a20 a20: in al,0x64 ; teste si on peut envoyer une commande test al,2 jnz a20 mov al,0xD1 out 0x64,al jmp .1 ; temporisation .1: in al,0x64 ; teste si on peut envoyer une commande test al,2 jnz .1 mov al,0xDF out 0x60,al a20end: ; initialisation de la gdt ; descInit base(32),limite(20/32),acces(8),flags(4/8),adresse(16) descInit 0,0xFFFFF,CS_ACCES,1101b,gdt_cs descInit 0,0xFFFFF,DS_ACCES,1101b,gdt_ds ; initialisation du pointeur sur la gdt mov ax,gdtend ; calcule la limite de gdt mov bx,gdt sub ax,bx mov word [gdtptr],ax xor eax,eax ; calcule l'adresse lineaire de gdt mov ax,ds mov bx,gdt call calcadr mov dword [gdtptr+2],ecx ; passage en modep cli lgdt [gdtptr] ; charge la gdt mov eax,cr0 or ax,1 mov cr0,eax ; PE mis a 1 (CR0) jmp next next: mov ax,0x10 ; segment de donne mov ds,ax mov fs,ax mov gs,ax mov es,ax mov ss,ax mov esp,0x9F000 jmp dword 0x8:0x1000 end: jmp end msgDebut db "Chargement du kernel",13,10,0 gdt: gdt_null: dw 0,0,0,0 gdt_cs: dw 0,0,0,0 gdt_ds: dw 0,0,0,0 gdtend: gdtptr: dw 0x0000 ; limite dd 0 ; base bootdrv: db 0 ;; NOP jusqu'a 510 times 510-($-$$) db 144 dw 0xAA55 |
Le fichier main.asm correspond au code du noyau. Ce noyau n'est qu'a un stade embryonnaire. Il utilise un modele d'adressage lineaire (flat model). Les interruptions sont gerees (reprogrammation du controleur d'interruption, mise en place de la table des descripteurs d'interruption, etc.). Un mecanisme d'appels systemes est en place. De nombreuses routines d'affichage sont realisees ainsi que le pilote pour le clavier (qwerty) :
%define CS_ACCES 10011011b %define DS_ACCES 10010011b %define SS_ACCES 10010111b %define GDTBASE 0x800 %define IDTBASE 0x0 %define CS_LIM 0xFFFFF ; limite en blocs de 4 ko ! %define DS_LIM 0xFFFFF ; = 4 Go comme limite superieure. %define SS_LIM 0x10 ; = 0x10000 comme limite inferieure. %define STACKPTR 0x1FFFF ; adresse de depart de esp %define MAXAPPELS 100 [BITS 32] [ORG 0x1000] jmp start %include "GDT.INC" %include "aff.asm" %include "pic.asm" %include "irq.asm" start: ; initialisation de la gdt ; descInit base(32),limite(20/32),acces(8),flags(4/8),adresse(16) descInit 0,CS_LIM,CS_ACCES,1101b,gdt_cs descInit 0,DS_LIM,DS_ACCES,1101b,gdt_ds descInit 0,SS_LIM,SS_ACCES,1101b,gdt_ss descInit 0xB8000,4000,DS_ACCES,0101b,gdt_screen ; ram ecran ; initialisation de gdtptr mov ax,gdtend ; calcule la limite de gdt mov bx,gdt sub ax,bx mov word [gdtptr],ax mov eax,GDTBASE ; adresse lineaire de gdt mov dword [gdtptr+2],eax ; initialisation de idtptr mov ax,idtend mov bx,idt sub ax,bx mov word [idtptr],ax mov eax,IDTBASE mov dword [idtptr+2],eax ; recopie de la gdt a son adresse xor ecx,ecx xor esi,esi xor edi,edi mov cx,word [gdtptr] ; charge la limite mov esi,gdt mov edi,GDTBASE rep movsb ; recopie de la idt a son adresse xor ecx,ecx xor esi,esi xor edi,edi mov cx,word [idtptr] mov esi,idt mov edi,IDTBASE rep movsb ; chargement de la idt et de la nouvelle gdt lidt [idtptr] ; charge l'idt lgdt [gdtptr] ; charge la gdt ; initialisation des segments jmp next next: mov ax,0x10 ; segment de donne mov ds,ax mov es,ax mov fs,ax mov gs,ax mov ax,0x18 ; pile mov ss,ax mov esp,STACKPTR ; un petit message call clrscr mov esi,msg00 call print ; initialisation des interruptions cli call init_pic ; fichier pic.asm call init_irq ; fichier irq.asm sti mov esi,msg01 call print ; initialisation des appels systemes gateInit 0x8,syscalls,TRAP_FLAG+PRESENT_F,0,GDTBASE+0x28 ; selecteur,offset,wc,adresse mov esi,msg03 call print ; KERNEL mov eax,2 ; utilisation des appels systemes pour afficher un message mov esi,msg04 int 0x80 end: jmp end ;------------------------------------------------------------------- ;------------------------------------------------------------------- ; ROUTINES APPELS SYSTEMES ; Entree: ; eax -> numero de fonction ; ebx,ecx,edx -> arguments ; esi,edi -> autres arguments ;------------------------------------------------------------------- syscalls: push ebx push ecx push edx call [systab+4*eax] pop ebx pop ecx pop edx iret end_syscalls: systab: dd scrollup dd gotoxy dd print end_systab: ;------------------------------------------------------------------- ; DONNEES ;------------------------------------------------------------------- ;------------------------------------------------------------------- ; table gdt ;------------------------------------------------------------------- gdt: gdt_null: ; 0x0 dw 0,0,0,0 gdt_cs: ; 0x8 dw 0,0,0,0 gdt_ds: ; 0x10 dw 0,0,0,0 gdt_ss: ; 0x18 dw 0,0,0,0 gdt_screen: ; 0x20 dw 0,0,0,0 gdt_call_gate: ; 0x28 dw 0,0,0,0 gdtend: ;------------------------------------------------------------------- ; table idt ;------------------------------------------------------------------- idt: times 256 dw 0,0,0,0 idtend: ;------------------------------------------------------------------- ; pointeur sur gdt ;------------------------------------------------------------------- gdtptr: dw 0x0000 ; limite dd 0 ; base ;------------------------------------------------------------------- ; pointeur sur idt ;------------------------------------------------------------------- idtptr: dw 0x0000 ; limite dd 0 ; base ;------------------------------------------------------------------- ; MESSAGES ;------------------------------------------------------------------- msg00: db 'mode protege',10,0 msg01: db 'interruptions etablies',10,0 msg02: db '.',0 msg03: db 'appels systemes etablis',10,0 msg04: db 'debug : ceci prouve que les appels systemes sont ok',10,0 |
Le fichier UTIL.INC contient des fonctions utiles en vrac :
;--------------------------------------------------------- ; Synopsis: Affiche une chaine de caracteres se terminant par 0x0 ; Entree: ds:si -> pointe sur la chaine a afficher ;--------------------------------------------------------- afficher: push ax push bx .debut: lodsb ; ds:si -> al cmp al,0 ; fin chaine ? jz .fin mov ah,0x0E ; appel au service 0x0e, int 0x10 du bios mov bx,0x07 ; bx -> attribut, al -> caractere ascii int 0x10 jmp .debut .fin: pop bx pop ax ret ;--------------------------------------------------------- ;--------------------------------------------------------- ; Synopsis: conversion de chaine hexa en ascii ; Entree: ; ds:si -> chaine hexa ; cx -> nombre d'octets a convertir ; Sortie: ; es:di -> chaine ascii terminee par '0x0' ;--------------------------------------------------------- hex2a: push ax push bx push dx .debut: xor ax,ax xor bx,bx xor dx,dx lodsb ror ax,4 mov bl,al mov dl,byte [tableau+bx] mov byte [es:di],dl inc di rol ax,4 and al,0x0F mov bl,al mov dl,byte [tableau+bx] mov byte [es:di],dl inc di loop .debut mov byte [es:di],0 pop dx pop bx pop ax ret tableau db '0123456789ABCDEF' ;--------------------------------------------------------- |
Le fichier GDT.INC contient des fonctions permettant d'initialiser les descripteurs de segments et les descripteurs systemes :
;-------------------------------------------------------------------- ; CalcAdr ; Entree: ; ax -> segment ; bx -> offset ; Sortie: ; ecx -> adresse lineaire sur 32 bits ; Modifie: partie haute de ebx ;-------------------------------------------------------------------- calcadr: xor ecx,ecx mov cx,ax shl ecx,4 and ebx,0x0000FFFF add ecx,ebx ret ;-------------------------------------------------------------------- ;-------------------------------------------------------------------- ; descInit ;-------------------------------------------------------------------- %macro descInit 5 ; base(32),limite(20/32),acces(8),flags(4/8),adresse(32) push eax ; base : mov eax,%1 mov word [%5+2],ax shr eax,16 mov byte [%5+4],al shr eax,8 mov byte [%5+7],al ; limite : mov eax,%2 and eax,0x000FFFFF mov word [%5],ax ; ecrit (0..15) shr eax,16 ; place (16..19) sur le nibble inferieur mov byte [%5+6],0 ; initialise flags+lim(16..19) a 0 or [%5+6],al ; ecrit (16..19) ; flags : mov al,%4 and al,0x0F shl al,4 or [%5+6],al ; acces : mov byte [%5+5],%3 pop eax %endmacro ;-------------------------------------------------------------------- %define LDT_FLAG 0x2 ; ldt %define TASK_FLAG 0x5 ; task gate %define TSS_FLAG 0x9 ; TSS %define CALL_FLAG 0xC ; call gate %define INT_FLAG 0xE ; interrupt gate %define TRAP_FLAG 0xF ; trap gate %define PRESENT_F 0x80 ; present flag %define DPL0 0x00 %define DPL1 0x20 %define DPL2 0x40 %define DPL3 0x60 ;-------------------------------------------------------------------- ; intdesc ;-------------------------------------------------------------------- %macro gateInit 5 ; selecteur(16),offset(32),type (8),wc(5/8),adresse(32) push eax ; selecteur : mov word [%5+2],%1 ; offset : mov eax,%2 mov word [%5],ax shr eax,16 mov word [%5+6],ax ; type : mov byte [%5+5],%3 ; wc : mov byte [%5+4],%4 and byte [%5+4],00011111b pop eax %endmacro ;-------------------------------------------------------------------- |
Le fichier aff.asm contient les routines d'affichage (affichage de chaines de caracteres, scrolling, effacage de l'ecran...) :
%define RAMSCREEN 0xB8000 %define SIZESCREEN 0xFA0; = 4000, nombres d'octets d'une page texte %define SCREENLIM 0xFA0 ; Si un octet >= SCREENLIM, il n'est pas dans ; la ram ecran. ;----------------------------------------------------------------- ; Entree: ; 1er arg -> nombre de lignes a scroller (de 0 a 25) ;----------------------------------------------------------------- scrollup: push ebp mov ebp,esp push eax push ebx push ecx push edx push esi push edi push ds push es xor edi,edi ; desination = 0xB8000:0 mov eax,[ebp+8] ; nombre de lignes a scroller ; Decrementation de X cmp byte [ds:X],al ; si X < n jb .azero ; alors X->0 sub byte [ds:X],al ; sinon X->X-n jmp .load .azero: mov byte [ds:X],0 .load: push eax mov ax,0x20 ; gdt_screen mov ds,ax mov es,ax pop eax push eax mov eax,0 push eax call getpos ; calcul l'offset en ram de la ligne a scroller pop eax pop eax mov esi,edx ; esi -> offset en ram ecran a ramener a l'origine. push esi ; valeur qui servira pour le remplissage mov ecx,SIZESCREEN sub ecx,esi ; ecx -> nombre d'octets a recopier push ecx ; valeur qui servira pour le remplissage rep movsb ; transfere esi vers edi pop edi pop ecx .remplissage: ; rempli le bas de l'ecran avec \0 mov byte [edi],0 inc edi dec ecx jnz .remplissage pop es pop ds pop edi pop esi pop edx pop ecx pop ebx pop eax pop ebp ret ;----------------------------------------------------------------- ; Pour afficher une chaine de caracteres ; Entree: ; ds:esi -> chaine terminee par \0 ;----------------------------------------------------------------- print: push ebp mov ebp,esp push eax push ebx push ecx push edx push esi push edi push ds push es xor eax,eax mov al,byte [X] ; position du curseur en argument push eax mov al,byte [Y] push eax call getpos ; retourne dans edx position dans la ram pop eax pop eax mov edi,edx ; edi -> pointe sur offset en ram ecran du curseur mov ax,0x20 mov es,ax .afficher: lodsb cmp al,0 ; teste si fin de chaine jz .fin ; si oui, fin. cmp al,0xa jz .cr_nl jmp .car .cr_nl: mov byte [Y],79 jmp .fin_afficher .car: mov byte [es:edi],al ; sinon, copie d'un caractere... inc edi mov byte al,[ds:XYattr] mov byte [es:edi],al ; ... et de l'attribut. inc edi .fin_afficher: .incrementeXY: add byte [Y],1 ; on incremente Y cmp byte [Y],80 ; si Y < 80 jb .finIncrementeXY ; alors on affiche le caractere suivant mov byte [Y],0 ; sinon, Y->0 et X->X+1 add byte [X],1 ; Note : si X>24, le scrolling mettra X a 24 .finIncrementeXY: .testeLimites: xor eax,eax mov al,byte [X] ; position du curseur en argument push eax mov al,byte [Y] push eax call getpos ; retourne dans edx position dans la ram pop eax pop eax mov edi,edx ; edi -> pointe sur offset en ram ecran du curseur cmp edi,SCREENLIM ; teste si on depasse les limites de l'ecran jb .afficher ; si non, on continue sub edi,160 ; si oui, scrolle d'une ligne ... push byte 1 call scrollup pop eax ; on recupere la variable passe par le push jmp .afficher ; et on continue .fin: pop es pop ds pop edi pop esi pop edx pop ecx pop ebx pop eax pop ebp ret ;----------------------------------------------------------------- ; Entree: ; 1er arg -> x (0 a 24). ; 2e arg -> y (0 a 79). ;----------------------------------------------------------------- gotoxy: push ebp mov ebp,esp push eax mov eax,[ebp+8] ; recupere la valeur de y mov byte [Y],al ; mise a jour de 'curY' mov eax,[ebp+12] ; recupere la valeur de x mov byte [X],al ; mise a jour de 'curX' pop eax pop ebp ret ;----------------------------------------------------------------- ; Entree: ; 1er arg -> x (0 a 24). ; 2e arg -> y (0 a 79). ; Retour: ; edx -> offset a partir du debut de la ram ecran. ;----------------------------------------------------------------- getpos: push ebp mov ebp,esp push ecx push ebx push eax mov ebx,[ebp+8] ; recupere la valeur de y shl ebx,1 ; y*2 mov eax,[ebp+12] ; recupere la valeur de x mov ecx,eax shl eax,7 ; x*128 shl ecx,5 ; x*32 add eax,ecx ; x*128+x*32 = x*160 add eax,ebx ; eax -> x*160+y*2 mov edx,eax pop eax pop ebx pop ecx pop ebp ret ;----------------------------------------------------------------- ; Entree: ; al -> attribut ;----------------------------------------------------------------- color: mov byte [XYattr],al ret ;----------------------------------------------------------------- ;----------------------------------------------------------------- ; Pour afficher une chaine de caracteres ; Entree: ; 1er argument -> caractere a afficher ;----------------------------------------------------------------- putcar: push ebp mov ebp,esp push eax push ebx push ecx push edx push esi push edi push ds push es xor eax,eax mov al,byte [X] ; position du curseur en argument push eax mov al,byte [Y] push eax call getpos ; retourne dans edx position dans la ram pop eax pop eax mov edi,edx ; edi -> pointe sur offset en ram ecran du curseur mov ax,0x20 mov es,ax .afficher: mov byte al,[ebp+8] ; On recupere le caractere dans al cmp al,0xA ; Teste si cr-nl jz .cr_nl jmp .car .cr_nl: ; Retour chariot + new line mov byte [Y],79 ; On place le curseur en fin de ligne, il sera incremente ; par la procedure .incrementeXY jmp .fin_afficher .car: ; Caracter normal a afficher mov byte [es:edi],al ; Copie du caractere... inc edi mov byte al,[ds:XYattr] mov byte [es:edi],al ; ... et de l'attribut. inc edi .fin_afficher: .incrementeXY: add byte [Y],1 ; on incremente Y cmp byte [Y],80 ; si Y < 80 jb .finIncrementeXY ; alors on affiche le caractere suivant mov byte [Y],0 ; sinon, Y->0 et X->X+1 add byte [X],1 ; Note : si X>24, le scrolling mettra X a 24 cmp byte [X],25 jb .finIncrementeXY push byte 1 call scrollup pop eax .finIncrementeXY: .fin: pop es pop ds pop edi pop esi pop edx pop ecx pop ebx pop eax pop ebp ret ;----------------------------------------------------------------- ;----------------------------------------------------------------- ; clrscr ; Synopsis: efface l'ecran ;----------------------------------------------------------------- clrscr: push dword 25 call scrollup pop eax ret ;----------------------------------------------------------------- X: db 10 Y: db 0 XYattr: db 0x07 ;----------------------------------------------------------------- |
Le fichier pic.asm contient la fonction qui programme le controleur d'interruptions pour donner une valeur correcte aux vecteurs d'interruptions materielles et masquer toutes les interruptions excepter celle du clavier :
;------------------------------------------------------------------- ; init_pic ; Synopsys: Initialisation du 8259. ;------------------------------------------------------------------- init_pic: ; Maitre master: mov al,0x11 ; Initialisation de ICW1 out 0x20,al jmp .1 ; temps d'attente .1: mov al,0x20 ; Initialisation de ICW2 out 0x21,al ; vecteur de depart = 32 jmp .2 ; temps d'attente .2: mov al,0x04 ; Initialisation de ICW3 out 0x21,al jmp .3 .3: mov al,0x01 ; Initialisation de ICW4 out 0x21,al jmp .4 .4: mov al,0xFF ; demasquage des interruptions out 0x21,al ; Esclave slave: mov al,0x11 ; Initialisation de ICW1 out 0xA0,al jmp .1 ; temps d'attente .1: mov al,0x70 ; Initialisation de ICW2 out 0xA1,al ; vecteur depart = 96 jmp .2 .2: mov al,0x02 ; Initialisation de ICW3 out 0xA1,al jmp .3 .3: mov al,0x01 ; Initialisation de ICW4 out 0xA1,al jmp .4 .4: mov al,0xFF ; demasquage des interruptions out 0xA1,al ; Masquage des irqs mov al,0xFD ; j'autorise seulement l'irq1 (clavier). out 0x21,al ret ;------------------------------------------------------------------- |
Le fichier irq.asm initialise les differents descripteurs systemes de la table IDT gerant les interruptions. Les appels systemes sont geres a partir d'un descripteur (trap gate) de cette table :
%include "kbd.asm" ;------------------------------------------------------------------- ; init_irq ; Synopsis: fait correspondre un handler a une ISR. ;------------------------------------------------------------------- init_irq: gateInit 0x08,interrupts,INT_FLAG+PRESENT_F,0,IDTBASE ; 0 - division par 0 gateInit 0x08,interrupts,INT_FLAG+PRESENT_F,0,IDTBASE+8*1 ; 1 - step gateInit 0x08,interrupts,INT_FLAG+PRESENT_F,0,IDTBASE+8*2 ; 2 - NMI gateInit 0x08,interrupts,INT_FLAG+PRESENT_F,0,IDTBASE+8*3 ; 3 - breakpoint gateInit 0x08,interrupts,INT_FLAG+PRESENT_F,0,IDTBASE+8*4 ; 4 - overflow gateInit 0x08,interrupts,INT_FLAG+PRESENT_F,0,IDTBASE+8*5 ; 5 - BOUND gateInit 0x08,interrupts,INT_FLAG+PRESENT_F,0,IDTBASE+8*6 ; 6 - opcode invalide gateInit 0x08,interrupts,INT_FLAG+PRESENT_F,0,IDTBASE+8*7 ; 7 - coproc. non valide gateInit 0x08,interrupts,INT_FLAG+PRESENT_F,0,IDTBASE+8*8 ; 8 - double faute gateInit 0x08,interrupts,INT_FLAG+PRESENT_F,0,IDTBASE+8*9 ; 9 - overrun gateInit 0x08,interrupts,INT_FLAG+PRESENT_F,0,IDTBASE+8*10 ;10 - task state segment invalide gateInit 0x08,interrupts,INT_FLAG+PRESENT_F,0,IDTBASE+8*11 ;11 - segment non present gateInit 0x08,interrupts,INT_FLAG+PRESENT_F,0,IDTBASE+8*12 ;12 - stack exception gateInit 0x08,interrupts,INT_FLAG+PRESENT_F,0,IDTBASE+8*13 ;13 - general prot. exception gateInit 0x08,interrupts,INT_FLAG+PRESENT_F,0,IDTBASE+8*14 ;14 - page fault gateInit 0x08,interrupts,INT_FLAG+PRESENT_F,0,IDTBASE+8*15 ;15 - reserve gateInit 0x08,interrupts,INT_FLAG+PRESENT_F,0,IDTBASE+8*16 ;16 - erreur coproc. ; ... gateInit 0x08,irq0,INT_FLAG+PRESENT_F,0,IDTBASE+8*32 ; IRQ0 - timer gateInit 0x08,irq1,INT_FLAG+PRESENT_F,0,IDTBASE+8*33 ; IRQ1 - keyboard gateInit 0x08,irq2,INT_FLAG+PRESENT_F,0,IDTBASE+8*34 ; IRQ2 cascade gateInit 0x08,irq3,INT_FLAG+PRESENT_F,0,IDTBASE+8*35 ; IRQ3 - COM2 or COM4 gateInit 0x08,irq4,INT_FLAG+PRESENT_F,0,IDTBASE+8*36 ; IRQ4 - COM1 or COM3 gateInit 0x08,irq5,INT_FLAG+PRESENT_F,0,IDTBASE+8*37 ; IRQ5 - LPT2 gateInit 0x08,irq6,INT_FLAG+PRESENT_F,0,IDTBASE+8*38 ; IRQ6 - floppy disk gateInit 0x08,irq7,INT_FLAG+PRESENT_F,0,IDTBASE+8*39 ; IRQ7 - LPT1 ; ... gateInit 0x08,irq8,INT_FLAG+PRESENT_F,0,IDTBASE+8*112 ; IRQ8 - real time clock gateInit 0x08,irq9,INT_FLAG+PRESENT_F,0,IDTBASE+8*113 ; IRQ9 - cascade gateInit 0x08,irq10,INT_FLAG+PRESENT_F,0,IDTBASE+8*114 ; IRQ10 - reserve gateInit 0x08,irq11,INT_FLAG+PRESENT_F,0,IDTBASE+8*115 ; IRQ11 - reserve gateInit 0x08,irq12,INT_FLAG+PRESENT_F,0,IDTBASE+8*116 ; IRQ12 - mouse gateInit 0x08,irq13,INT_FLAG+PRESENT_F,0,IDTBASE+8*117 ; IRQ13 - numeric coprocessor gateInit 0x08,irq14,INT_FLAG+PRESENT_F,0,IDTBASE+8*118 ; IRQ14 - fixed disk controller gateInit 0x08,irq15,INT_FLAG+PRESENT_F,0,IDTBASE+8*119 ; IRQ15 - reserve ; ... gateInit 0x08,syscalls,TRAP_FLAG+PRESENT_F,0,IDTBASE+8*128 ; trap numero 0x80 ret ;------------------------------------------------------------------- ;------------------------------------------------------------------- ; Routines interruptions (ISR) ;------------------------------------------------------------------- interrupts: irq0: irq2: irq3: irq4: irq5: irq6: irq7: irq8: irq9: irq10: irq11: irq12: irq13: irq14: irq15: mov al,0x20 out 0x20,al ; EOI envoyee au PIC iret irq1: cli call kbd_interrupt sti iret end_interrupts: ;------------------------------------------------------------------- |
Le fichier kbd.asm contient la routine appelee quand une interruption liee au clavier a lieu. Ce code correspond donc au driver du clavier :
; Make codes %define LSHIFT 0x2A %define RSHIFT 0x36 %define CTRL 0x1D %define ALT 0x38 ; Break codes %define BRK_LSHIFT 0xAA %define BRK_RSHIFT 0xB6 %define BRK_CTRL 0x9D %define BRK_ALT 0xB8 ;----------------------------------------------------------------------------- ; Routine d'interruption du clavier ;----------------------------------------------------------------------------- kbd_interrupt: cli push eax push ebx xor eax,eax .wait4buffer: ; On teste si le buffer de sortie est plein in al,0x64 test byte al,1 jz .wait4buffer ; Tant que le buffer est vide, on attend ; REM : Il faudrait limiter le nb de loop !!! in al,0x60 ; Lecture du scan-code cmp al,0x81 ; On teste si c'est un breakcode jnb .breakcode .makecode: cmp al,LSHIFT jz .shift cmp al,RSHIFT jz .shift cmp al,CTRL jz .ctrl cmp al,0xE0 jz .e0 cmp al,0xE1 jz .e1 jmp .normal .normal: xor ebx,ebx dec al mov byte bl,[keytable+eax*4] push ebx call putcar pop ebx jmp .fin .shift: jmp .fin .ctrl: jmp .fin .e0: .e1: jmp .fin .breakcode: cmp al,BRK_LSHIFT jz .brkshift cmp al,BRK_RSHIFT jz .brkshift cmp al,BRK_CTRL jz .brkctrl jmp .fin .brkshift: jmp .fin .brkctrl: jmp .fin .fin: mov al,0x20 out 0x20,al ; EOI envoyee au PIC pop ebx pop eax sti ret ;----------------------------------------------------------------------------- ; Flags e0flag: db 0 e1flag: db 0 sflag: db 0 ; shift cflag: db 0 ; ctrl aflag: db 0 ; alt ; Mappage des touches ; normal shift ctrl alt touche keytable: db 0x1B, 0x1B, 0x1B, 0x1B ; esc (0x01) db '1', '!', '1', '1' db '2', '@', '2', '2' db '3', '#', '3', '3' db '4', '$', '4', '4' db '5', '%', '5', '5' db '6', '^', '6', '6' db '7', '&', '7', '7' db '8', '*', '8', '8' db '9', '(', '9', '9' db '0', ')', '0', '0' db '-', '_', '-', '-' db '=', '+', '=', '=' db 0x08, 0x08, 0x7F, 0x08 ; backspace db 0x09, 0x09, 0x09, 0x09 ; tab db 'q', 'Q', 'q', 'q' db 'w', 'W', 'w', 'w' db 'e', 'E', 'e', 'e' db 'r', 'R', 'r', 'r' db 't', 'T', 't', 't' db 'y', 'Y', 'y', 'y' db 'u', 'U', 'u', 'u' db 'i', 'I', 'i', 'i' db 'o', 'O', 'o', 'o' db 'p', 'P', 'p', 'p' db '[', '{', '[', '[' db ']', '}', ']', ']' db 0x0A, 0x0A, 0x0A, 0x0A ; enter db 0xFF, 0xFF, 0xFF, 0xFF ; ctrl db 'a', 'A', 'a', 'a' db 's', 'S', 's', 's' db 'd', 'D', 'd', 'd' db 'f', 'F', 'f', 'f' db 'g', 'G', 'g', 'g' db 'h', 'H', 'h', 'h' db 'j', 'J', 'j', 'j' db 'k', 'K', 'k', 'k' db 'l', 'L', 'l', 'l' db ';', ':', ';', ';' db 0x27, 0x22, 0x27, 0x27 ; '" db '`', '~', '`', '`' ; `~ db 0xFF, 0xFF, 0xFF, 0xFF ; Lshift (0x2a) db '\', '|', '\', '\' db 'z', 'Z', 'z', 'z' db 'x', 'X', 'x', 'x' db 'c', 'C', 'c', 'c' db 'v', 'V', 'v', 'v' db 'b', 'B', 'b', 'b' db 'n', 'N', 'n', 'n' db 'm', 'M', 'm', 'm' db 0x2C, 0x3C, 0x2C, 0x2C ;,< db 0x2E, 0x3E, 0x2E, 0x2E ;.> db 0x2F, 0x3F, 0x2F, 0x2F ;/? db 0xFF, 0xFF, 0xFF, 0xFF ; Rshift (0x36) db 0xFF, 0xFF, 0xFF, 0xFF ; (0x37) db 0xFF, 0xFF, 0xFF, 0xFF ; (0x38) db 0xFF, 0xFF, 0xFF, 0xFF ; (0x39) db 0xFF, 0xFF, 0xFF, 0xFF ; (0x3a) db 0xFF, 0xFF, 0xFF, 0xFF ; (0x3b) db 0xFF, 0xFF, 0xFF, 0xFF ; (0x3c) db 0xFF, 0xFF, 0xFF, 0xFF ; (0x3d) db 0xFF, 0xFF, 0xFF, 0xFF ; (0x3e) db 0xFF, 0xFF, 0xFF, 0xFF ; (0x3f) db 0xFF, 0xFF, 0xFF, 0xFF ; (0x40) db 0xFF, 0xFF, 0xFF, 0xFF ; (0x41) db 0xFF, 0xFF, 0xFF, 0xFF ; (0x42) db 0xFF, 0xFF, 0xFF, 0xFF ; (0x43) db 0xFF, 0xFF, 0xFF, 0xFF ; (0x44) db 0xFF, 0xFF, 0xFF, 0xFF ; (0x45) db 0xFF, 0xFF, 0xFF, 0xFF ; (0x46) db 0xFF, 0xFF, 0xFF, 0xFF ; (0x47) db 0xFF, 0xFF, 0xFF, 0xFF ; (0x48) db 0xFF, 0xFF, 0xFF, 0xFF ; (0x49) db 0xFF, 0xFF, 0xFF, 0xFF ; (0x4a) db 0xFF, 0xFF, 0xFF, 0xFF ; (0x4b) db 0xFF, 0xFF, 0xFF, 0xFF ; (0x4c) db 0xFF, 0xFF, 0xFF, 0xFF ; (0x4d) db 0xFF, 0xFF, 0xFF, 0xFF ; (0x4e) db 0xFF, 0xFF, 0xFF, 0xFF ; (0x4f) db 0xFF, 0xFF, 0xFF, 0xFF ; (0x50) db 0xFF, 0xFF, 0xFF, 0xFF ; (0x51) db 0xFF, 0xFF, 0xFF, 0xFF ; (0x52) db 0xFF, 0xFF, 0xFF, 0xFF ; (0x53) db 0xFF, 0xFF, 0xFF, 0xFF ; (0x54) db 0xFF, 0xFF, 0xFF, 0xFF ; (0x55) db 0xFF, 0xFF, 0xFF, 0xFF ; (0x56) db 0xFF, 0xFF, 0xFF, 0xFF ; (0x57) db 0xFF, 0xFF, 0xFF, 0xFF ; (0x58) db 0xFF, 0xFF, 0xFF, 0xFF ; (0x59) db 0xFF, 0xFF, 0xFF, 0xFF ; (0x5a) db 0xFF, 0xFF, 0xFF, 0xFF ; (0x5b) db 0xFF, 0xFF, 0xFF, 0xFF ; (0x5c) db 0xFF, 0xFF, 0xFF, 0xFF ; (0x5d) db 0xFF, 0xFF, 0xFF, 0xFF ; (0x5e) db 0xFF, 0xFF, 0xFF, 0xFF ; (0x5f) db 0xFF, 0xFF, 0xFF, 0xFF ; (0x60) db 0xFF, 0xFF, 0xFF, 0xFF ; (0x50) db 0xFF, 0xFF, 0xFF, 0xFF db 0xFF, 0xFF, 0xFF, 0xFF db 0xFF, 0xFF, 0xFF, 0xFF db 0xFF, 0xFF, 0xFF, 0xFF db 0xFF, 0xFF, 0xFF, 0xFF endkeytable: |