IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

x86 32-bits / 64-bits Assembleur Discussion :

Bootloader et Kernel, passage mode protégé ↔ réel


Sujet :

x86 32-bits / 64-bits Assembleur

  1. #1
    Membre régulier
    Inscrit en
    Mars 2006
    Messages
    209
    Détails du profil
    Informations forums :
    Inscription : Mars 2006
    Messages : 209
    Points : 95
    Points
    95
    Par défaut Bootloader et Kernel, passage mode protégé ↔ réel
    Bonjour à vous tous !

    Me revoilà, et encore avec des problèmes (pour changer). Je me suis mis il y a plus ou moins 1 mois a l'assembleur et, comme tous débutant, on veut faire de grandes choses, comme coder un OS comme Windows (version -14 pour ma part :p). Je suis le tutoriel sur le cours de Pépin, très bien fait en plus, mais voilà, je suis arrivé au mode protégé. Donc, plus d'interruption et, pour le mode VESA, ça devient compliqué haha :p.

    Pour le mode vesa, en recherchant, je suis tombé sur ce lien où une des personnes explique (en gros) comment utiliser le mode VESA 2.0 en mode protégé. Mais voilà, vu que je suis déjà en mode protégé, quelques soucis « subsistent » (pas sûr de l'écriture) et, donc, je me suis résolu à faire quelques tests en mode texte, plutôt que de faire le kikoolol. J'ai réussi à afficher un écran blanc sans en comprendre le fonctionnement. J'ai donc testé un total de 2 codes. Les deux sont assez légers ^^.

    Voila le bootloader, il passe en mode protégé :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    %define BASE    0x100  ; 0x0100:0x0 = 0x1000
    %define KSIZE   50     ; nombre de secteurs a charger
     
    [BITS 16]
    [ORG 0x0]
     
    jmp start
    start:
     
    	;initialisation des segments en 0x07C0
        mov ax, 0x07C0
        mov ds, ax
        mov es, ax
     
    	;Initialisation de la pile(F000h - 8000h) = 7000h
        mov ax, 0x8000    
        mov ss, ax
        mov sp, 0xF000
     
    	;On récupère l'unité de boot utilisée
    	;Disque dur? Disquette?
        mov [bootdrv], dl    
     
    	;charger le noyau
        xor ax, ax
        int 0x13
     
    	;On sauvegarde es
        push es
     
    	;On récupère l'adresse du début du kernel
        mov ax, BASE
        mov es, ax
        mov bx, 0
     
    	;On récupère la fonction et le nombre de secteurs à charger
        mov ah, 2
        mov al, KSIZE
     
    	;On indique les cylindres et à partir de quel secteur on charge
        mov ch, 0
        mov cl, 2
     
    	;On indique à partir de quelle tête et quelle unité de disque
        mov dh, 0
        mov dl, [bootdrv]
        int 0x13
     
    	;On restaure es
        pop es
     
    	;initialisation du pointeur sur la GDT
    	;Calcul de la limite de la GDT (fin - début)
        mov ax, gdtend
        mov bx, gdt
        sub ax, bx
    	;On met la limite dans le premier champ de la gdt
        mov word [gdtptr], ax
     
    	;Calcul de l'adresse linéaire de la GDT
    	;Mise à 0 des registres
        ; xor eax, eax
        ; xor ebx, ebx
     
    	; On récupère l'adresse de base 0x07C0
        ; mov ax, ds
     
    	; On "déplace d'une lettre vers gauche" l'adresse de base
    	; 0x07C0 -->> 0x7C00
        ; mov ecx, eax
        ; shl ecx, 4
    	; On Ajoute le pointeur de la gdt
        ; mov bx, gdt
        ; add ecx, ebx
    	; On écrit le pointeur dans le champ pointeur de la GDT
        ; mov dword [gdtptr + 2], ecx
     
    	mov eax, 0x7C00
    	add eax, gdt
    	mov dword [gdtptr + 2], eax
     
    	;passage en modep
        cli              ;Annule les interruptions
        lgdt [gdtptr]    ;charge la gdt
        mov eax, cr0
        or  ax, 1
        mov cr0, eax     ;On met le bit de poids faible de CR0 a 1
     
    	;On vide le cache interne
        jmp next
    	next:
     
    	;Et on réinitialise les segments
    	;Les segments de données
        mov ax, 0x10        
        mov ds, ax
        mov fs, ax
        mov gs, ax
        mov es, ax
        mov ss, ax
        mov esp, 0x9F000
     
    	;Réinitialise le segment de code et "jump" vers le kernel
        jmp dword 0x8:0x1000
     
    ;Les Variables
    ;--------------------------------------------------------------------
    bootdrv:  db 0
    ;--------------------------------------------------------------------
    gdt:;Pointeur sur le début du segment de la GDT
        db 0, 0, 0, 0, 0, 0, 0, 0
    	;Déscripteur "NULL"
     
    gdt_cs:
        db 0xFF, 0xFF, 0x0, 0x0, 0x0, 10011011b, 11011111b, 0x0
    	;Descripteur de code
    	;La base est 0x0, la limite 0xFFFFF * 4096 ~= 4go
     
    gdt_ds:
        db 0xFF, 0xFF, 0x0, 0x0, 0x0, 10010011b, 11011111b, 0x0
    	;Descripteur de segment
    	;Idem
     
    gdtend:;Pointeur sur la fin du segment de la GDT
     
    ;--------------------------------------------------------------------
    gdtptr:
        dw 0  ; limite
        dd 0  ; base
    ;--------------------------------------------------------------------
     
    ;Bourrage de 0 pour arriver a 510 octets
    times 510-($-$$) db 0
    ;On ajoute le mot 0x55AA a l'envers car intel = Little Endian
    dw 0xAA55
    Et voici le code du kernel :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    [bits 32]
     
    org 0x1000
     
    jmp _start
    _start:
    	;On réactive les interruptions et on repasse en mode réel
    	sti
    	mov eax, cr0
    	dec eax
    	mov cr0, eax
     
    	;On réinitialise les différents segments
    	mov ax, 0x100
    	mov es, ax
    	mov ds, ax
     
    	;Et on écrit le magnifique caractère 'B'	
    	mov ax, 0x03
    	int 0x10
     
    	xor bx, bx
    	mov cx, 1
     
    	xor dx, dx
     
    	mov ax, 0x02
    	int 0x10
     
    	mov ax, 0x0A42
    	int 0x10
     
    	end: jmp end
    Ce code, comme vous vous en doutez, ne fonctionne évidemment pas, il ne me fait pas "rebooter" le PC comme des fois quand j'essaye d'écrire en dehors d'une zone allouée, mais il laisse l'écran noir, avec le petit curseur qui clignote en haut a gauche, pas très utile donc.

    Je me suis dit que c'était dut au mode "32 bits", mais ma connaissance là-dedans peut s'apparenter à un petit trou noir.

    J'en ai donc profité pour faire un petit bidouillage maison, qui fut tout de même plus convaincant.

    Voici mon fichier kernel1 :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    [bits 32]
     
    %define b2 0x0A00
    org 0x1000
     
    jmp _start
    _start:
    	;On passe en mode réel
    	sti
    	mov eax, cr0
    	dec eax
    	mov cr0, eax
     
    	jmp b2:0
    et kernel2
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    [bits 16]
     
    [org 0x0]
     
    jmp _start
    _start:
     
    	mov ax, 0xA00
    	mov es, ax
    	mov ds, ax
     
    	;On initialise les segments et on affiche le caractère
    	mov ax, 0x03
    	int 0x10
     
    	xor bx, bx
    	mov cx, 1
     
    	xor dx, dx
     
    	mov ax, 0x02
    	int 0x10
     
    	mov ax, 0x0A42
    	int 0x10
     
    	end: jmp end
    Ce code fut plus convaincant, en effet. Il ne m'affiche pas le B, il ne faut pas rêver, mais m'affiche un "fond" cyan de la taille d'un caractère a la place du B.


    Merci de votre aide.

  2. #2
    Membre éclairé
    Avatar de edfed
    Profil pro
    être humain
    Inscrit en
    Décembre 2007
    Messages
    476
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : être humain

    Informations forums :
    Inscription : Décembre 2007
    Messages : 476
    Points : 701
    Points
    701
    Billets dans le blog
    1
    Par défaut
    comment veux tu faire du mode protegé si tu continue à utilser l'int 10h du bios?

    un coup d'oeil sur la doc

    INT 10,9 - Write Character and Attribute at Cursor Position


    AH = 09
    AL = ASCII character to write
    BH = display page (or mode 13h, background pixel value)
    BL = character attribute (text) foreground color (graphics)
    CX = count of characters to write (CX >= 1)


    returns nothing


    - does not move the cursor
    - in graphics mode (except mode 13h), if BL bit 7=1 then
    value of BL is XOR'ed with the background color
    montre que le caractère B ne s'affiche pas car tu ne dis pas correctement à INT 10h ce qu'elle doit faire. tout simplement.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
     
    ;Et on écrit le magnifique caractère 'B'	
    	mov ax, 0x03
    	int 0x10
     
    	xor bx, bx
    	mov cx, 1
     
    	xor dx, dx
     
    	mov ax, 0x02
    	int 0x10
     
    	mov ax, 0x0A42 
    	int 0x10

    utilise ce type de doc quand tu codes avec les interruptions bios et la memoire du mode protegé, ça aide enormement:
    http://docs.huihoo.com/help-pc/int-int_10.html



    mais pour afficher des pixels (ou des caractères selon le mode), il n'y à pas besoin du bios, et donc, pas besoin de repasser en mode reel.
    en utilisant un descripteur de segment pour la zone de mémoire à utiliser.
    d'ailleur, en mode reel aussi on à pas besoin du bios pour afficher, car c'est très lent.

Discussions similaires

  1. Passage en mode protégé
    Par Nyarlathotep dans le forum Assembleur
    Réponses: 1
    Dernier message: 02/02/2007, 20h39
  2. [Débutant] Segmentation mode réel / mode protégé
    Par vivid dans le forum Assembleur
    Réponses: 14
    Dernier message: 21/02/2006, 19h31
  3. Passage en mode protégé
    Par jojo's dans le forum Assembleur
    Réponses: 14
    Dernier message: 10/07/2004, 23h50
  4. Passage en mode protégé avec DPMI
    Par Hell_Hibou dans le forum x86 16-bits
    Réponses: 4
    Dernier message: 09/09/2003, 19h04
  5. Mode protégé pour un OS
    Par Ninkosen dans le forum Programmation d'OS
    Réponses: 2
    Dernier message: 25/11/2002, 13h46

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo