Forum Linux.noyau impossible d'afficher des pixels via le mode reel

Posté par  . Licence CC By‑SA.
Étiquettes : aucune
6
10
août
2019

Bonjour à tous,

voila je suis en train de faire mon petit systeme d'exploitation maison. J'ai réalisé un MBR tres simple qui charge mon noyau dans la RAM (via l'aide du bios) puis je saute à l'adresse de mon noyau. Le noyau par la suite affiche du texte via la carte graphic qui est mappé en mémoire, et ca marche.

Je veux maintenant par ce meme procédé rendre mon écran bleu puis ensuite afficher mon texte. Et la ca ne marche pas du tout, seul le texte est affiché. d'apres ce que j'ai lu, pour afficher un pixel, ca se fait au segment 0xA000 avec ensuite 64Ko d'offset pour afficher les pixels. Je vous montre mon code :

[BITS 16] ; directive pour le compilateur : les instructions sont sur 16 bits
[ORG 0x0]

jmp start

start:
mov ax, 0xA000 ; 
mov es, ax

mov ax, 0x8000 ;segment pour la pile
mov ss, ax

mov bp, 0xFFFF ;base pour la pile
mov sp, bp
mov bx, 0
mov ax, 64000

loop: ;tant que la variable 64000 n'a pas atteint 0 on dessine un pixel bleu
sub ax, 0x01    
mov byte [es:bx], 1 ;on dessine un pixel bleu 
add bx, 0x01    
cmp ax, 0x0
jne loop


mov ax, 0xB000
mov es, ax 
mov byte [es:0x8A00], 'H'
mov byte [es:0x8A01], 0x57
mov byte [es:0x8A02], 'E'
mov byte [es:0x8A03], 0x0A
mov byte [es:0x8A04], 'L'
mov byte [es:0x8A05], 0x4E
mov byte [es:0x8A06], 'L'
mov byte [es:0x8A07], 0x62
mov byte [es:0x8A08], 'O'
mov byte [es:0x8A09], 0x0E

end:
    jmp end

Je ne comprend pas pourquoi ca ne marche pas. Avez vous une idée ?
merci d'avance
Cdt

  • # Ca fait des années que je n'ai plus fait ça ...

    Posté par  . Évalué à 3.

    Mais peut-être une piste ici ? :

    https://stackoverflow.com/questions/48648548/graphics-mode-in-assembly-8086

    Pour info: en mode texte, tu dois écrire à l'adresse 0B800:0000, sur 2 octets. Le premier est l'octet correspondant à ton caractère, le second est celui correspondant à son attribut.

    Si tu veux tracer des pixels ou des lignes il faut passer en mode graphique (mode 13h: http://www.brackeen.com/vga/basics.html#5 ). Par contre je ne suis pas sur que tu puisses écrire du texte simplement, et le premier lien que j'ai donné devrait t'en dire plus.

  • # Nostalgie, nostalgie

    Posté par  . Évalué à 2.

    Salut,

    Pour completer les propos de totof2000, dans ton programme, tu assignes ES a 0b000h, qui est le segment de la memoire video du mode MDA mais tu accedes clairement au segment 0b800h du mode CGA ou 0b000h:8000h, ca revient au meme mais bon, ca parait etrange. Quelles ressources as-tu utilisees ?

    Aussi, tu assignes BP mais tu ne l'utilises pas. Et ce n'est pas une bonne idee d'assigner SP avec une valeur impaire, car sur le 8086, il y a une penalite en cas d'acces a un mot non aligne.

    Et je ne parlerai pas du saut inutile au debut du programme. Ah si.

    Je me permets de te conseiller un livre sur la programmation assembleur 8086 sous DOS disponible gratuitement : The Art of Assembly Language : http://www.ic.unicamp.br/~pannain/mc404/aulas/pdfs/Art%20Of%20Intel%20x86%20Assembly.pdf

    Il me semble qu'il est lie a une bibliotheque : UCR standard library ou pas loin qui est dans le domaine public.

    En tout cas, je te souhaite bon succes dans ton exploration de ce systeme 8086.

    • [^] # Re: Nostalgie, nostalgie

      Posté par  . Évalué à 1. Dernière modification le 10 août 2019 à 22:23.

      effectivement toute la partie du code avec BP c'est de la magie noir que j'aurais du supprimé. Pour la premiere partie de ta réponse, je ne l'ai pas trop comprise. la carte vidéo est mappé en mémoire donc j'utilise tout simple segment << 4 + offset pour arrivé sur la bonne case mémoire physique, et les différentes combinaisons pour acceder a cette mémoire physique est tres grande .

      pour les sources que j'utilise : Texte du lien mais j'ai dépassé le cadre du tuto pour ce que je veux faire

      • [^] # Re: Nostalgie, nostalgie

        Posté par  . Évalué à 1.

        Je comprends, tu es parti d'un tuto 32-bit et tu as fait la conversion.

        Voici un bout de code effacant l'ecran en mode texte :

             mov ax,0b800h
             mov es,ax
        
             mov al,32
             mov ah,1fh  ; fond bleu (1), ecriture en blanc (0fh)
        
             mov cx,80*25
             xor di,di
             cld
             rep stosw
        

        Ca remplit la memoire de caractere ASCII 32 (espace) avec fond bleu et inscription en blanc.
        J'utilise 0b800h comme segment de base, ainsi le premier caractere est en 0 plutot que 8000h.

        Le chapitre 23 du PDF que je t'ai suggere traite de la memoire video.

        • [^] # Re: Nostalgie, nostalgie

          Posté par  . Évalué à 1.

          yes ton idée est bonne pour mettre mon écran en bleu. Ton pdf ne parle helas que du mode text graphic or moi je veux dessiner des pixels non du text. J'ai l'impression que utiliser la carte graphique est beaucoup plus compliqué que je ne le pensais. Tout ce que je vois sur internet c'est de passer a travers le bios pour dessiner des pixels.

          • [^] # Re: Nostalgie, nostalgie

            Posté par  . Évalué à 1.

            Une fois le mode 13h active, c'est assez simple en fait, si tout ce que tu veux faire est d'afficher des pixels.

            Le segment de base pour ce mode est 0a000h. Les octets aux offsets de 0 a 63999 representent les 64000 (320*200) pixels dans l'ordre horizonal gauche-droite et vertical bas-haut. Donc y*320+x te donne l'offset d'un pixel. Un pixel = un octet representant un index dans la palette. La palette est composee de 256 couleurs sur 262.144 et avec une carte graphique d'epoque du moins, est configurable assez facilement sans passer par le BIOS.

            Petit exemple pour afficher un pixel blanc au centre :

            mov ah,0 ; selectionne un mode video
            mov al,13h
            int 10h
            
            mov ax,0a000h
            mov es,ax
            
            mov byte [es:100*320+160],15 ; pixel blanc (15 dans la palette par defaut) en x=160 et y=100
            

            Apres si tu avais deja compris tout ca et que tu veux passer en mode 13h sans BIOS, ca sera une autre paire de manches.

          • [^] # Re: Nostalgie, nostalgie

            Posté par  . Évalué à 3.

            J'ai traduit jusque ce qu'il faut du programme C passe en lien par totof2000 en assembleur (https://files.osdev.org/mirrors/geezer/osd/graphics/modes.c) pour passer en mode 13h sans utiliser le BIOS. Seule la fonction write_regs() etait necessaire, ainsi que le tableau g_320x200x256. La palette me semble rudimentaire mais facilement reprogrammable.

            Malheureusement mon XT n'a qu'une carte CGA donc j'ai teste ca avec dosemu.

                    ...
            
                    ; passe en mode 13h
                    mov si,g_320x200x256
                    call write_regs
            
                    ; ES = segment de base de la memoire video
                    mov ax,0a000h
                    mov es,ax
            
                    ; efface l'ecran
                    xor di,di
                    xor ax,ax
                    mov cx,320*200/2
                    cld
                    rep stosw
            
                    ; pixel en 160,100
                    mov byte [es:100*320+160],1
            
                    ...
            
            VGA_AC_INDEX    equ 3c0h
            VGA_AC_WRITE    equ 3c0h
            VGA_AC_READ     equ 3c1h
            VGA_MISC_WRITE  equ 3c2h
            VGA_SEQ_INDEX   equ 3c4h
            VGA_SEQ_DATA    equ 3c5h
            VGA_CRTC_INDEX  equ 3d4h
            VGA_CRTC_DATA   equ 3d5h
            VGA_GC_INDEX    equ 3ceh
            VGA_GC_DATA     equ 3cfh
            VGA_INSTAT_READ equ 3dah
            
            VGA_NUM_SEQ_REGS        equ 5
            VGA_NUM_CRTC_REGS       equ 25
            VGA_NUM_GC_REGS equ 9
            VGA_NUM_AC_REGS equ 21
            
            g_320x200x256:
            
            ; MISC
                    db 63h
            
            ; SEQ
                    db 03h, 01h, 0Fh, 00h, 0Eh
            
            ; CRTC
                    db 5Fh, 4Fh, 50h, 82h, 54h, 80h, 0BFh, 1Fh
                    db 00h, 41h, 00h, 00h, 00h, 00h, 00h, 00h
                    db 9Ch, 0Eh, 8Fh, 28h, 40h, 96h, 0B9h, 0A3h
                    db 0FFh
            
            ; GC
                    db 00h, 00h, 00h, 00h, 00h, 40h, 05h, 0Fh
                    db 0FFh
            
            ; AC
                    db 00h, 01h, 02h, 03h, 04h, 05h, 06h, 07h
                    db 08h, 09h, 0Ah, 0Bh, 0Ch, 0Dh, 0Eh, 0Fh
                    db 41h, 00h, 0Fh, 00h, 00
            
            ;void write_regs(unsigned char *regs)
            ;{
            ;       unsigned i;
            ;
            ; Entree : DS:SI = tableau g_xxx
            write_regs:
            
                    cld
            
            ;/* write MISCELLANEOUS reg */
            ;       outportb(VGA_MISC_WRITE, *regs);
            ;       regs++;
            
                    mov dx,VGA_MISC_WRITE
                    lodsb
                    out dx,al
            
            ;/* write SEQUENCER regs */
            ;       for(i = 0; i < VGA_NUM_SEQ_REGS; i++)
            ;       {
            ;               outportb(VGA_SEQ_INDEX, i);
            ;               outportb(VGA_SEQ_DATA, *regs);
            ;               regs++;
            ;       }
            
                    xor cl,cl
            .l1:
                    mov dx,VGA_SEQ_INDEX
                    mov al,cl
                    out dx,al
                    mov dx,VGA_SEQ_DATA
                    lodsb
                    out dx,al
                    inc cl
                    cmp cl,VGA_NUM_SEQ_REGS
                    jnz .l1
            
            ;/* unlock CRTC registers */
            ;       outportb(VGA_CRTC_INDEX, 0x03);
            ;       outportb(VGA_CRTC_DATA, inportb(VGA_CRTC_DATA) | 0x80);
            ;       outportb(VGA_CRTC_INDEX, 0x11);
            ;       outportb(VGA_CRTC_DATA, inportb(VGA_CRTC_DATA) & ~0x80);
            
                    mov dx,VGA_CRTC_INDEX
                    mov al,3
                    out dx,al
            
                    mov dx,VGA_CRTC_DATA
                    in al,dx
                    or al,80h
                    out dx,al
            
                    mov dx,VGA_CRTC_INDEX
                    mov al,11h
                    out dx,al
            
                    mov dx,VGA_CRTC_DATA
                    in al,dx
                    and al,7fh
                    out dx,al
            
            ;/* make sure they remain unlocked */
            ;       regs[0x03] |= 0x80;
            ;       regs[0x11] &= ~0x80;
            
                    or byte [si+3],80h
                    and byte [si+11h],7fh
            
            ;/* write CRTC regs */
            ;       for(i = 0; i < VGA_NUM_CRTC_REGS; i++)
            ;       {
            ;               outportb(VGA_CRTC_INDEX, i);
            ;               outportb(VGA_CRTC_DATA, *regs);
            ;               regs++;
            ;       }
            
                    xor cl,cl
            .l2:
                    mov dx,VGA_CRTC_INDEX
                    mov al,cl
                    out dx,al
            
                    mov dx,VGA_CRTC_DATA
                    lodsb
                    out dx,al
            
                    inc cl
                    cmp cl,VGA_NUM_CRTC_REGS
                    jnz .l2
            
            ;/* write GRAPHICS CONTROLLER regs */
            ;       for(i = 0; i < VGA_NUM_GC_REGS; i++)
            ;       {
            ;               outportb(VGA_GC_INDEX, i);
            ;               outportb(VGA_GC_DATA, *regs);
            ;               regs++;
            ;       }
            
                    xor cl,cl
            .l3:
                    mov dx,VGA_GC_INDEX
                    mov al,cl
                    out dx,al
            
                    mov dx,VGA_GC_DATA
                    lodsb
                    out dx,al
            
                    inc cl
                    cmp cl,VGA_NUM_GC_REGS
                    jnz .l3
            
            ;/* write ATTRIBUTE CONTROLLER regs */
            ;       for(i = 0; i < VGA_NUM_AC_REGS; i++)
            ;       {
            ;               (void)inportb(VGA_INSTAT_READ);
            ;               outportb(VGA_AC_INDEX, i);
            ;               outportb(VGA_AC_WRITE, *regs);
            ;               regs++;
            ;       }
            
                    xor cl,cl
            .l4:
                    mov dx,VGA_INSTAT_READ
                    in al,dx
            
                    mov dx,VGA_AC_INDEX
                    mov al,cl
                    out dx,al
            
                    mov dx,VGA_AC_WRITE
                    lodsb
                    out dx,al
            
                    inc cl
                    cmp cl,VGA_NUM_AC_REGS
                    jnz .l4
            
            ;/* lock 16-color palette and unblank display */
            ;       (void)inportb(VGA_INSTAT_READ);
            ;       outportb(VGA_AC_INDEX, 0x20);
            
                    mov dx,VGA_INSTAT_READ
                    in al,dx
            
                    mov dx,VGA_AC_INDEX
                    mov al,20h
                    out dx,al
            
                    ret
            
            • [^] # Re: Nostalgie, nostalgie

              Posté par  . Évalué à 3. Dernière modification le 13 août 2019 à 12:05.

              Hello.

              Malheureusement mon XT n'a qu'une carte CGA donc j'ai teste ca avec dosemu.

              Faut pas désespérer …

              https://www.seasip.info/VintagePC/cga.html ;)

              • [^] # Re: Nostalgie, nostalgie

                Posté par  . Évalué à 1.

                Aaah ces machines recelent encore bien des secrets.

                Ceci dit, j'etais juste decu de ne pas pouvoir tester mon programme sur une vraie machine, sinon je trouve que le mode 4 couleurs a un certain charme.

          • [^] # Re: Nostalgie, nostalgie

            Posté par  . Évalué à 1.

            As-tu trouve satisfaction ?

  • # Situation de concurrence

    Posté par  . Évalué à 1.

    Je viens d'y penser. Dans ton programme, il existe une situation de concurrence par le fait que tu charges SS et SP separements. Couper les interruptions avec l'instruction CLI ne suffirait pas car ton systeme pourrait aussi recevoir une interruption non-masquable.

    Sur mon systeme une NMI peut etre generee par le 8087 ou en cas d'erreur de parite memoire par exemple.

    Utilise LSS pour charger SS:SP a la place. L'instruction est atomique et te premunira de ce probleme.

Suivre le flux des commentaires

Note : les commentaires appartiennent à celles et ceux qui les ont postés. Nous n’en sommes pas responsables.