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

Programmation d'OS Assembleur Discussion :

Kernel C ne démarre pas


Sujet :

Programmation d'OS Assembleur

  1. #1
    Nouveau Candidat au Club
    Homme Profil pro
    Chef de projet MOA
    Inscrit en
    Septembre 2012
    Messages
    3
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Chef de projet MOA
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2012
    Messages : 3
    Points : 0
    Points
    0
    Par défaut Kernel C ne démarre pas
    Bonjour a tous pour approfondire mais connaissance j'aimerai démarre un mini noyau en asm C/C++ j'ai passer 2 ans sur le C et 8 mois sur Asm
    donc je suis aller sur se site pour Débuter se projet :

    http://a.michelizza.free.fr/pmwiki.php

    donc j'ai bien compris le bootloader en Asm et le kernel qui affiche un message

    mon soucis c'est au passage du kernel en C donc voici le bootloader :

    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
     
    %define BASE    0x1000  ; 0x0100:0x0 = 0x1000
    %define KSIZE   50     ; nombre de secteurs a charger
     
    [BITS 16]
    [ORG 0x0]
     
    jmp start
     
    afficher:
        push ax
        push bx
    .debut:
        lodsb         ; ds:si -> al
        cmp al, 0     ; fin chaine ?
        jz .fin
        mov ah, 0x0E  ; appel au service 0x0e, int 0x10 du bios
        mov bx, 0x07  ; bx -> attribut, al -> caractere ascii
        int 0x10
        jmp .debut
    .fin:
        pop bx
        pop ax
        ret
     
    start:
     
    ; initialisation des segments en 0x07C0
        mov ax, 0x07C0
        mov ds, ax
        mov es, ax
        mov ax, 0x8000    ; stack en 0xFFFF
        mov ss, ax
        mov sp, 0xf000
     
    ; recuparation de l'unite de boot
        mov [bootdrv], dl    
     
    ; affiche un msg
        mov si, msgDebut
        call afficher
     
    ; charger le noyau
        xor ax, ax
        int 0x13
     
        push es
        mov ax, BASE
        mov es, ax
        mov bx, 0
        mov ah, 2
        mov al, KSIZE
        mov ch, 0
        mov cl, 2
        mov dh, 0
        mov dl, [bootdrv]
        int 0x13
        pop es
     
    ; initialisation du pointeur sur la GDT
        mov ax, gdtend    ; calcule la limite de GDT
        mov bx, gdt
        sub ax, bx
        mov word [gdtptr], ax
     
        xor eax, eax      ; calcule l'adresse lineaire de GDT
        xor ebx, ebx
        mov ax, ds
        mov ecx, eax
        shl ecx, 4
        mov bx, gdt
        add ecx, ebx
        mov dword [gdtptr+2], ecx
     
    ; passage en modep
        cli
        lgdt [gdtptr]    ; charge la gdt
        mov eax, cr0
        or  ax, 1
        mov cr0, eax        ; PE mis a 1 (CR0)
     
        jmp next
    next:
        mov ax, 0x10        ; segment de donne
        mov ds, ax
        mov fs, ax
        mov gs, ax
        mov es, ax
        mov ss, ax
        mov esp, 0x9F000    
     
        jmp dword 0x8:0x1000    ; reinitialise le segment de code
    ;--------------------------------------------------------------------
    bootdrv:  db 0
    msgDebut: db "Chargement du kernel", 13, 10, 0
    ;--------------------------------------------------------------------
    gdt:
        db 0, 0, 0, 0, 0, 0, 0, 0
    gdt_cs:
        db 0xFF, 0xFF, 0x0, 0x0, 0x0, 10011011b, 11011111b, 0x0
    gdt_ds:
        db 0xFF, 0xFF, 0x0, 0x0, 0x0, 10010011b, 11011111b, 0x0
    gdtend:
    ;--------------------------------------------------------------------
    gdtptr:
        dw 0  ; limite
        dd 0  ; base
    ;--------------------------------------------------------------------
     
    ;; NOP jusqu'a 510
    times 510-($-$$) db 144
    dw 0xAA55
    puis le kernel en C


    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
     
     
    extern void scrollup(unsigned int);
    extern void print(char *);
     
    extern kY;
    extern kattr;
     
    void _start(void)
    {
    	kY = 18;
    	kattr = 0x5E;
    	print("un message\n");
     
    	kattr = 0x4E;
    	print("un autre message\n");
     
    	scrollup(2);
     
    	while (1);
    }
    le screen.c
    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
     
    #include "types.h"
     
    #define RAMSCREEN 0xB8000	/* debut de la memoire video */
    #define SIZESCREEN 0xFA0	/* 4000, nombres d'octets d'une page texte */
    #define SCREENLIM 0xB8FA0
     
    char kX = 0;			/* position courante du curseur a l'ecran */
    char kY = 17;
    char kattr = 0x0E;		/* attributs video des caracteres a afficher */
     
     
    /* 
     * 'scrollup' scrolle l'ecran (la console mappee en ram) vers le haut
     * de n lignes (de 0 a 25).
     */
    void scrollup(unsigned int n)
    {
    	unsigned char *video, *tmp;
     
    	for (video = (unsigned char *) RAMSCREEN;
    	     video < (unsigned char *) SCREENLIM; video += 2) {
    		tmp = (unsigned char *) (video + n * 160);
     
    		if (tmp < (unsigned char *) SCREENLIM) {
    			*video = *tmp;
    			*(video + 1) = *(tmp + 1);
    		} else {
    			*video = 0;
    			*(video + 1) = 0x07;
    		}
    	}
     
    	kY -= n;
    	if (kY < 0)
    		kY = 0;
    }
     
    void putcar(uchar c)
    {
    	unsigned char *video;
    	int i;
     
    	if (c == 10) {		/* CR-NL */
    		kX = 0;
    		kY++;
    	} else if (c == 9) {	/* TAB */
    		kX = kX + 8 - (kX % 8);
    	} else if (c == 13) {	/* CR */
    		kX = 0;
    	} else {		/* autres caracteres */
    		video = (unsigned char *) (RAMSCREEN + 2 * kX + 160 * kY);
    		*video = c;
    		*(video + 1) = kattr;
     
    		kX++;
    		if (kX > 79) {
    			kX = 0;
    			kY++;
    		}
    	}
     
    	if (kY > 24)
    		scrollup(kY - 24);
    }
     
    /*
     * 'print' affiche a l'ecran, a la position courante du curseur, une chaine
     * de caracteres terminee par \0.
     */
    void print(char *string)
    {
    	while (*string != 0) {	/* tant que le caractere est different de 0x0 */
    		putcar(*string);
    		string++;
    	}
    }
    et le type.h
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    #ifndef _I386_TYPE_
    #define _I386_TYPE_
     
    typedef unsigned char u8;
    typedef unsigned short u16;
    typedef unsigned int u32;
    typedef unsigned char uchar;
     
    #endif
    donc avec se boot.asm kernel.c screen.c type.h je compile le tous avec cette commande :

    nasm -f bin boot.asm -o boot.c
    gcc -c kernel.c -o kernel.o
    gcc -c screen.c -o kernel.o

    ld --oformat binary -Ttext 1000 kernel.o screen.o -o kernel

    donc je me retrouve avec un boot.bin et un fichier kernel

    j'installe Grub4dos sur usb et je démarre mon boot.bin et la j'ai chargement du kernel puis il charge mon noyau et reboot directement je suis perdu ici merci de votre aide

  2. #2
    Candidat au Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Mars 2014
    Messages
    2
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 33
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Mars 2014
    Messages : 2
    Points : 4
    Points
    4
    Par défaut
    Relis bien le tutoriel, le code assembleur que tu as écrit est en 16 bits (prévu pour être chargé par le BIOS et non par le GRUB), cela peut se voir via les lignes suivantes:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    [BITS 16] ;spécifie un code 16 bits
    ...
     int 0x13 ;interruption du BIOS pour afficher à l'écran, utilisable uniquement en mode réel (16 bits)
    Au contraire le GRUB passe en mode protégé (32 bits) avant de donner la main à ton code, ce qui inévitablement provoque une erreur dès la première instruction.

  3. #3
    Nouveau Candidat au Club
    Homme Profil pro
    Chef de projet MOA
    Inscrit en
    Septembre 2012
    Messages
    3
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Chef de projet MOA
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2012
    Messages : 3
    Points : 0
    Points
    0
    Par défaut Kernel C qui ne démarre pas
    bonjour merci de votre réponse après avoir bien Lu le tutoriel j'ai effectivement trouver plusieurs erreur
    donc la j'ai un boot en 16 bits qui et charger par le BIOS
    qui charge un mini-noyau en asm qui lui affiche un message ,charge la GDT puis passer en 32 bits puis saute vers mon noyau en C
    donc je compile

    mon Boot en 16 Bits :

    nasm -f bin boot.asm -o Boot.bin

    mon mini noyau :

    nasm -f aout kernel.asm -o kernel.o

    mon noyau :

    gcc - c Main.c

    Compilation de mon micro noyau et mon noyau en C

    ld --oformat binary -Ttext 1000 kernel.o Main.o -o kernel

    donc la je me retrouver un Boot.bin et un fichier kernel ( qui lui contien mon micro noyau en asm qui charge mon noyau en C )

    donc je place mon boot.bin au premier secteur et mon kernel au 2 eme mais Meme erreur

  4. #4
    Membre chevronné
    Avatar de Forthman
    Homme Profil pro
    conception mécanique
    Inscrit en
    Janvier 2005
    Messages
    702
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : France, Tarn et Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : conception mécanique
    Secteur : Industrie

    Informations forums :
    Inscription : Janvier 2005
    Messages : 702
    Points : 1 905
    Points
    1 905
    Par défaut
    question : quand tu passes en mode protégé, et que tu "sautes" vers ton kernel, comment est codé ton saut ? en 16 ou en 32 bits ?

  5. #5
    Nouveau Candidat au Club
    Homme Profil pro
    Chef de projet MOA
    Inscrit en
    Septembre 2012
    Messages
    3
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Chef de projet MOA
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2012
    Messages : 3
    Points : 0
    Points
    0
    Par défaut Kernel C qui ne démarre pas
    bonjour désolé pour le retard donc le bootloader et en 16 Bits car quand je charge la GDT ( 32 Bits ) la VM bloque Erreur de processeur et la VM redémarre

    donc je suis obliger de passer en 16bits mai le noyau en C ne se lance pas je vois pas mon erreur

  6. #6
    Nouveau membre du Club
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Janvier 2014
    Messages
    24
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Janvier 2014
    Messages : 24
    Points : 26
    Points
    26
    Par défaut
    Idem, le noyau C ne se lance pas, bien que cela boot sans problème

  7. #7
    Nouveau Candidat au Club
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Juillet 2014
    Messages
    1
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Pyrénées Atlantiques (Aquitaine)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Juillet 2014
    Messages : 1
    Points : 1
    Points
    1
    Par défaut Là, ca devrait pouvoir démarrer correctement !
    Bonsoir !

    Je ne sais pas si ce sujet est encore d'actualité mais quelque chose me surprend dans le code du premier message:
    je récupère quelques lignes:
    %define BASE 0x1000 ; 0x0100:0x0 = 0x1000
    [...]
    puis plus loin...
    push es
    mov ax, BASE
    mov es, ax
    mov bx, 0
    mov ah, 2
    mov al, KSIZE
    mov ch, 0
    mov cl, 2
    mov dh, 0
    mov dl, [bootdrv]
    int 0x13
    pop es
    J'en déduit que le noyau sera chargé à l'addrese 16 bits AX:BX soit 1000:0000, ce qui équivaut pile-poil après le 64ème kilo octet dans la mémoire. C'est comme ca en 16 bits.
    J'en arrive au jump final, qui lui est en 32 bits:
    jmp dword 0x8:0x1000
    0x1000 est une addresse mémoire à lire en 32 bits cette fois-ci soit 0x0000:1000, c'est juste après le premier 4ko de mémoire.
    Ca veut dire qu'il ne saute pas à l'endroit ou se trouve le noyau en C !

    Si je voulais une correspondance entre la valeur mise dans BASE et là ou je saute avec mon jump, j'aurais mis plutot:
    jmp dword 0x8:0x1000 << 4
    ou
    jmp dword 0x8:0x10000
    Afin qu'il saute à l'addresse 32 bits 0001:0000 qui pointe au même endroit que la version 16 bits 1000:0000, soit juste après les 64 premiers kilos octets de mémoire.
    Ensuite pour le LD je met un offset de 10000 à la place de 1000, comme ca:
    ld --oformat binary -melf_i386 -Ttext 10000 kernel.o screen.o -o kernel
    (jai précisé que c'était un noyau 32 bits dans la foulée... mes fichiers C sont compilés avec ces arguments "-Wall -m32 -fno-builtin -c" )
    Et enfin, un DD pour finir le tout.
    cat boot.bin kernel /dev/zero | dd of=mon_os.img bs=512 count=1000
    Il faut veiller à ce que la taille du 'disque" soit supèrieure à celle qui fut définie par: %define KSIZE 50 ; nombre de secteurs a charger

    Voili, voulou, à mon avis, le soucis était à ce niveau là, l'erreure initiale était sur le dernier jump.

    Une fois passé en 32 bits, la première fonction à créer sera probablement une imitation de printf (mode texte ou mode VESA sur le LFB, bien plus joli ^^) avec sa gestion des %s, %i, %c... pour afficher des 'sous-chaines' et la valeur des variables. Ca tombe sous le sens que c'est absolument necessaire pour le débuggage de base dans les étapes suivantes. Et puis c'est marrant de recoder un printf en assembleur ou en C si pas envie d'y perdre trop de temps. On peut faire plus simple et plus 'graphique' que la console Linux !


    ps: Après le chargement du noyau via l'interuption 13h, il est interessant d'ajouter une ligne telle : jc fatal_disk_error ; gestion erreur -> JC :Saut si drapeau de retenue vaut 1 (CF = 1). qui renvoit sur l'affichage d'une string d'erreure de chargement. simple précaution.

Discussions similaires

  1. Réponses: 2
    Dernier message: 24/11/2007, 11h56
  2. [VS.Net 2005][ClickOnce] Mon application ne démarre pas
    Par Vonotar dans le forum Visual Studio
    Réponses: 3
    Dernier message: 07/12/2005, 14h44
  3. [OAI] Agent ne démarre pas
    Par mokrac dans le forum Oracle
    Réponses: 3
    Dernier message: 22/11/2005, 14h03
  4. nouvelle CM et ça ne démarre pas
    Par loveflower dans le forum Composants
    Réponses: 16
    Dernier message: 11/05/2005, 16h50
  5. Services Oracle ne démarre pas sans connexion réseau??
    Par dreamanoir dans le forum Oracle
    Réponses: 6
    Dernier message: 22/02/2005, 00h44

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