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 :

C création de fichier 16 bits *.COM sous DOS (Question: Hexadecimal)


Sujet :

C

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre confirmé

    Homme Profil pro
    Sans emploi
    Inscrit en
    Août 2019
    Messages
    76
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : Belgique

    Informations professionnelles :
    Activité : Sans emploi

    Informations forums :
    Inscription : Août 2019
    Messages : 76
    Par défaut C création de fichier 16 bits *.COM sous DOS (Question: Hexadecimal)
    Bonjour,

    Je viens de faire un petit programme en C qui crée un fichier COM pour MS-DOS / peut qu'il marche sur d'autre système DOS (testé sous MS-DOS 6.22).

    En premier lieu j'ai créé un programme COM minimal en assembleur qui s'ouvre et se ferme directement sous DOS sans rien faire d'autre.

    En visionnant le code hexadecimal de ce programme ça se résume à ceci:
    J'ai voullu pour étude créer un logiciel en C capable de générer ce même programme en se lancant.

    J'ai réussi au final a avoir un code similaire généré par mon programme C, cependant il y a 2 '0' en plus à la fin du fichier COM c.a.d ceci:
    A savoir j'utilise la fonction C fwrite() pour générer du code dans mon fichier en mode binaire.

    Voici le code source du programme en C capable de générer le fichier COM éxecutable.

    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
    #include <stdio.h>
    int main(void){
            int a=0;
            FILE *fp;
            char str[8];
            fp=fopen("file.com","wb");
     
            if (fp==NULL)
                    return -1;
            a=184; /*org 100*/
            fwrite (&a,sizeof(a),1,fp);
            a=52556;
            fwrite (&a,sizeof(a),1,fp);
            a=33;
            fwrite (&a,sizeof(a),1,fp);
            fclose(fp);
            return 0;
    }
    Dans l'exemple ici j'ai du faire quelques calcule pour tomber sur les chiffres en mode décimal pour correspondre aux chiffres hexadécimaux.
    Ce concernant je n'ai pas vraiment tout compris car j'ai du inverser les lettre 4C CD en C4 DC pour effectuer mon calcul final

    C*16^0 + 4*16^1 + D*16^2 + C*16^3 = 4CCD (C'est ce que je n'ai pas compris car c'est inversé par paire)
    12+64+3328+49152=52556

    21h = 33

    Si vous pouvez m'explique la raison pour laquelle j'ai du inverser les lettres pour le calcul de 4CCD?

    Aussi pourquoi fwrite() place 00 à la fin de mon fichier COM? Est-ce impossible d'omettre ce '00'?

    Cependant le fichier COM final s'execute correctement.

  2. #2
    Membre expérimenté

    Homme Profil pro
    Enseignant
    Inscrit en
    Septembre 2012
    Messages
    330
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : Enseignant
    Secteur : Enseignement

    Informations forums :
    Inscription : Septembre 2012
    Messages : 330
    Par défaut
    Je pense que cela est lié à "l'endianness"... les "processeurs" lisent les informations dans les registres en fonction du poids le plus fort (Big Endian) ou du poids le plus faible (Little Endian)
    Maintenant j'ignore si à la compilation il est possible de modifier cet "endianness"...

    Concernant fwrite() je suis pas certain que ce soit la bonne fonction à utiliser (essaie write() tout court) -- peut-être qu'elle ajoute le '\0' de fin de chaîne.

  3. #3
    Modérateur
    Avatar de Obsidian
    Homme Profil pro
    Chercheur d'emploi
    Inscrit en
    Septembre 2007
    Messages
    7 489
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Chercheur d'emploi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2007
    Messages : 7 489
    Par défaut
    Bonjour !

    Citation Envoyé par Kitsune64 Voir le message
    Si vous pouvez m'explique la raison pour laquelle j'ai du inverser les lettres pour le calcul de 4CCD?
    C'est effectivement lié à l'endianess ou « boutisme » en français.

    Les processeurs Motorola sont typiquement grand-boutistes (6809, 68000…), ce qui est une des raisons qui les rendaient plus faciles et donc plus populaires auprès des jeunes programmeurs (que nous étions quand on pouvait encore faire de l'assembleur de façon sérieuse) là où les Intel, dont le x86, sont généralement petit-boutistes.

    La raison à cela est que les données au format grand-boutiste sont plus faciles à lire par le programmeur quand on explore un dump hexadécimal (donc sommes toutes relativement rarement) alors que le format petit-boutiste est beaucoup plus facile à traiter pour les machines et peut, dans une certaine mesure, améliorer les performances et rendre un processeur sensiblement plus rapide à technologie équivalente. Cela est dû au fait qu'en déposant les octets de poids faible d'abord, les octets qui occupent une même position au sein d'un registre de longueur arbitraire occupent également la même place en mémoire. Par exemple, les valeurs « CD », « 45CD » et « 3B2F45CD » se retrouvent codées en mémoire :

    CD
    CD 45
    CD 45 2F 3B
    … ce qui permet en fait au microprocesseur d'utiliser les mêmes mécanismes pour remplir les registres 8 bits, 16 bits, 32 bits ou plus larges encore, en se contentant de s'arrêter quand le registre est rempli.

    C'est d'ailleurs ce que tu vois dans ton premier exemple. Dans la série B8 00 4C CD 21, B8 00 4C correspond à MOV AX,4c00h, qui dépose dans AH le code 4Ch qui indique au DOS que le programme prend fin, et dans AL la valeur 00, qui est en fait le paramètre de l'opération et qui, ici, correspond à la valeur de retour renvoyée et retournée à la ligne de commande ou au script BAT s'il existe. C'est cette valeur qui est renvoyée par return dans main ou par exit() quand on travaille en langage C.

    Les codes CD 21, quant à eux, correspondent à int 21h.

    J'ai réussi au final a avoir un code similaire généré par mon programme C, cependant il y a 2 '0' en plus à la fin du fichier COM c.a.d ceci:
    Je ne sais pas pourquoi le compilateur ajoute un zéro mais il est déjà assez remarquable qu'il ne s'en tienne qu'à ça. D'habitude, même avec la meilleure volonté du monde, les compilateurs remplissent les petits fichiers de données inutiles. Le bénéfice se fait sentir à plus grande échelle.

    Ce zéro peut correspondre à n'importe quoi : une sentinelle pour détecter la fin des données, une place réservée pour insérer un hook à l'usage du débogueur, une manière de séparer le code chargé en mémoire de ce qui s'y trouvait avant ou, parfois, du padding (rembourrage) pour aligner la prochaine instruction sur une adresse multiple de la taille du bus (mais ça ne semble pas être le cas ici).

  4. #4
    Membre Expert
    Femme Profil pro
    ..
    Inscrit en
    Décembre 2019
    Messages
    691
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Âge : 95
    Localisation : Autre

    Informations professionnelles :
    Activité : ..

    Informations forums :
    Inscription : Décembre 2019
    Messages : 691
    Par défaut
    Salut,

    Citation Envoyé par Obsidian Voir le message
    Ce zéro peut correspondre à n'importe quoi
    C'est parce que le int est codé ici sur 2 octets,
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    0x00B8 devient B8 00 en mémoire, fwrite ecrit B8 00
    0x4CCD devient CD 4C en mémoire, fwrite ecrit CD 4C
    0x0021 devient 21 00 en mémoire, fwrite ecrit 21 00

  5. #5
    Modérateur
    Avatar de Obsidian
    Homme Profil pro
    Chercheur d'emploi
    Inscrit en
    Septembre 2007
    Messages
    7 489
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Chercheur d'emploi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2007
    Messages : 7 489
    Par défaut
    Citation Envoyé par kaitlyn Voir le message
    C'est parce que le int est codé ici sur 2 octets,
    Ah oui ! En effet, j'ai lu un peu trop vite. Ce n'est pas la compilation d'un programme C qui a donné directement lieu à ce fichier objet mais c'est le résultat de son générateur qui, lui, est écrit en C.

    Bien vu.

  6. #6
    Membre confirmé

    Homme Profil pro
    Sans emploi
    Inscrit en
    Août 2019
    Messages
    76
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : Belgique

    Informations professionnelles :
    Activité : Sans emploi

    Informations forums :
    Inscription : Août 2019
    Messages : 76
    Par défaut
    Merci pour toutes ces infos ça éclaircit pas mal de choses concernant le code de ce post.

    Citation Envoyé par kaitlyn Voir le message
    Salut,
    C'est parce que le int est codé ici sur 2 octets,

    0x0021 devient 21 00 en mémoire, fwrite ecrit 21 00[/CODE]
    Je tournais autour de ce problème tout à l'heure, je pense que je dois passer vers un unsigned char...Pour coder par un seul octet; peut être.
    J'ai croisé un code source tout à l'heure qui indiquais d'utiliser unsigned char avec fwrite pour l'écriture en binaire. Sauf que mon compilateur ne gère pas par défaut ce type de déclaration.
    Je pense que je vais devoir définir (si j'y arrive avec ce compilateur) ce qu'est un unsigned char.

    Concernant le compilateur utilisé:
    Pour information, j'utilisais le compilateur SubC cette fois. Ce choix est du au fait que c'est un de seul compilateur pour le langage C dans le domaine publique.
    La dernière version que j'ai trouvée compilée pour DOS est de 2014, il gère la norme C89 normalement mais est en phase expérimentale dans sa version DOS

    ---Réédition---

    Ca marche avec simplement un char à la place du int cette histoire de zero...Sous DOS donc et avec ce compilateur, donc je ne sais pas si Turbo C réagirai de la même manière par exemple.

    Le dernier code:
    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
    #include <stdio.h>
     
    void xfile(char a,FILE *fp);
     
    int main(void){
            FILE *fp;
     
            printf("%d\n",sizeof(int));   /* 2 (octets) */
            printf("%d\n",sizeof(char));  /* 1 (octet) */
     
            fp=fopen("file.com","wb");
     
            if (fp==NULL)
                    return -1;
     
            xfile(184,fp); /* B8 */
            xfile(0,fp);   /* 00 */
            xfile(76,fp);  /* 4C */
            xfile(205,fp); /* CD */
            xfile(33,fp);  /* 21 */
     
            fclose(fp);
            return 0;
    }
     
    void xfile(char a,FILE *fp){
            fwrite(&a,sizeof(a),1,fp);
    }
    C'est plus simple en codant sur un seul octet en revanche ça demande 2 fois plus l'utilisation de la fonction fwrite(). Et donc je n'ai plus 00 a la fin du fichier généré...Encore merci!

  7. #7
    Membre Expert
    Femme Profil pro
    ..
    Inscrit en
    Décembre 2019
    Messages
    691
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Âge : 95
    Localisation : Autre

    Informations professionnelles :
    Activité : ..

    Informations forums :
    Inscription : Décembre 2019
    Messages : 691
    Par défaut
    Citation Envoyé par Kitsune64 Voir le message
    donc je ne sais pas si Turbo C réagirai de la même manière par exemple.
    Dans la mesure où les compilateurs répondent au même standard, ce sera pareil.
    djgpp et open watcom peuvent vraisemblablement générer des exécutables pour ms-dos. Attention à bien télécharger sur les sites officiels.
    Sinon, pour ce que tu tentes de faire, tu peux écrire quelque chose comme

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    unsigned char buffer[]= {0xB8, 0x00, 0x4C, 0xCD, 0x21};
    /* ... */
    fwrite(buffer, 1, sizeof buffer, fp);  /* ou plus généralement:
    fwrite(buffer, sizeof buffer[0], sizeof buffer / sizeof buffer[0], fp);
    */

  8. #8
    Membre confirmé

    Homme Profil pro
    Sans emploi
    Inscrit en
    Août 2019
    Messages
    76
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : Belgique

    Informations professionnelles :
    Activité : Sans emploi

    Informations forums :
    Inscription : Août 2019
    Messages : 76
    Par défaut
    Merci pour le raccourcis, ça simplifiera grandement la mise en place d'écrire ainsi.

    Je vais d’abord essayer ta portion de code sur SubC pour le moment. unsigned char ne passe pas sur celui-ci, simplement char ce qui correspond a un seul octet via ce compilateur.

    DJGPP, je l'aimais bien, mais je ne pense pas qu'il génère des programme de base en mode réel (16bits);il faut un extenseur mémoire DPMI de souvenir.
    Je (re)ferai des tests avec ce compilateur pour en avoir le cœur net.

Discussions similaires

  1. Fichiers d'aide .hlp sous windows 8.1 64 bits
    Par gaby277 dans le forum Windows 8
    Réponses: 0
    Dernier message: 26/12/2014, 10h38
  2. renommer des fichiers avec 4 décimales sous dos
    Par gundorf dans le forum Scripts/Batch
    Réponses: 2
    Dernier message: 17/06/2012, 10h33
  3. Réponses: 2
    Dernier message: 28/02/2010, 19h19
  4. Réactiver le port com sous DOS
    Par Poisson Rouge dans le forum Windows
    Réponses: 7
    Dernier message: 28/12/2005, 13h59
  5. Désenregistrement d'Objets COM sous Windows
    Par barthelv dans le forum Windows
    Réponses: 2
    Dernier message: 21/05/2003, 15h11

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