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

C Discussion :

Une fonction qui fonctionne, mais qui ne veut pas fonctionner


Sujet :

C

  1. #1
    Membre averti
    Homme Profil pro
    Étudiant
    Inscrit en
    Juillet 2014
    Messages
    18
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 28
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Juillet 2014
    Messages : 18
    Par défaut Une fonction qui fonctionne, mais qui ne veut pas fonctionner
    Bonjour à tous, je développe mon propre système d'exploitation en assembleur (syntaxe NASM) et en C avec gcc. Je suis aux prémices de mon système et j'ai un bug dans l'exécution de mon petit noyau que je ne parviens pas à résoudre :
    j'ai une fonction print qui écrit dans la mémoire vidéo une chaîne de caractère qu'on lui passe en argument, je l'ai écrite en deux versions :

    version 1 :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    void print (const uint8_t* string)
    {
        for (const uint8_t* i = string; *i != 0; ++i)
        {
            put_char(*i, char_color | char_mode);
            ++cursor_x;
        }
    }
    et version 2 :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    void print (const uint8_t* string)
    {
        for (; *string != 0; ++string)
        {
            put_char(*string, char_color | char_mode);
            ++cursor_x;
        }
    }
    (que personnellement je n'aime pas)

    j'ai ensuite deux versions de mon noyau (si on peut vraiment lui donner ce nom) qui appelle cette fonction, une en assembleur et une en C :

    version assembleur:
    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
    BITS 32
     
    extern init_video
    extern print
     
    global _start
     
    _start:
    call init_video
    mov eax, msg
    push eax
    call print
    pop eax
     
    cli
    hlt
    msg: db " OK : Beetle kernel loaded successfully !", 0
    et version C :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    #include "Beetle/screen.h"
     
    void _start (void)
    {
        init_video();
        print(" OK : Beetle kernel loaded successfully !");
        while(1);
    }
    Quand je compile pour utiliser mon "noyau" assembleur l'appel à ma fonction print marche parfaitement et le texte voulu s'affiche à l'écran, peut importe la version de print que j'utilise, cependant pour la version C du noyau l'appelle marche mais le texte ne s'affiche que pour la deuxième version de print, si j'utilise la première, un bandeau blanc de la taille d'un caractère et faisant toute la longueur de la chaîne s'affiche, et je n'ai pas trouvé pourquoi, avez vous une idée? Au cas où ça serait utile voici les arguments que je passe à
    gcc : -c -ffreestanding -nostdlib -lgcc -I /Users/adrien/Documents/Informatique/OS/Beetle/include. A noter que je suis sur Mac et que j'ai dû compiler une version de gcc avec clang ce qui apparemment n'est pas tout à fait supporter, peut être le problème vient-il de là? Je mettrais sous ce poste tout les fichiers avec le code source pour éviter de sur-charger ce message

  2. #2
    Membre averti
    Homme Profil pro
    Étudiant
    Inscrit en
    Juillet 2014
    Messages
    18
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 28
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Juillet 2014
    Messages : 18
    Par défaut Fichiers
    Comme dit je poste ici tout les fichiers dans leurs intégralité

    bootloader.s
    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
    %define BOOT_POS 0x07C0
    %define BOOT_STACK_START 0x50
    %define BOOT_STACK_SIZE 0x76FF
     
    %define KERNEL_POS_SECTOR_START 0x2
    %define KERNEL_SECTOR_SIZE  0x2
    %define KERNEL_POS_COPY 0x7E0 ;Le kernel sera copié à l'adresse 0x7E00
     
    mov ax, BOOT_POS
    mov ds, ax
    mov es, ax
     
    mov ax, BOOT_STACK_START
    mov ss, ax
    mov sp, BOOT_STACK_SIZE
     
    c_error:
    xor ax, ax
    xor dl, dl
    int 0x13
    jc c_error
     
    ;Le contrôleur de disquette est initialisé
    ;On copie 2 secteurs après le premier secteur de la disquette dans lequel le bootloader est chargé
    mov ax, KERNEL_POS_COPY
    mov es, ax
    xor bx, bx
    mov ah, 0x02
    mov al, KERNEL_SECTOR_SIZE
    xor ch, ch
    mov cl, KERNEL_POS_SECTOR_START
    xor dx, dx
    int 0x13
     
    ;passage en mode 32bits
    cli
     
    mov ax, gdt_end
    mov bx, gdt_start
    sub ax, bx
    mov word [gdtr_limit], ax
     
    xor eax, eax
    xor ebx, ebx
    mov ax, ds
    shl eax, 4
    mov ebx, gdt_start
    add eax, ebx
    mov dword [gdtr_base], eax
     
    lgdt [gdtr_limit]
     
    mov eax, cr0
    or eax, 1
    mov cr0, eax
     
    jmp nxt
    nxt:
    mov ax, 0x10
    mov ds, ax
    mov es, ax
    mov fs, ax
    mov gs, ax
    mov ss, ax
    mov esp, BOOT_STACK_START
     
    jmp 0x8:0x7E00
     
    gdt_start:
        null_segment: dd 0, 0
        code_segment: db 0xFF, 0xFF, 0x0, 0x0, 0x0, 10011011b, 11011111b, 0x0
        data_segment: db 0xFF, 0xFF, 0x0, 0x0, 0x0, 10010011b, 11011111b, 0x0
    gdt_end:
     
    gdtr_limit: dw 0x00
    gdtr_base:  dd 0x0
     
    times 510 - ($ - $$) db 0x00
    dw 0xAA55
    screen.h
    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
    #ifndef SCREEN_H
    #define SCREEN_H
     
    #include <stdint.h>
     
    #define VIDEO_RAM_START 0xB8000
    #define VIDEO_RAM_END   0xBFFFF
     
    static uint8_t cursor_x;
    static uint8_t cursor_y;
    static enum COLOR char_color;
    static enum MODE  char_mode;
     
    enum COLOR
    {
        BLACK,
        BLUE,
        GREEN,
        CYAN,
        RED,
        MAGENTA,
        YELLOW,
        WHITE
    };
     
    enum MODE
    {
        FLASH = 1 << 7,
        NO_FLASH = 0 << 7,
        OVER = 1 << 3,
        NO_OVER = 0 << 3,
        DEFAULT = NO_FLASH | NO_OVER
    };
     
    void init_video (void);
    void print      (const uint8_t*);
     
    #endif
    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
    #include "Beetle/screen.h"
     
    void put_char (const uint8_t pchar, const uint8_t char_attr)
    {
        uint8_t* memory_ptr = (uint8_t*)(cursor_y * 160 + cursor_x * 2 + VIDEO_RAM_START);
        *memory_ptr = pchar;
        *(memory_ptr + 1) = char_attr;
    }
     
    void init_video (void)
    {
        for (uint8_t* i = (uint8_t*)VIDEO_RAM_START; i != (uint8_t*) (VIDEO_RAM_END + 1); ++i)
        {
            *i = 0x00;
        }
     
        cursor_x = 0;
        cursor_y = 0;
        char_color = WHITE;
        char_mode  = DEFAULT;
    }
     
    void print (const uint8_t* string)
    {
        for (; *string != 0; ++string)
        {
            put_char(*string, char_color | char_mode);
            ++cursor_x;
        }
    }
    je vais assez doucement dans le développement c'est pour ça qu'il n'y a pas de fonction pour scroller l'écran etc, je teste tout ce que je fais sur machine réelle car j'ai déjà eu la surprise de voir que quelque chose qui fonctionne sur VirtualBox ne fonctionne pas forcément sur mon petit i5

  3. #3
    Expert éminent

    Femme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2007
    Messages
    5 202
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Juin 2007
    Messages : 5 202
    Par défaut
    Et si tu ajoutais des warnings de compilations: -Wall et -Wextra (dans un second temps)?
    Et si tu compilais en optimisant (-O2 ou -O3)?

    parce qu'a part une copie d'un pointeur, tes deux versions de la fonction semblent identiques.

  4. #4
    Membre averti
    Homme Profil pro
    Étudiant
    Inscrit en
    Juillet 2014
    Messages
    18
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 28
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Juillet 2014
    Messages : 18
    Par défaut
    Citation Envoyé par ternel Voir le message
    Et si tu ajoutais des warnings de compilations: -Wall et -Wextra (dans un second temps)?
    Et si tu compilais en optimisant (-O2 ou -O3)?

    parce qu'a part une copie d'un pointeur, tes deux versions de la fonction semblent identiques.
    Alors c'est assez étrange :
    J'ai compilé avec -Wall et -Wextra et apparement c'était le fait d'utiliser uint8_t* à la place de char* qui posait problème j'ai donc re compilé en remplaçant uint8_t par char, ça à marché, et maintenant quand je remet la version avec des uint8_t ça marche parfaitement. Je n'ai toujours pas compris le problème mais merci

  5. #5
    Expert confirmé

    Avatar de fearyourself
    Homme Profil pro
    Ingénieur Informaticien Senior
    Inscrit en
    Décembre 2005
    Messages
    5 121
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : Etats-Unis

    Informations professionnelles :
    Activité : Ingénieur Informaticien Senior
    Secteur : Industrie

    Informations forums :
    Inscription : Décembre 2005
    Messages : 5 121
    Par défaut
    Je pense que tu avais une partie de ton programme qui était compilé avec une autre compréhension des méthodes. Je dis cela parce que je pense que tes méthodes sont identiques.

    En compilant avec O1, j'obtiens le même code assembleur.

    Note: pas de variables statiques dans ton .h...

  6. #6
    Expert éminent

    Femme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2007
    Messages
    5 202
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Juin 2007
    Messages : 5 202
    Par défaut
    C'est probablement parce que sur ton système, les char sont signés, ce qui n'est pas le cas des uint8_t.

  7. #7
    Membre averti
    Homme Profil pro
    Étudiant
    Inscrit en
    Juillet 2014
    Messages
    18
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 28
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Juillet 2014
    Messages : 18
    Par défaut
    Citation Envoyé par ternel Voir le message
    C'est probablement parce que sur ton système, les char sont signés, ce qui n'est pas le cas des uint8_t.
    pourtant du point de vue du processeur signé ou pas ça ne veut plus rien dire, c'est juste une interprétation du compilateur ça après, ça pourrait jouer un rôle de signer ou pas ses variables ? Ça me semble assez étrange

    Citation Envoyé par fearyourself Voir le message
    Je pense que tu avais une partie de ton programme qui était compilé avec une autre compréhension des méthodes. Je dis cela parce que je pense que tes méthodes sont identiques.

    En compilant avec O1, j'obtiens le même code assembleur.

    Note: pas de variables statiques dans ton .h...
    Bat elles me semblent totalement identique c'est bien pour ça que je ne comprenais pourquoi ça ne marchait pas, et pourquoi je le comprends encore moins maintenant que ça marche.

    De toute façon, je pense que vu ce dans quoi je m'embarque je n'ai pas finis d'en rencontrer des choses étranges qui devraient marcher et qui ne marchent pas ^^ En parlant de ça je bloque sur quelque chose donc je vais probablement réapparaître dans un nouveau post mais pas avant d'avoir moi même retourner le problème dans tout les sens. En tout cas merci pour vos réponses rapides, bonne soirée à vous

  8. #8
    Expert confirmé

    Inscrit en
    Août 2006
    Messages
    3 963
    Détails du profil
    Informations forums :
    Inscription : Août 2006
    Messages : 3 963
    Par défaut
    Bonjour,
    Citation Envoyé par DridriLaBastos Voir le message
    ça pourrait jouer un rôle de signer ou pas ses variables ? Ça me semble assez étrange
    Évidemment que ça joue un rôle !

    Tu crois qu'on se serait donné la peine d'en avoir la possibilité si ça ne servait à rien ?

  9. #9
    Membre averti
    Homme Profil pro
    Étudiant
    Inscrit en
    Juillet 2014
    Messages
    18
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 28
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Juillet 2014
    Messages : 18
    Par défaut
    Citation Envoyé par droggo Voir le message
    Bonjour,

    Évidemment que ça joue un rôle !

    Tu crois qu'on se serait donné la peine d'en avoir la possibilité si ça ne servait à rien ?
    Non bien sûr je sais que ça ne sert pas à rien mais du point de vue du processeur ça reste une variable de 8bits, le nombre qu'il soit négatif ou pas c'est juste une interprétation des bits de cette variable si je met 0b10001001 dans un octet soit je le considère comme non signé et il vaut 137 soit je le considère comme signé et il vaut -119, mais c'est toujours les mêmes bits utilisés et par exemple pour de la mémoire vidéo la valeur 0b10001001 ça voudrait dire afficher le caractère en sur exposition, en le faisant clignoter, sans fond et de couleur bleu, et que je choisisse ensuite de considérer ce nombre comme signé (donc valant 137) ou non signé (et valant -119) ça ne change pas la valeur qu'il y a dans la RAM, du coup je ne voit pas en quoi utilisé des chars signé ou non change quelque chose dans ce cas là, il doit donc y avoir quelque chose qui m'a échappé dans le doc d'intel sur le codage des nombres vus qu'utiliser des nombres non signés plutôt que signés ça a tout débloqué (même si je trouve quand même ça étrange)

  10. #10
    Expert éminent

    Femme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2007
    Messages
    5 202
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Juin 2007
    Messages : 5 202
    Par défaut
    On recommence:
    Tu codes en C.
    En C, les types signés et non signés sont différents. Le compilateur fais des choses spéciales pour les traiter différemment.
    Donc, te tromper dans le choix provoque des incompréhensions.

    Pire, certaines opérations sont des comportements indéfinis (undefined behaviour = UB) qui autorisent le compilateur à faire ce qu'il veut.
    A savoir: ce qu'on peut espérer, rien, autre chose, invoquer un démon dans ton nez ou effacer ton disque dur ou pire, faire n'importe quoi quand tu ne t'y attends pas, et sans raison apparente.

    Conclusion:
    C'est juste la raison du langage. Respecte les signes.

  11. #11
    Membre averti
    Homme Profil pro
    Étudiant
    Inscrit en
    Juillet 2014
    Messages
    18
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 28
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Juillet 2014
    Messages : 18
    Par défaut
    Aaaah ok, du coup c'est étrange que ça marche maintenant même alors que j'utilise des unsigned char, mais je vais tout repasser en char normale

  12. #12
    Expert éminent

    Femme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2007
    Messages
    5 202
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Juin 2007
    Messages : 5 202
    Par défaut
    Concernant les unsigned char, note que c'est le type à utiliser pour inspecter la mémoire brute (non typée).
    Ca doit fonctionner. C'est même le type dédié pour cela.
    Par contre, ca ne doit pas fonctionner avec signed char.

    Si le compilateur décide que char correspond à signed char, char non plus ne fonctionne pas. Comme ce n'est pas toi qui fait ce choix, tu ne peux pas te baser dessus.
    Utilise les unsigned char, c'est la bonne solution.


    Attention, tu as peut-être un autre soucis avec l'arithmétique de pointeurs.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    /* dans screen.h */
    #define VIDEO_RAM_START 0xB8000
     
    /* dans screen.c */
    void put_char (const uint8_t pchar, const uint8_t char_attr)
    {
        uint8_t* memory_ptr = (uint8_t*)(cursor_y * 160 + cursor_x * 2 + VIDEO_RAM_START);
    ...
    Pour commencer, j'utiliserai un typedef uint8_t videomemory_char .
    les constantes entieres sont d'un type qui n'est pas uint8_t*.

    Je te suggère d'utiliser ceci:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    /* dans screen.h */
    typedef unsigned char videomemomry_char;
    #define VIDEO_RAM_START ((videomemomry_char*)0xB8000)
     
    #define VIDEO_SCREEN_LINESIZE 80
    #define VIDEO_SCREEN_BLOCSIZE 2
     
    /* dans screen.c */
    void put_char (videomemomry_char const pchar, videomemomry_charc const char_attr)
    {
        videomemomry_char* memory_ptr = VIDEO_RAM_START + VIDEO_SCREEN_BLOCSIZE * (cursor_y * VIDEO_SCREEN_LINESIZE + cursor_x);
    ...
    Et comme ca devient très vite chiant à écrire, j'ajouterai une paire de fonction
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    videomemomry_char* screen_at(? line, ? pos) {
        return VIDEO_RAM_START + VIDEO_SCREEN_BLOCSIZE * (pos + VIDEO_SCREEN_LINESIZE*line);
    }
     
    videomemomry_char read_screen_at(? line, ? pos) { return *screen_at(line, pos); }
    Ce qui te permettra d'écrire putchar et getchar très simplement:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    void put_char (videomemomry_char const pchar, videomemomry_charc const char_attr)
    {
        videomemomry_char* memory_ptr = screen_at(cursor_y, cursor_x);
        memory_ptr[0] = pchar;
        memory_ptr[1] = char_attr;
    }

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Réponses: 1
    Dernier message: 20/04/2011, 17h03
  2. Réponses: 3
    Dernier message: 20/04/2008, 21h06
  3. Une formule qui ne veut pas fonctionner
    Par Maxence45 dans le forum Excel
    Réponses: 4
    Dernier message: 09/11/2007, 01h17
  4. [C#] Fonction comme MessageBox mais qui renvoie un string
    Par kinou dans le forum Windows Forms
    Réponses: 5
    Dernier message: 19/05/2006, 11h40
  5. Une table qui existe mais qui est inconnu! ?
    Par Nino dans le forum InterBase
    Réponses: 6
    Dernier message: 13/06/2003, 11h47

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