org 0x0000 ; Adresse de début .COM jmp start %include "affichageTexte.asm" start: ;On initialise Data Segment et Extra Segment à Code Segment call initialise_segments mov si, hello; met l'adresse de la chaîne à afficher dans le registre SI call affiche_chaine mov ax, 0x4F00 ; demande infos sur le pilote VESA VBE mov di, VESASignature int 10h cmp ax, 0x4F ; Si AL <> 0x4F, on n'a pas de VESA, donc fin. Si AH <> O, erreur, donc fin. jne fin mov si, OEMStringPtr ; pointeur vers le nom de l'OEM stocké offset:segment lodsw; on charge l'adresse d'offset dans ax mov bx, ax ; BX contient l'adresse d'offset lodsw ; on charge l'adresse de segment dans ax mov si, bx ; SI pointe sur le nom de l'OEM push ds ; on sauvegarde DS mov ds, ax ; ds contient l'adresse de segment du nom de l'OEM call affiche_chaine pop ds ; on restaure DS mov cx , 18 lignes_vides: mov si, retour_chariot call affiche_chaine loop lignes_vides mov si, VideoModePtr ; pointeur vers la liste des modes supportés lodsw ; on charge l'adresse d'offset dans ax mov cx, ax ; cx contient l'adresse d'offset lodsw ; on charge l'adresse de segment dans ax mov si, cx ; si pointe sur le premier mode supporté mov dx, ax ; dx contient l'adresse de segment lit_mode_suivant: push ds mov ds, dx ; ds contient l'adresse de segment de la liste des modes lodsw ;charge dans ax le mode pop ds cmp ax, 0xFFFF ; Fin de la liste je arret_modes mov cx, ax mov ax, 0x4F01 ; demande infos sur le mode VESA mov di, ModeAttributes int 0x10 cmp ax, 0x4F ; Si AL <> 0x4F, la fonction n'est pas supportée, on se contentera du VGA. Si AH <> O, erreur, pareil. jne lit_mode_suivant test word [ModeAttributes], 0xF jz lit_mode_suivant ;On ecrit les modes mov di, hello ; on écrit dans hello mov ax, cx push cx mov ch, 3 mov bl, 16 call nombre_vers_chaine mov al, ':' stosb mov ch, 4 mov bl, 10 mov ax, [XResolution] call nombre_vers_chaine mov ax, ('*' << 8) + ' ' stosw mov al, ' ' stosb mov ax, [YResolution] call nombre_vers_chaine mov ax, ' ' stosb mov ch, 2 mov al, [BitsPerPixel] call nombre_vers_chaine mov al, ' ' stosb mov ax, ';' ; on met 2 caractères d'un coup après la chaîne : un '\n' et le zéro terminal. stosw ; les caractères sont dépilés, c'est à dire qu'il faut placer le premier dans la zone basse pop cx push si ;sauve si sur la pile mov si, hello call affiche_chaine pop si ; on récupère si push dx mov ax, [XResolution] shr ax, 5 push ax mov ax, [YResolution] shr ax, 3 push ax mov al, [BitsPerPixel] xor ah, ah shr ax, 3 pop bx mul bx pop bx mul bx pop dx cmp ax, [maxResol] jb lit_mode_suivant mov [maxResol], ax mov [mode_souhaite], cx jmp lit_mode_suivant arret_modes: mov cx, [mode_souhaite] ; On s'enquiert du mode souhaité mov ax, 0x4F01 ; demande infos sur le mode VESA mov di, ModeAttributes int 0x10 mov di, hello ; on écrit dans hello mov ax, cx push cx mov ch, 3 mov bl, 16 call nombre_vers_chaine mov al, ':' stosb mov ch, 4 mov bl, 10 mov ax, [XResolution] call nombre_vers_chaine mov ax, ('*' << 8) + ' ' stosw mov al, ' ' stosb mov ax, [YResolution] call nombre_vers_chaine mov ax, ' ' stosb mov ch, 2 mov al, [BitsPerPixel] call nombre_vers_chaine mov ax, 13 ; on met 2 caractères d'un coup après la chaîne : un '\n' et le zéro terminal. stosw ; les caractères sont dépilés, c'est à dire qu'il faut placer le premier dans la zone basse pop cx mov si, hello call affiche_chaine mov al, [BitsPerPixel] shr al, 3 mov byte [octetsParPixel], al mov ax, [WinASegment] or ax, ax ; on teste l'adresse du segment de la fenêtre. Si elle est nulle, on passe en mode 0x13 jnz adresse_OK adresse_mode_13h: mov word [mode_souhaite], 0x0013 ; infos du mode 0x13, le mode VGA mov word [WinASegment], 0xA000 mov word [YResolution], 200 mov word [XResolution], 320 mov byte [octetsParPixel], 1 adresse_OK: mov di, hello ; met l'adresse de la chaîne à lire dans le registre SI call lit_chaine ; On attend l'utilisateur pour nettoyer l'écran mov ax, 0x4F02 mov bx, [mode_souhaite] int 0x10 ; Changement de mode vidéo call nettoyage_ecran mov ax, 30 ; Coordonnée Y mov bx, 121 ; Coordonnée X call affiche_point mov ax, 10 ; Coordonnée Y mov bx, 10 ; Coordonnée X call affiche_point mov bx, 160 ; Coordonnée X mov ax, 100 ; Coordonnée Y call affiche_point mov bx, 319 ; Coordonnée X mov ax, 199 ; Coordonnée Y call affiche_point mov bx, 639 ; Coordonnée X mov ax, 399 ; Coordonnée Y call affiche_point mov bx, 639 ; Coordonnée X mov ax, 479 ; Coordonnée Y call affiche_point mov bx, 799 ; Coordonnée X mov ax, 599 ; Coordonnée Y call affiche_point mov bx, 1279 ; Coordonnée X mov ax, 1023 ; Coordonnée Y call affiche_point push 16 push 0 push 26 push 0 call affiche_ligne add sp, 8 push 12 push 0 push 12 push 10 call affiche_ligne add sp, 8 push 14 push 10 push 14 push 0 call affiche_ligne add sp, 8 push 16 push 10 push 26 push 10 call affiche_ligne add sp, 8 push 120;test octant6 push 30 push 110 push 10 call affiche_ligne add sp, 4 push 100;test octant5 push 20 call affiche_ligne add sp, 4 push 110;test octant3 push 50 call affiche_ligne add sp, 4 push 100; test octant 4 push 40 call affiche_ligne add sp, 4 push 130;test octant 7 push 10 call affiche_ligne add sp, 4 push 140; test octant 8 push 20 call affiche_ligne add sp, 4 push 140; test octant 1 push 40 call affiche_ligne add sp, 4 push 130; test octant 2 push 50 call affiche_ligne add sp, 8 push 10 push 10 push 310 push 190 call affiche_ligne add sp, 8 mov cx, 27 mov bx, 8*27 mov ax, 50 afficheAlphabet: dec cx call affiche_caractere inc cx sub bx, 8 loop afficheAlphabet fin: jmp $ lit_chaine: push ax push cx push dx mov ah, 0x03 int 0x10; appel de l'interruption BIOS qui donne la position du curseur, stockée dans dx mov cx, 1 attend_clavier: mov ah, 0x01;on teste le buffer clavier int 0x16 jz attend_clavier ;al contient le code ASCII du caractère xor ah, ah; on lit le buffer clavier int 0x16 stosb cmp al, 13 je fin_attend_clavier ;al contient le code ASCII du caractère mov ah, 0x0A;on affiche le caractère courant cx fois int 0x10 inc dl; on passe à la colonne suivante pour la position du curseur mov ah, 0x02;on positionne le curseur int 0x10 jmp attend_clavier fin_attend_clavier: inc dh; on passe à la ligne suivante pour la position du curseur xor dl, dl mov ah, 0x02;on positionne le curseur int 0x10 mov byte [di], 0;on met le caractère terminal dans si pop dx pop cx pop ax ret ;fin de lit_chaine ;fonction affiche_point : on est déjà dans un mode graphique ;BX : Coordonnée X du point ;AX : Coordonnée Y du point affiche_point: push bx ; On sauve les registres qu'on va manipuler push cx push es push di push dx push ax mov cx, word [BytesPerScanLine] mul cx mov di, ax push dx mov ax, bx xor ch, ch mov cl, byte [octetsParPixel] mul cx add di, ax pop dx .change_fenetre: mov ax, 0x4F05 xor bh, bh xor bl, bl int 0x10 ; Changement de fenêtre mov es, [WinASegment] ; On va dans la mémoire vidéo mov bx, couleurPoint .couleur: inc bx mov al, byte [bx] stosb loop .couleur pop ax ; On restaure les registres manipulés pop dx pop di pop es pop cx pop bx ret ;fin de affiche_point ;fonction affiche_ligne : on est déjà dans un mode graphique affiche_ligne: jmp depart_affiche_ligne Y2: dw 0 X2: dw 0 Y1: dw 0 X1: dw 0 deltaX: dw 0 deltaY: dw 0 incX: dw 0 incY: dw 0 e: dw 0 depart_affiche_ligne: push si push ax push bx push cx push dx push di push es mov ax, sp mov si, ax add si, 16 ; SI pointe sur Y2 mov di, Y2 mov ax, ds mov es, ax mov ax, ss mov ds, ax mov cx, 4 rep movsw mov ax, es mov ds, ax mov ax, [X2] mov bx, [X1] sub ax, bx mov [deltaX], ax mov cx, [Y2] mov bx, [Y1] sub cx, bx mov [deltaY], cx or ax, ax ; test deltaX jnz test_deltaX_positif or cx, cx ; test deltaY jnz test_deltaY_deltaX_nul fin_affiche_ligne: mov bx, [X2] mov ax, [Y2] call affiche_point ; mov bx, [X1] ; mov ax, [Y1] ; call affiche_point pop es pop di pop dx pop cx pop bx pop ax pop si ret deltaX_positif: or cx, cx jnz test_deltaY_deltaX_positif ;vecteur horizontal vers la droite mov cx, [deltaX] mov word [incX], 1 mov word [incY], 0 jmp ligne_H_V test_deltaY_deltaX_nul: ;cx contient deltaY mov word [incY], 1 mov word [incX], 0 cmp cx, 0 jns ligne_H_V neg cx mov word [incY], -1 ligne_H_V: mov bx, [X1] mov ax, [Y1] avance_H_V: call affiche_point add bx, [incX] add ax, [incY] loop avance_H_V jmp fin_affiche_ligne test_deltaX_positif: cmp ax, 0 jns deltaX_positif or cx, cx ; CX contient DeltaY jnz test_deltaY_deltaX_negatif ;vecteur horizontal vers la gauche mov cx, [deltaX] neg cx mov word [incX], -1 mov word [incY], 0 jmp ligne_H_V charge_registres: shl cx, 1 shl ax, 1 mov [deltaY], cx mov [deltaX], ax mov bx, [X1] mov ax, [Y1] ret charge_e_deltaX_et_cmp_X2: mov [e], ax call charge_registres mov cx, [X2] ret charge_e_deltaY_et_cmp_Y2: mov [e], cx call charge_registres mov cx, [Y2] ret affiche_et_charge_eY: call affiche_point add ax, [incY] mov dx, [e] ret affiche_et_charge_eX: call affiche_point add bx, [incX] mov dx, [e] ret octants1_et_4: call charge_e_deltaX_et_cmp_X2 depart_boucle1: call affiche_et_charge_eX cmp bx, cx je fin_affiche_ligne sub dx, [deltaY] cmp dx, 0 jns X_pret1 add ax, [incY] add dx, [deltaX] X_pret1: mov [e], dx jmp depart_boucle1 deltaY_positif_deltaX_negatif: neg ax deltaY_positif_deltaX_positif: mov word [incY], 1 ;deltaY > 0, deltaX > 0 cmp ax, cx jae octants1_et_4 neg ax call charge_e_deltaY_et_cmp_Y2 depart_boucle2_et_3: call affiche_et_charge_eY cmp ax, cx je fin_affiche_ligne add dx, [deltaX] cmp dx, 0 jns X_pret2_et_3 add bx, [incX] add dx, [deltaY] X_pret2_et_3: mov [e], dx jmp depart_boucle2_et_3 octant5: call charge_e_deltaX_et_cmp_X2 depart_boucle5: call affiche_et_charge_eX cmp bx, cx je fin_affiche_ligne sub dx, [deltaY] cmp dx, 0 js X_pret5 add ax, [incY] add dx, [deltaX] X_pret5: mov [e], dx jmp depart_boucle5 octant8: neg cx call charge_e_deltaX_et_cmp_X2 depart_boucle8: call affiche_et_charge_eX cmp bx, cx je fin_affiche_ligne add dx, [deltaY] cmp dx, 0 jns X_pret8 add ax, [incY] add dx, [deltaX] X_pret8: mov [e], dx jmp depart_boucle8 test_deltaY_deltaX_positif: mov word [incX], 1 cmp cx, 0 jns deltaY_positif_deltaX_positif ;deltaY < 0, deltaX > 0 mov word [incY], -1 neg cx cmp ax, cx jae octant8 neg cx jmp octants6_et_7 test_deltaY_deltaX_negatif: mov word [incX], -1 cmp cx, 0 ; cx contient deltaY jns deltaY_positif_deltaX_negatif ;deltaY < 0, deltaX < 0 mov word [incY], -1 cmp ax, cx ; ax contient deltaX jbe octant5 neg ax octants6_et_7: call charge_e_deltaY_et_cmp_Y2 depart_boucle6_et_7: call affiche_et_charge_eY cmp ax, cx je fin_affiche_ligne add dx, [deltaX] cmp dx, 0 js X_pret6_et_7 add bx, [incX] add dx, [deltaY] X_pret6_et_7: mov [e], dx jmp depart_boucle6_et_7 ;AFFICHE_LIGNE ENDP nettoyage_ecran: push di push es push ax push bx push cx push dx mov es, [WinASegment]; On lit l'adresse de départ de la mémoire vidéo mov cx, [YResolution] mov ax, [XResolution] mul cx ; Nombre de points total mov ax, dx mov cl, [octetsParPixel] mul cl mov cx, ax xor dx, dx xor bh, bh xor bl, bl boucle_fenetres: push cx mov ax, 0x4F05 int 0x10 ; Changement de fenêtre mov cx, [WinSize] shl cx, 9 ;Passage de ko en mots. xor di, di .point: push cx push bx mov cl, [octetsParPixel] xor ch, ch mov bx, couleur_defaut .couleur: inc bx mov al, byte [bx] stosb loop .couleur pop bx pop cx loop .point inc dx pop cx loop boucle_fenetres .depile: xor dx, dx mov [bloc_courant], dl mov ax, 0x4F05 int 0x10 ; Changement de fenêtre pop dx pop cx pop bx pop ax pop es pop di ret ;Fin nettoyage_ecran affiche_caractere: push bx push dx push si push cx push ax push ax mov ax, cx mov cx, 6 mul cx mov si, Alphabet; adresse de la lettre add si, ax; si contient l'adresse de la lettre .colonne: pop ax push cx mov dl, 0b10000000 mov cx, 8; On affiche 8 colonnes .ligne: push ax mov al, [si]; On charge l'octet à afficher test al, dl jz .suite pop ax call affiche_point push ax .suite: shr dl, 1 inc bx pop ax loop .ligne pop cx inc ax; passage à la ligne suivante sub bx, 8 push ax inc si loop .colonne pop ax pop ax pop cx pop si pop dx pop bx ret ;Initialisation des segments initialise_segments: mov ax, cs mov ds, ax mov es, ax mov ax, 0x8000 cli mov ss, ax mov sp, 0xF000 sti ret ;Fin initialisation segments mode_souhaite: dw 0x0013 maxResol: dw 0 couleur_defaut: db 0x00, 0x1F, 0x1F, 0x1F; ARGB couleurPoint: db 0x00, 0xFF, 0x00, 0x00; ARGB octetsParPixel: db 4 bloc_courant: db 0 disquettes: db ' lecteur(s) de disquette installé(s).', 13, 0 pas: db 'Pas de ', 0 coprocesseur: db 'Coprocesseur arithmétique.', 13, 0 memoire_dispo: db ' ko.', 13, 0 au_demarrage: db ' au démarrage.', 13, 0 DMA: db 'DMA.', 13, 0 RS232: db ' port(s) RS232 disponible(s).', 13, 0 manette: db 'Manette de jeu.', 13, 0 modem_interne: db 'Modem interne.', 13, 0 imprimantes: db ' imprimante(s) connectée(s).', 13, 0 heure: db '00 h 00 min 00 s', 13, 0 retour_chariot: db 13, 0 nombre_de_cylindres: db ' cylindres.', 13, 0 nombre_de_tetes: db ' tetes.', 13, 0 nombre_de_secteurs: db ' secteurs par piste.', 13, 0 pas_33h: db 'Pas d`interruption 0x33.', 13, 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 res2: times 216 db 0; Complément à 256 octets, taille du bloc %include "alphabet.asm" hello: db 'Bonjour papi. Je cherche une ligne de plus de quatre vingts caractères. Ce doit être relativement facile à trouver, non ?', 13, 0 times 4096-($-$$) db 0