BITS 32 org 0x06000 %define RAM_VIDEO 0xb8000 %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 ;On va copier les infos VESA du chargeur d'amorçage dans nos données mov esi, 512 + (0x07c0<<4) mov edi, VESASignature mov ecx, 512/4 rep movsd ; mov ax, 8*2 ; mov es, ax ; mov ds, ax xor eax, eax mov esi, 1024 + (0x07c0<<4) mov edi, NbEntreesMemoire movsw xor ecx, ecx mov cx, word[NbEntreesMemoire] mov eax, ecx shl ecx, 1 add ecx, eax shl ecx, 1 rep movsd ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; 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 ; mov edi, chaine ; xor eax, eax ; mov eax, dword[FlatMemory] ; mov ebx, 16 ; mov cl, 1 ; mov ch, 0 ; call nombreVersChaine ; mov esi, chaine ; call afficheChaine ; jmp $ ; mov edi, clavier ; call litChaine mov cx, 8*3 ;En route pour le 3ème segment mov es, cx call nettoyageEcran ; mov dword [couleurPoint], 0x0F0F0F0F ; xor ecx, ecx ; mov cx, [XResolution] ;toutEcran: ; push ecx ; mov ebx, ecx ; dec ebx ; shl ebx, 16 ; xor ecx, ecx ; mov cx, [YResolution] ;ligneVerticale: ; mov eax, ecx ; dec eax ; add eax, ebx ; call metPixel ; loop ligneVerticale ; pop ecx ; loop toutEcran mov dword [couleurPoint], 0xFFFFFFFF mov eax, 0x00100000 mov ebx, 0x001A0000 call afficheLigne mov eax, 0x000C0000 mov ebx, 0x000C000A call afficheLigne mov eax, 0x000E000A mov ebx, 0x000E0000 call afficheLigne mov eax, 0x001A000A mov ebx, 0x0010000A call afficheLigne mov eax, 0x01000100 mov ebx, 0x01800130 call afficheLigne mov ebx, 0x018000D0 call afficheLigne mov ebx, 0x01300180 call afficheLigne mov ebx, 0x01300080 call afficheLigne mov ebx, 0x00800130 call afficheLigne mov ebx, 0x008000D0 call afficheLigne mov ebx, 0x00D00180 call afficheLigne mov ebx, 0x00D00080 call afficheLigne mov cx, 8*2 ;En route pour le 2e segment mov es, cx mov dword [curseur], 0 mov esi, chaine call afficheChaine mov edi, chaine xor eax, eax mov ax, word [NbEntreesMemoire] mov ebx, 10 mov cl, 1 mov ch, 8 call nombreVersChaine mov esi, chaine call afficheChaine mov esi, DonneesMemoire mov dword [curseur], 16 mov cx, word [NbEntreesMemoire] mov ebx, 16 s5: push ecx mov ecx, 6 s1: push ecx lodsd push esi mov edi, chaine mov cl, 1 mov ch, 8 call nombreVersChaine mov esi, chaine call afficheChaine pop esi pop ecx loop s1 ; lodsd ; push esi ; mov edi, chaine ; call nombreVersChaine ; mov esi, chaine ; call afficheChaine ; pop esi add word [curseur], 8 mov word [curseur+2], 0 pop ecx ; add esi, 16 loop s5 mov ecx, 100 add word [curseur], 8 mov word [curseur+2], 0 xor eax, eax afficheAlphabet: call afficheCaractere inc al loop afficheAlphabet add word [curseur], 8 mov word [curseur+2], 0 princ: mov bx, 8*2 ;En route pour le 2ème segment mov es, bx mov edi, chaine call litChaine mov esi, chaine suivant: lodsb or al, al jz fin call afficheCaractere jmp suivant fin: jmp princ;$ ;;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,100,101 db 11, 36, 15, 28, 30, 35, 31, 19, 25, 26, 39, 40,102,103, 27, 29 db 14, 16, 17, 18, 20, 21, 22, 23, 41, 47,104, 42, 33, 34, 13, 32 db 12, 24, 43, 44, 45, 46,105, 70, 50, 51,107, 52, 49, 53, 54, 55 db 56, 57, 58, 59, 60, 61, 62, 63,108, 65, 64,109, 66,110, 67, 68 db 111, 69,112,113, 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 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; Synopsis: Affiche une chaîne de caractères se terminant par NULL ;; ; Entree: SI -> pointe sur la chaîne à afficher ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; afficheChaine: push eax ; push ebx ; push ecx xor eax, eax ; xor ebx, ebx ; mov cx, [curseurX] ; mov al, ch ; shl al, 2 ; add al, ch ; shl ax, 5 ; On vient de faire une multiplication par 160. ; mov bl, cl ; shl bl, 1 ; add ax, bx ; mov bx, ax ; add ebx, RAM_VIDEO .caractereSuivant: lodsb ; ds:esi -> al or al, al ; fin chaine ? jz .fin ; cmp cl, 80 ; Le curseur est en fin de chaîne ; jne .continuer ; xor cl, cl ; inc ch ;.continuer: cmp al, 102 jne .ligneOK add dword [curseur], 8 mov dword [curseur + 2], 0 ; mov al, cl ; shl al, 1 ; sub ebx, eax ; mov cl, 0 ; inc ch ; add ebx, 160 jmp .caractereSuivant .ligneOK: ; cmp ch, 25 ; jb .scrollOK ; push esi ; mov esi, RAM_VIDEO + 160;On décale tout d'une ligne ; mov edi, RAM_VIDEO ; push ecx ; mov ecx, 160*24/4 ; rep movsd ; mov ecx, 40;On vide la dernière ligne ; push eax ; xor eax, eax ; rep stosd ; pop eax ; pop ecx ; pop esi ; dec ch ; sub ebx, 160 ; jmp .ligneOK call afficheCaractere ;.scrollOK: ; mov byte [ebx], al ; inc ebx ; mov byte [ebx], 0x07 ; inc ebx ; inc cl jmp .caractereSuivant .fin: ; mov [curseurX], cx; Sauvegarde de la position du curseur ; pop ecx ; pop ebx pop eax ret ;curseurX: ; db 0 ;curseurY: ; db 0 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; nombreVersChaine ;; ;;------------------------------------------------------------------;; ;; Ecrit dans la chaîne pointée par EDI le nombre contenu dans EAX ;; ;; si CL est à un, on écrit un caractère terminal ;; ;; CH contient le nombre minimal de caractères à utiliser ;; ;; EBX contient la base ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; nombreVersChaine: push edx push ecx xor cl, cl .stocke_digit: xor edx, edx div ebx push edx ; Sauve le reste dans la pile inc cl or eax, eax ; Si le quotient n'est pas nul jne .stocke_digit ; on recommence ;Les digits sont stockés dans la pile .ajout_zero: cmp ch, cl jbe .clearCH push 0;51-74+10 ; Nombre magique permettant de remplir avec des espaces inc cl jmp .ajout_zero .clearCH: xor ch, ch ;Affichage du chiffre : On en affiche au moins un : zéro .affiche_digit: pop eax ; cmp al, 10 ; jae .dixPlus add al, 1 stosb ; met AL dans l'octet pointé par EDI et incrémente EDI ; jmp .boucle_digit ;.dixPlus: ; Pour les bases à plus de 10 chiffres, on utilise l'alphabet ; add al, 74 - 10 ; stosb ; jmp .boucle_digit ;.boucle_digit: loop .affiche_digit pop ecx ; on récupère le paramètre cx test cl, 0b1 ; s'il est à 1, on écrit un caractère terminal jz .depile mov byte [edi], 0 .depile: pop edx ret ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; Fin nombreVersChaine ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; litChaine ;; ;;------------------------------------------------------------------;; ;; Ecrit dans la chaîne pointée par EDI les caractères écrits au ;; ;; clavier, jusqu'à un retour chariot. ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; litChaine: push eax push ebx mov byte [derniereTouche], 0 .attend_clavier: xor eax, eax cmp byte [derniereTouche], 0 jz .attend_clavier mov al, [derniereTouche] mov byte [derniereTouche], 0 mov ebx, traductionASCII add ebx, eax mov al, [ebx] cmp al, 100 ;Traitement de l'espace arrière jne .testTab dec edi mov al, 51 call afficheCaractere sub dword [curseur], 0x100000 jmp .attend_clavier .testTab: cmp al, 101 ;Traitement de la tabulation avant jne .testEntree dec edi mov eax, (51<<24)+(51<<16)+(51<<8)+51 stosd add word [curseur+2], 3 .testEntree: cmp al, 102 je .fin_attend_clavier test byte[touchesActives + 5], 0b100 ;On teste le shift gauche enfoncé jnz .shift test byte[touchesActives + 6], 0b1000000 ;On teste le shift droit enfoncé jz .RAS .shift: cmp al, 104 ;On ne stocke pas un Shift gauche comme touche je .attend_clavier cmp al, 105 ;On ne stocke pas un Shift droit comme touche je .attend_clavier add al, 73 .RAS: stosb call afficheCaractere jmp .attend_clavier .fin_attend_clavier: mov al, 0 stosb mov al, 51 call afficheCaractere add word [curseur], 7 mov word [curseur+2], 0 dec edi pop ebx pop eax ret ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; Fin litChaine ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; nettoyageEcran ;; ;;------------------------------------------------------------------;; ;; Colorie tout l'écran avec la couleur stockée dans couleurDefaut. ;; ;; ES doit contenir le descripteur de segment de l'écran. ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; nettoyageEcran: push edi push eax push ecx xor eax, eax xor ecx, ecx xor edi, edi mov cx, [YResolution] mov ax, [XResolution] mul ecx ; Nombre de points total mov ecx, eax mov eax, [couleurDefaut] rep stosd pop ecx pop eax pop edi ret ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; Fin nettoyageEcran ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; metPixel ;; ;;------------------------------------------------------------------;; ;; Colorie le pixel dont la position est dans EAX (mot haut : X, ;; ;; mot bas : Y) avec la couleur contenue dans couleurPoint ;; ;; ES doit contenir le descripteur de segment de l'écran. ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; metPixel: push edi push ecx push eax push ebx push edx mov ebx, eax and eax, 0xFFFF shr ebx, 16 xor ecx, ecx mov cx, [XResolution] mul ecx ; On fait une multiplication 32 bits à partir de valeurs de 16 bits. add eax, ebx shl eax, 2 mov edi, eax mov eax, [couleurPoint] stosd .retour: pop edx pop ebx pop eax pop ecx pop edi ret ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; Fin metPixel ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; afficheLigne ;; ;;------------------------------------------------------------------;; ;; Dessine un segment de droite entre le point stocké dans EAX et ;; ;; celui stocké dans EBX (mot haut : X, mot bas : Y) avec la ;; ;; couleur contenue dans couleurPoint ;; ;; ES doit contenir le descripteur de segment de l'écran. ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; Y2: dd 0 afficheLigne: push esi push eax push ebx push ecx push edx push edi cmp eax, ebx ;On travaille dans le sens de abscisses positives jbe .ordreOK xchg eax, ebx ;On inverse si ce n'est pas le cas .ordreOK: mov [Y2], ebx ;On stocke le point d'arrivée sub ebx, eax ;On calcule les longueur à parcourir en X et Y mov cx, bx ;deltaY shr ebx, 16 ;deltaX or bx, bx ;Si deltaX est nul, on sera sur une ligne verticale jz .ligneVerticale or cx, cx ;Si deltaY est nul, on sera sur une ligne horizontale jnz .test_deltaY mov cx, bx ;CX contient le nombre de pixels à afficher mov ebx, 0x10000;Incrément de 1 pixel vers la droite jmp .avance_H_V .ligneVerticale: mov ebx, 0x00001;Incrément de 1 pixel vers le bas .avance_H_V: call metPixel ;Affichage du pixel add eax, ebx ;Incrément loop .avance_H_V .fin_afficheLigne: call metPixel ;Affichage du dernier pixel pop edi pop edx pop ecx pop ebx pop eax pop esi ret .test_deltaY: push 0x10000 ;Incrément de 1 pixel vers la droite push 1 ;Incrément de 1 pixel vers le bas jns .suite ;Si deltaY est positif, on est standard neg cx ;Sinon, on l'oppose, ainsi que l'incrément en Y neg dword[esp] .suite: cmp bx, cx ;Si deltaY>deltaX jae .principal xchg bx, cx ;On échange deltaY et deltaX mov edx, [esp + 4] ;Ainsi que les incréments xchg edx, [esp] mov [esp + 4], edx .principal: ;Et on continue normalement mov dx, bx ;DX contient l'écart .boucle: call metPixel sub dx, cx ;On enlève deltaY cmp dx, cx ;Si on est inférieur ou égal à deltaY ja .affichage add eax, [esp] ;On applique l'incrément en Y add dx, bx ;On ajoute deltaX à l'écart .affichage: add eax, [esp + 4] ;On applique l'incrément en X cmp eax, [Y2] ;Sommes-nous arrivés ? jb .boucle pop edx ;On s'en va proprement pop edx jmp .fin_afficheLigne ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; Fin afficheLigne ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; afficheCaractere ;; ;;------------------------------------------------------------------;; ;; Dessine un caractère au point stocké dans EAX (mot haut : X, ;; ;; mot bas : Y) avec la couleur contenue dans couleurPoint. ;; ;; ES doit contenir le descripteur de segment de l'écran. ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; afficheCaractere: push es push edx push esi push edi push eax push ebx push ecx mov ecx, 7 ;7 lignes par caractère mul ecx mov esi, Alphabet ; adresse de la lettre add esi, eax ; si contient l'adresse de la lettre mov eax, [curseur] mov bx, 8*3 ;En route pour le 2ème segment mov es, bx mov ebx, eax ;EBX stocke le pixel courant and eax, 0xFFFF shr ebx, 16 ; xor ecx, ecx mov cx, [XResolution] mul ecx ; On fait une multiplication 32 bits à partir de valeurs de 16 bits. add eax, ebx shl eax, 2 mov edi, eax mov ecx, 7 .colonne: push ecx mov dl, 0b10000000 mov ecx, 8; On affiche 8 colonnes lodsb mov bl, al .ligne: test bl, dl jnz .point mov eax, [couleurDefaut] jz .suite .point: mov eax, [couleurPoint] .suite: stosd shr dl, 1 loop .ligne pop ecx xor eax, eax mov ax, [XResolution] shl eax, 2 add edi, eax sub edi, 32 loop .colonne add dword [curseur], 0x80000 pop ecx pop ebx pop eax pop edi pop esi pop edx pop es ret ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; Fin afficheCaractere ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;-------------------------------------------------------------------- idtptr: dw IDTSIZE << 3 ; limite dd IDTBASE ; base descripteurInterruption: dw 0, 1 * 8, INTGATE, 0 %include "alphabet.asm" chaine: db 83,51,11,19,51,19,13,19,51,31,24,15,51,29,31,26,15,28,12,15,51,16,25,24,13,30,19,25,24,51,14,51,11,16,16,19,13,18,11,17,15,51,14,15,51,30,15,34,30,15,51,27,31,19,51,102,0 ;"J'ai ici une superbe fonction d'affichage de texte qui ne saurait planter sur un malheureux saut ", 13, "de ligne", 13, 0 clavier: db "12345678 ", 0 ;mode_souhaite: dw 0x0013 ;maxResol: dw 0 couleurDefaut: db 0x00, 0x1F, 0x2F, 0x2F; ARBG couleurPoint: db 0x00, 0x00, 0x7F, 0x00; BGRA ;octetsParPixel: db 4 ;bloc_courant: db 0 curseur: dw 0 ;Informations du pilote VESA VESASignature: times 4 db 0; 'VESA', signature de 4 octets VESAVersion: dw 0; numéro de version de VBE OEMStringPtr: dd 0; Pointeur vers le nom de l'OEM Capabilities: dd 0; Possibilités de la carte graphique VideoModePtr: dd 0; Pointeur vers les modes accessibles TotalMemory: dw 0; Nombre de blocs mémoire de 64ko reserved: times 236 db 0; Complément à 256 octets, taille du bloc ;Informations d'un mode vidéo ModeAttributes: dw 0; Attributs du mode WinAAttributes: db 0; Attibuts de la fenêtre A WinBAttributes: db 0; Attibuts de la fenêtre B WinGranularity: dw 0; Granularité de la fenêtre en ko WinSize: dw 0; Taille de la fenêtre en ko WinASegment: dw 0; Segment de la fenêtre A WinBSegment: dw 0; Segment de la fenêtre B WinFuncPtr: dd 0; Pointeur vers la fonction "de fenêtrage" BytesPerScanLine: dw 0; Octets par "scanline" XResolution: dw 0; Résolution horizontale YResolution: dw 0; Résolution vertical XCharSize: db 0; Largeur d'un caractère YCharSize: db 0; Hauteur d'un caractère NumberOfPlanes: db 0; Nombre de plans mémoire BitsPerPixel: db 0; Bits par pixel NumberOfBanks: db 0; Nombre de banques de style CGA MemoryModel: db 0; Type de modèle mémoire BankSize: db 0; Taille des banques de style CGA NumberOfImagePages: db 0; Nombre de pages image res1: db 0; Reservé RedMaskSize: db 0; Taille du masque rouge en couleur directe RedFieldPosition: db 0; Position du bit faible du masque rouge GreenMaskSize: db 0; Taille du masque vert en couleur directe GreenFieldPosition: db 0; Position du bit faible du masque vert BlueMaskSize: db 0; Taille du masque bleu en couleur directe BlueFieldPosition: db 0; Position du bit faible du masque bleu RsvdMaskSize: db 0; Taille du masque réservé en couleur directe RsvdFieldPosition: db 0; Position du bit faible du masque réservé DirectColorModeInfo: db 0; Attributs du mode de couleur directe FlatMemory: dd 0 res2: times 212 db 0; Complément à 256 octets, taille du bloc NbEntreesMemoire: dw 0 DonneesMemoire: dw 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF dw 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF dw 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF dw 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF dw 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF times 4*1024-($-$$) db 0