; Illustre l'affichage de texte plein en VGA, en utilisant la technique en ; une passe de BitMan, basée sur le mode write 3. CHAR_HEIGHT equ 8 ;nombre de lignes d'affichage par caractère ;(doit être <256) SCREEN_HEIGHT equ 480 ;nombre de lignes d'affichage par écran SCREEN_SEGMENT equ 0a000h ;emplacement de la mémoire de l'écran FG_COLOR equ 14 ;couleur du texte BG_COLOR equ 1 ;couleur de la boîte du fond GC_INDEX equ 3ceh ;port E/S du registre Index Graphics Controller (GC) SET_RESET equ 0 ;index du registre Set/Reset dans GC G_MODE equ 5 ;index du registre Graphics Mode dans GC BIT_MASK equ 8 ;index du registre Bit Mask dans GC .model small .stack 200h .data Line dw ? ;numéro de la ligne courante CharHeight dw ? ;nombre de lignes d'affichage dans chaque caractère ;(doit être <256) MaxLines dw ? ;nombre maximal de lignes d'affichage du texte qui ;seront à l'écran LineWidthBytes dw ? ;offset d'une ligne d'affichage à une autre FontPtr dd ? ;pointeur sur la police avec laquelle afficher SampleString label byte db 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' db 'abcdefghijklmnopqrstuvwxyz' db '0123456789!@#$%^&*(),<.>/?;:',0 .code start: mov ax,@data mov ds,ax mov ax,12h int 10h ;sélectionne le mode 640x480 en 16 couleurs mov ah,11h ;fonction génératrice de caractère du BIOS mov al,30h ;sous-fonction qui récupère le pointeur de la police du BIOS mov bh,3 ;sous-fonction qui récupère la police 8x8 ROM int 10h ;récupère le pointeur sur la police 8x8 du BIOS mov word ptr [FontPtr],bp mov word ptr [FontPtr+2],es mov bx,CHAR_HEIGHT mov [CharHeight],bx ;nombre de lignes d'affichage par caractère mov ax,SCREEN_HEIGHT sub dx,dx div bx mul bx ;nombre maximal de lignes d'affichage pleines du mov [MaxLines],ax ;du texte qui seront à l'écran mov ah,0fh ;fonction du statut vidéo du BIOS int 10h ;récupère le nombre de colonnes (octets) par rangée mov al,ah ;convertit la variable de colonne en octet sub ah,ah ;dans AH en mot dans AX mov [LineWidthBytes],ax ;largeur des lignes d'affichage en octet ;affiche à présent le texte sub bx,bx mov [Line],bx ;commence à la ligne d'affichage 0 LineLoop: sub ax,ax ;commence à la colonne 0; doit être un multiple ;de 8 mov ch,FG_COLOR ;couleur dans laquelle afficher le texte mov cl,BG_COLOR ;couleur dans laquelle afficher la boîte du fond mov si,offset SampleString ;texte à afficher call DrawTextString ;affiche le texte test mov bx,[Line] add bx,[CharHeight] ;numéro de la prochaine ligne d'affichage dans laquelle afficher mov [Line],bx cmp bx,[MaxLines] ;fin? jb LineLoop ;pas encore mov ah,7 int 21h ;attend une touche clavier, sans écho mov ax,03h int 10h ;revient en mode texte mov ah,4ch int 21h ;quitte pour DOS ; Affiche une chaîne de texte. ; Entrée: ; AX = coordonnée X à laquelle afficher le coin supérieur gauche du ; premier caractère ; BX = coordonnée Y à laquelle afficher le coin supérieur gauche du premier ; caractère ; CH = couleur de premier plan (texte) ; CL = couleur de fond (boîte) ; DS:SI = pointeur sur la chaîne à afficher, terminée par zéro ; CharHeight doit être paramétré à la hauteur de chaque caractère ; FontPtr doit être paramétré à la police d'affichage ; LineWidthBytes doit être paramétré à la largeur en octets des lignes ; d'affichage ; Ne pas compter sur les registres autres que DS, SS, et SP qui sont préservés. ; La coordonnée X est tronquée en un multiple de 8. Les caractères sont supposés ; avoir 8 pixels de large. align 2 DrawTextString proc near cld shr ax,1 ;adresse de l'octet X de départ dans la ligne d'affichage shr ax,1 shr ax,1 mov di,ax mov ax,[LineWidthBytes] mul bx ;offset de départ de la ligne d'affichage initiale add di,ax ;offset de départ de l'octet initial mov ax,SCREEN_SEGMENT mov es,ax ;ES:DI = offset de la première ligne d'affichage ;du caractère initial ;configure le matériel du VGA afin que nous ;puissions remplir les latches avec la couleur de fond mov dx,GC_INDEX mov ax,(0ffh SHL 8) + BIT_MASK out dx,ax ;positionne le registre Bit Mask à 0xFF (par ;défaut, mais je le fais pour m'assurer que ;vous comprenez que le registre Bit Mask et ;les données CPU ont eu un AND dans le mode Write 3) mov ax,(003h SHL 8) + G_MODE out dx,ax ;sélectionne le mode Write 3 mov ah,cl ;couleur de fond mov al,SET_RESET out dx,ax ;paramètre la couleur d'affichage à la couleur ,de fond mov byte ptr es:[0ffffh],0ffh ;écrit 8 pixels de la couleur de fond ; dans la mémoire offscreen inutilisée mov cl,es:[0ffffh] ;relit la couleur de fond dans les latches ;les latches sont remplis maintenant de la ;couleur de fond. Peu importe la valeur ;dans CL ;nous avons juste besoin d'une cible pour lire ;ainsi nous pourrons charger les latches mov ah,ch ;couleur de premier plan out dx,ax ;paramètre la couleur set/reset (affichage) à ;la couleur de premier plan ;nous sommes prêts à afficher ! DrawTextLoop: lodsb ;prochain caractère à afficher and al,al ;fin de la chaîne? jz DrawTextDone ;oui push ds ;mémorise le segment de la chaîne push si ;mémorise l'offset du prochain caractère dans ;la chaîne push di ;mémorise l'offset d'affichage ;charge ces variables avant de supprimer DS mov dx,[LineWidthBytes] ;offset d'une ligne à la suivante dec dx ;compense pour STOSB mov cx,[CharHeight] ; mul cl ;offset du caractère dans la table des polices lds si,[FontPtr] ;pointe sur la table des polices add si,ax ;pointe sur le début du caractère à afficher ;la boucle qui suit devrait être déroulée ;afin d'obtenir un maximum de performance! DrawCharLoop: ;affiche toutes les lignes du caractère movsb ;récupère le prochain octet du caractère et ;affiche le caractère; AND de donnée ;avec le registre Bit Mask pour devenir ;le masque ;de bits, et sélectionne entre le latch ;(contenant la couleur de fond) et registre ;Set/Reset (contenant la couleur du premier ;plan) add di,dx ;pointe sur la prochaine ligne destination loop DrawCharLoop pop di ;retrouve l'offset d'affichage initial inc di ;offset d'affichage du prochain caractère pop si ;retrouve l'offset du prochain caractère ;dans la chaîne pop ds ;retrouve le segment de la chaîne jmp DrawTextLoop ;affiche le prochain caractère, s'il y en a align 2 DrawTextDone: ;restaure le registre Graphics Mode à son ;état par défaut en mode Write 0 mov dx,GC_INDEX mov ax,(000h SHL 8) + G_MODE out dx,ax ;sélectionne le mode Write 0 ret DrawTextString endp end start