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

Assembleur Discussion :

Compilateur asm, comment ça fonctionne ?


Sujet :

Assembleur

  1. #1
    Membre du Club
    Profil pro
    Inscrit en
    Juin 2005
    Messages
    309
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2005
    Messages : 309
    Points : 61
    Points
    61
    Par défaut Compilateur asm, comment ça fonctionne ?
    Bonjour, je sais en gros comment fonctionne les compilateurs, on fait une analyste syntaxique, grammaticale, etc pour transformer cela en assembleur, puis en code objet, puis en executable. En bref ce n'est que de la conversion de format de fichier en y ajoutant le nécessaire avec l'éditeur de liens.

    La ou je me pose des questions c'est pour les compilateurs assembleur, si je voudrais en écrire un, quelle est le format du code objet, est-ce qu'il y a un standard précis à respecter ? Ensuite comment savoir en quoi traduire les instructions asm en son équivalent binaire ?? Est-ce qu'il y a une liste quelque part ?

    Suite à cela, après avoir analysé le code source, transformé cela en une suite binaire, comment savoir quelle instruction doit aller ou dans le fichier objet ? (à moins qu'il y ait un format précis) Est-ce qu'on enregistre la conversion de façon séquentielle pour faire un gros fichier .o qui contient l'équivalent binaire du code source dans le même ordre que ça à été écrit ? Parce que ça revient au même, à moins bien sûr que par exemple l'instruction MOV sont équivalent binaire ne soit pas (4D4F56) soit 10011010100111101010110 mais autre chose. Dans mon exemple MOV == à '10011010100111101010110' selon le code ascii, est-ce que le cpu respecte la norme ascii ?

    merci de m'éclairer sur ces points

  2. #2
    Membre régulier
    Profil pro
    Conseil - Consultant en systèmes d'information
    Inscrit en
    Juillet 2004
    Messages
    89
    Détails du profil
    Informations personnelles :
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Conseil - Consultant en systèmes d'information

    Informations forums :
    Inscription : Juillet 2004
    Messages : 89
    Points : 106
    Points
    106
    Par défaut
    La doc Intel donne toutes les infos
    Mais sache que c'est plutot long à écrire un compilo (et à lire la doc aussi d'ailleur )

    Liens (La doc est en 3 tomes): http://search2.intel.com/corporate/default.aspx?as_sitesearch=www.intel.com/design/pentiumii/manuals&q=Basic+architecture&num=10&restrict=en-US&filter=1&ie=utf8&oe=utf8&lr=&UserQuery=Basic+architecture&site=main&client=main&output=xml_no_dtd&ip=10.18.11.70&access=p

  3. #3
    Membre du Club
    Profil pro
    Inscrit en
    Juin 2005
    Messages
    309
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2005
    Messages : 309
    Points : 61
    Points
    61
    Par défaut
    Ok, je vais me lancer à la lecture

  4. #4
    Membre actif Avatar de amaury pouly
    Profil pro
    Inscrit en
    Décembre 2002
    Messages
    157
    Détails du profil
    Informations personnelles :
    Âge : 34
    Localisation : France

    Informations forums :
    Inscription : Décembre 2002
    Messages : 157
    Points : 224
    Points
    224
    Par défaut
    bonjour,
    d'abord, un compilo assembleur est différent d'un compilo C++ ou C surtout parce que le code qu'il doit transformer en fichier objet est SPECIFIQUE à la PLATEFORME(donc au processeur ou plutôt les familles de processeur) . Ainsi, un compilo pour assembleur x86 ne peut pas produire un exécutable pour ppc ou Mac . Et encore, dans la famille x86(Pentium+ donc çà fait vieux) chaque nouveau processeur apporte des fonctionnalité: SSE,SSE2,3DNow!(AMD),SSE3 même ainsi que d'autres instructions pour facilité la programmation(systenter,sysexit,sysfastcall) . Chaque instruction possible ENORMEMMENT de variante . Je te conseille de téléchager le manuel d'lntel . Les volumes 2A et 2B suffisent à eux deux(donc à peu près 2.5Mo) pour décrire toutes les instruction standard x86(il existe pour d'autre familles) ainsi que SSE,SSE2 .

    Donc chaque instruction pour un processeur(ou une famille: je le répèterais pas) possède un ou deux octet qui permettent au processeur de savoir que c'est elle . Puis selon l'instruction(c'est très spécifique de chacun) peut suivre un octet complémentaire si la source ou l'opérande est un registre(donc la moitié du temps) puis si nécessaire l'adresse ou la valeur littéral(là encore c'est indiqué dans le code de l'instruction si c'est une adresse ou une valeur) .

    Autant te dire que écrire un assembleur COMPLET est une tâche draconienne car rien de pour l'instruction mov ou add il doit exister 10 variantes binaires .

    Après le fichier objet possède un format spécifique(entre autres: sections de code,relocation,données,...) mais c'est surtout la partie .text et .data qui importe .

    Ah dernier point, le processeur CONNAIT PAS LE ASCII !!! Le processeur il connait QUE LES BITS ET OCTETS !
    Quand il interprète l'instruction, il le fait par octet:
    (je sais pas s'il fait comme çà mais c'est comme çà qu'on devrait faire je pense)
    ->lire le premier octet
    ->on sait quel instruction on traite
    ->lire l'octet suivant(en général c'est un octet d'info)
    ->si opérande=registre
    ->si opérande contenu dans octet, charger opérande
    ->sinon lire l'octet suivant et en déduire l'opérande
    ->lire les n octet suivant(dépend si c'est du 16/32/64-bits) et les interpréter comme une valeur ou une adresse .

    Evidemment chaque instruction à son agencememnt mais certains partie reviennent .

    Bonne chance

  5. #5
    Membre du Club
    Profil pro
    Inscrit en
    Juin 2005
    Messages
    309
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2005
    Messages : 309
    Points : 61
    Points
    61
    Par défaut
    Ok

    Mais ça veut dire que lorsqu'on code un secteur de boot et un kernel, bref tout ce qui est indépendant d'un OS, on doit le coder dans un format bin pure ?

    j'ai prit un exemple d'un secteur de boot et j'essaie de le décortiquer avec hex workshop, mais je n'arrive pas à repérer le code la dedans, j'essaye de trouver dans les docs de intel la liste des équivalent binaire des opcodes, mais je ne les trouve pas, ils sont dans le volume 1 2 ou 3 ?

    De plus cel m'amène à beaucoup de question, le code en question du boot secteur avec les questions dessus je l'ai posté dans mon autre topic sur [OS] qu'est-ce qu'on doit recoder pour un nouvel OS.

    Si tu pourrais aller jeter un oeil et éclairer ma lanterne ce serait sympa

    Donc le format COFF de Microsoft sert uniquement pour créer les exécutable PE Win32 ?

  6. #6
    Membre actif Avatar de amaury pouly
    Profil pro
    Inscrit en
    Décembre 2002
    Messages
    157
    Détails du profil
    Informations personnelles :
    Âge : 34
    Localisation : France

    Informations forums :
    Inscription : Décembre 2002
    Messages : 157
    Points : 224
    Points
    224
    Par défaut A
    en effet dans le cas d'un bootloader ou d'un kernel on doit créer un binaire pur(encore que pour le kernel on n'est pas obligé) donc pas de sections, juste le code . Pour le désassembler tu peux utiliser ndisasm(distribuer avec NASM) qui désassemble du binaire pur .
    Le format coff est surtout utile pour gérer les import, export, extern bref tout ce qui touche à la programmation en plusieur fichiers . Il permet l'utilisation de section(.text .data .reloc ....) . Néanmoins, on peut programmer un jernel en plusieur fichier, générer des fichiers .o et les lier avec ld(je parle pour gcc) et obtenir un binaire pur . Le format COFF est surotut un format intermédiaire pratique. Il est utile pour tout OS et beaucoup de format d'exécutable(même si les donnée sont pas positionnée pareil) .

    Pour la liste des opcode, la doc d'intel le précise dans A-32 Architecture Software Developper's Manuel vol 2B, à la 33ème page . tu verras c'est bien expliqué .

    Pour ce qui est de l'autre topic j'ai pas le temps d'aller voir maintenant .

  7. #7
    Membre du Club
    Profil pro
    Inscrit en
    Juin 2005
    Messages
    309
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2005
    Messages : 309
    Points : 61
    Points
    61
    Par défaut
    Ok merci beaucoup

    Quand tu auras le temps, si ça ne te dérange pas, j'aimerais vraiment qu'on passe en revue le code, car j'aime bien comprendre ce que je programmes et comme c'est un OS en plus je veux pas faire comme Microsoft et voir que ça fonctionne un peu pour me contenter mais j'aime comprendre tout ce qui se passe

  8. #8
    Membre éclairé
    Profil pro
    Inscrit en
    Juillet 2002
    Messages
    842
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2002
    Messages : 842
    Points : 696
    Points
    696
    Par défaut
    Citation Envoyé par amaury pouly
    bonjour,
    d'abord, un compilo assembleur est différent d'un compilo C++ ou C surtout parce que le code qu'il doit transformer en fichier objet est SPECIFIQUE à la PLATEFORME
    Ah bon, et pas le compilateur C ?

    Autant te dire que écrire un assembleur COMPLET est une tâche draconienne car rien de pour l'instruction mov ou add il doit exister 10 variantes binaires .
    Ce n'est pas pour cela que c'est dix fois plus compliqué. Un assembleur est bien plus simple qu'un compilateur.

    Après le fichier objet possède un format spécifique(entre autres: sections de code,relocation,données,...) mais c'est surtout la partie .text et .data qui importe .

    ->lire le premier octet
    ->on sait quel instruction on traite
    ->lire l'octet suivant(en général c'est un octet d'info)
    ->si opérande=registre
    ->si opérande contenu dans octet, charger opérande
    ->sinon lire l'octet suivant et en déduire l'opérande
    ->lire les n octet suivant(dépend si c'est du 16/32/64-bits) et les interpréter comme une valeur ou une adresse .
    Oui, enfin... c'est un peu plus compliqué. Il y a des extension d'opérande dans le mod r/m, ou des instruction sur deux octets. Il y a également un octet supplémentaire pour l'adressage 32 bits, et les n octets suivants il peut y avoir plus qu'une chose. Ca peut être les octets d'adressage, mais aussi une valeur immédiate.

  9. #9
    Membre du Club
    Profil pro
    Inscrit en
    Juin 2005
    Messages
    309
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2005
    Messages : 309
    Points : 61
    Points
    61
    Par défaut
    Salut

    Justement c'est quoi le mod R/M ? j'ai essayé de comprendre ça en lisant le volume 2A mais j'ai de la misère à faire la différence entre ça et un mnémonique simpe comme Mov par exemple.

    Si un opcode est sur 2 octets, il peut pas y avoir plus que 65536 opcodes alors ??

  10. #10
    Membre à l'essai
    Profil pro
    Inscrit en
    Mai 2005
    Messages
    10
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2005
    Messages : 10
    Points : 12
    Points
    12
    Par défaut
    Bonjour,

    pour bien comprendre, il faut lire :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    IA-32 Intel® Architecture
    Software Developer’s
    Manual
    Volume 2:
    Instruction Set Reference
    le chapitre 2 donne les formats des instructions et le chapitre 3 tous les opcodes.

    MOV n'est pas l'exemple le plus simple.
    En se limitant au 8 bits (je considère que l'on se place dans un contexte 32 bits pour les adresses), on peut avoir :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    mov reg8, reg8 ; exemple mov bl, ch
    mov reg8, imm ; exemple mov bl, 0xc5
    mov [mem], reg8 ; exemple mov [label], ah
    mov reg8, [mem] ; exemple mov dl, [eax+8]
    On dispose de :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    88 /r MOV r/m8,r8 Move r8 to r/m8
    8A /r MOV r8,r/m8 Move r/m8 to r8
    B0+ rb MOV r8,imm8 Move imm8 to r8
    C6 /0 MOV r/m8,imm8 Move imm8 to r/m8
    et
    A0 MOV AL,moffs8* Move byte at (seg:offset) to AL
    A2 MOV moffs8*,AL Move AL to (seg:offset)
    Premièrement, on constate qu'une même instruction peut parfois être codée de plusieurs manières.

    ne peut se coder qu'avec :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    88 /r MOV r/m8,r8 Move r8 to r/m8
    mais
    peut se coder avec :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    88 /r MOV r/m8,r8 Move r8 to r/m8
    ou
    A2 MOV moffs8*,AL Move AL to (seg:offset)
    De même :
    peut se coder avec :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    88 /r MOV r/m8,r8 Move r8 to r/m8
    ou
    8A /r MOV r8,r/m8 Move r/m8 to r8

    Exemple 1 :
    en utilisant :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    B0+ rb MOV r8,imm8 Move imm8 to r8
    Donc tout simplement un opcode suivi de la valeur 0xff.
    L'opcode s'obtient par : B0+ rb
    Il faut savoir qu'à tous les registres est associée une valeur de 0 à 7 donc codée sur 3 bits.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    AL=AX=EAX=MM0=XMM0=0=000
    CL=CX=ECX=MM1=XMM1=1=001
    DL=DX=EDX=MM2=XMM2=2=010
    BL=BX=EBX=MM3=XMM3=3=011
    AH=SP=ESP=MM4=XMM4=4=100
    CH=BP=EBP=MM5=XMM5=5=101
    DH=SI=ESI=MM6=XMM6=6=110
    BH=DI=EDI=MM7=XMM7=7=111
    Ici le registre de destination est bl, qui correspond à 3. 0xb0+0x03=0xb3 est donc l'opcode.
    On obtient l'instruction complète :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    0xb3 0xff ; mov bl, 0xff

    Exemple 2 :
    en utilisant :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    88 /r MOV r/m8,r8 Move r8 to r/m8
    Cette fois l'opcode est formé d'un seul byte 0x88, qui indique au CPU qu'il va devoir exécuter une instruction mov dont la source est un registre (ici ch) et dont la destination est soit un registre (R) soit un emplacement mémoire (M) en RAM (ici le registre bl).
    Pour préciser tout ça, l'opcode est suivi d'un byte ModR/M.
    Celui-ci va indiquer :
    1) si la destination est un registre ou un emplacement mémoire (Mod)
    2) quel est le registre source
    3) si la destination est un registre, lequel. Si la destination est emplacement mémoire, quel registre sert de base.

    1) est codé sur 2 bits. 2) est codé sur 3 bits. 3) est codé sur 3 bits.
    Donc un byte ModR/M est de la forme : * * | * * * | * * *.
    Ici la destination est un registre donc le mod est 1 1. (tableau page 2-6)
    Le registre source est ch qui correspond à 1 0 1.
    Le registre destination est bl qui correspond à 0 1 1.
    On obtient donc comme byte 1 1 | 1 0 1 | 0 1 1 = 0xeb. Comme l'indique directement le tableau page 2-6.
    On obtient l'instruction complète :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    0x88 0xeb; mov bl, ch
    Voilà pour un début.
    A bientôt.

  11. #11
    Membre du Club
    Profil pro
    Inscrit en
    Juin 2005
    Messages
    309
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2005
    Messages : 309
    Points : 61
    Points
    61
    Par défaut
    Merci

    Je comprends mieux maintenant

    Mais il y a encore quelques petits détails dont je me pose des questions. Si j'ai bien compris le Mod R/M n'est qu'un bit de plus. Mais quand je regarde mon code objet pur, tout est codé sur 8 bits. Donc ce bit est inclus dans un 8 bits ?

  12. #12
    Membre actif Avatar de amaury pouly
    Profil pro
    Inscrit en
    Décembre 2002
    Messages
    157
    Détails du profil
    Informations personnelles :
    Âge : 34
    Localisation : France

    Informations forums :
    Inscription : Décembre 2002
    Messages : 157
    Points : 224
    Points
    224
    Par défaut
    Mod R/M est un octet(byte) donc 8-bit . sinon on ne pourrait pas stocker toute ces infos .

  13. #13
    Membre du Club
    Profil pro
    Inscrit en
    Juin 2005
    Messages
    309
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2005
    Messages : 309
    Points : 61
    Points
    61
    Par défaut
    Ok je comprends

    Est-ce que tu voudrais bien m'aider à analyser ce source binaire pur ? C'est le source d'un petit bootloader, je voudrais arriver à trouver quelles sont les octets la dedans faisant partie de la première instruction ? Bon ça commence au début, mais ou ça se termine ? La première instruction du code est mov ax, 07C0h

    B8C0078ED88EC0B800808ED0BC00F0BE1700E81200EBFE48656C6C6F20776F726C6420210D0A005053AC3C007409B40EBB0700CD10EBF25B58C3

    avec une suite de 90909090 ...55AA

  14. #14
    sdx
    sdx est déconnecté
    Membre régulier Avatar de sdx
    Profil pro
    Inscrit en
    Janvier 2004
    Messages
    106
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2004
    Messages : 106
    Points : 90
    Points
    90
    Par défaut
    Salut !

    La première instruction est sur 3 octets, donc B8c007 (b8 = mov ax et c007 equivaut à 07c0 mais chez intel il aime bien compliquer le truc )

    La suite de 90, se sont des NOP ("no operation"), c'est à dire que ce code ne fait _rien_ (quand le proc trouve un NOP, il se contente d'incrémenter IP et de passer à la prochaine instruction)

    Le 55AA, c'est la signature d'un secteur de boot, mais en inversée (rapelle toi que tu est chez Intel !) comme 07c0 -> c007, aa55 -> 55aa


    le désassemblage est fastidieux 'à la main', essaie d'utiliser un debugger du genre TDebug, qui fait ça très bien

    courage!

  15. #15
    Membre à l'essai
    Profil pro
    Inscrit en
    Mai 2005
    Messages
    10
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2005
    Messages : 10
    Points : 12
    Points
    12
    Par défaut
    Bonjour,

    j'ai ajouté quelques labels pour rendre le code plus lisible.
    J'ai aussi traduit les sauts (qui sont relatifs) avec les labels.

    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
     
    b8c007               mov    ax, 7c0h
    8ed8                  mov    ds, ax
    8ec0                  mov    es, ax
    b80080               mov    ax, 8000h
    8ed0                  mov    ss, ax
    bc00f0                mov    sp, 0f000h
    be1700               mov    si, 17h ; = mov si data_txt
    e81200               call    +18 ; = call print
     
     
    loop:
    ebfe                  jmp    -2 ; = jmp loop
     
    data_txt: db 48  65  6c  6c  6f  20  
    	    ('H' 'e' 'l' 'l' 'o' ' ')
              db 77  6f  72  6c  64  20  21  0d   0a  00
    	    ('w' 'o' 'r' 'l' 'd' ' ' '!' '\r' '/n' 0)
     
     
    print:
    50                   push   ax
    53                   push   bx
    next:
    ac                   lodsb  
    3c00                cmp    al, 00h
    7409                jz     +9 ; = jz end
    b40e                mov    ah, 0eh
    bb0700            mov    bx, 07h
    cd10                int    10h
    ebf2                jmp    -14 ; = jmp next
    end:
    5b                   pop    bx
    58                   pop    ax
    c3                   ret
     
    90                   nop
    90                   nop
    .........................
    90                   nop
    90                   nop
     
    db 55 aa
    Après avoir fixé les registres de segments et configuré la pile,
    on affiche un message à l'aide d'une interuption bios et on entre
    dans une boucle infinie.

    A bientôt.

  16. #16
    Membre du Club
    Profil pro
    Inscrit en
    Juin 2005
    Messages
    309
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2005
    Messages : 309
    Points : 61
    Points
    61
    Par défaut
    Citation Envoyé par sdx
    Salut !

    La première instruction est sur 3 octets, donc B8c007 (b8 = mov ax et c007 equivaut à 07c0 mais chez intel il aime bien compliquer le truc )

    La suite de 90, se sont des NOP ("no operation"), c'est à dire que ce code ne fait _rien_ (quand le proc trouve un NOP, il se contente d'incrémenter IP et de passer à la prochaine instruction)

    Le 55AA, c'est la signature d'un secteur de boot, mais en inversée (rapelle toi que tu est chez Intel !) comme 07c0 -> c007, aa55 -> 55aa


    le désassemblage est fastidieux 'à la main', essaie d'utiliser un debugger du genre TDebug, qui fait ça très bien

    courage!
    Ok

    Mais si on inverse tout, le code ne devrait-il pas commencer par aa55 ? Ou si on inverse seulement les "couple" d'octets ??

    Quand le IP est incrémenté, comment le cpu fait pour savoir à quelle adresse est la prochaine instruction ? Car ici c'est un binaire pur, donc il passe tout ça octet par octet, mais encore la, j'imagine que tout les octets de ce bootloader ne doit pas être loadé en mémoire un octet à la suite des autres dans la même ordre non ? Dans ce cas il doit y avoir une sorte de liste chaînée d'adresse mémoire du code en quelque part .. dans la pile sans doute ?

  17. #17
    Membre du Club
    Profil pro
    Inscrit en
    Juin 2005
    Messages
    309
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2005
    Messages : 309
    Points : 61
    Points
    61
    Par défaut
    Citation Envoyé par zertur
    Bonjour,

    j'ai ajouté quelques labels pour rendre le code plus lisible.
    J'ai aussi traduit les sauts (qui sont relatifs) avec les labels.

    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
     
    b8c007               mov    ax, 7c0h
    8ed8                  mov    ds, ax
    8ec0                  mov    es, ax
    b80080               mov    ax, 8000h
    8ed0                  mov    ss, ax
    bc00f0                mov    sp, 0f000h
    be1700               mov    si, 17h ; = mov si data_txt
    e81200               call    +18 ; = call print
     
     
    loop:
    ebfe                  jmp    -2 ; = jmp loop
     
    data_txt: db 48  65  6c  6c  6f  20  
    	    ('H' 'e' 'l' 'l' 'o' ' ')
              db 77  6f  72  6c  64  20  21  0d   0a  00
    	    ('w' 'o' 'r' 'l' 'd' ' ' '!' '\r' '/n' 0)
     
     
    print:
    50                   push   ax
    53                   push   bx
    next:
    ac                   lodsb  
    3c00                cmp    al, 00h
    7409                jz     +9 ; = jz end
    b40e                mov    ah, 0eh
    bb0700            mov    bx, 07h
    cd10                int    10h
    ebf2                jmp    -14 ; = jmp next
    end:
    5b                   pop    bx
    58                   pop    ax
    c3                   ret
     
    90                   nop
    90                   nop
    .........................
    90                   nop
    90                   nop
     
    db 55 aa
    Après avoir fixé les registres de segments et configuré la pile,
    on affiche un message à l'aide d'une interuption bios et on entre
    dans une boucle infinie.

    A bientôt.
    Merci beaucoup pour cette traduction

    Mais dans le fichier binaire, comme je disais dans ma réplique précédente, tout cela est mit ensemble, comment le cpu sait que tel partie du code sont des instructions, la partie data_txt c'est une variable texte, etc ?

    Pour ce qui est de la traduction, est-ce que tu aurais l'aimabilité de m'expliquer comment tu as traduit cela avec la doc de Intel ?

    À quelles page tu as fait référence et quelles sont les tableaux dans la doc qu'on doit se servir pour cela ? J'imagine on prend dabord le premier octet, on consulte un tableau x, on voit que c'est un Mov, ensuite on prend le second octet on vérifie dans un autre tableau, on voit que c'est le registre ax et ainsi de suite ?

    J'imagine aussi que c'est de cette façon que l'on fait un désassembleur

    Dans le fond un désassembleur n'est pas très compliqué, enfin, pour désassembler du binaire pur, un exe Win32 PE ou Elf c'est une autre histoire, car le format est plus complexe :o

  18. #18
    sdx
    sdx est déconnecté
    Membre régulier Avatar de sdx
    Profil pro
    Inscrit en
    Janvier 2004
    Messages
    106
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2004
    Messages : 106
    Points : 90
    Points
    90
    Par défaut
    Ou si on inverse seulement les "couple" d'octets ??
    Tout à fait Tu inverses seulement les octets dans chaque mots, puis tu recommences avec les mots dans les doubles mots.

    Donc, si tu as
    tu vas avoir comme binaire :
    car b8 -> MOV AX; 66 -> Préfixe qui signifit que l'opérande est sur 32 bits; 78 56 34 12 -> 12345678 en notation 'classique'.

    Quand le IP est incrémenté, comment le cpu fait pour savoir à quelle adresse est la prochaine instruction ? Car ici c'est un binaire pur, donc il passe tout ça octet par octet, mais encore la, j'imagine que tout les octets de ce bootloader ne doit pas être loadé en mémoire un octet à la suite des autres dans la même ordre non ? Dans ce cas il doit y avoir une sorte de liste chaînée d'adresse mémoire du code en quelque part .. dans la pile sans doute ? Wink
    où vas tu chercher tout cela ... bien sur que non ! les opcodes sont rangés tous à la suite dans la mémoire. Les cpu les lit un à un (en théorie) et quand il finit l'execution d'une instruction, il incrémente IP (le pointeur d'instruction) de la taille de l'instruction qu'il pointe (il connait la taille de toutes les instructions, lui 8) )

    Le bootloader est chargé à l'adresse 0x07C00 (eqivalent de 07C0:0000 ou de 0000:07C00), donc la première instruction est à 07C00, les autres se suivent. Même si un humain est (presque) incapable de délimiter les instructions, le cpu en est capable, ainsi que les debuggers ou les logiciels de desassemblage.

    Il y a plein d'explications sur le sujet ici.

    @zertur -> Tu as utlisé un debugger ou tu as fait ça de tête ?

    Bonne continuation !

  19. #19
    sdx
    sdx est déconnecté
    Membre régulier Avatar de sdx
    Profil pro
    Inscrit en
    Janvier 2004
    Messages
    106
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2004
    Messages : 106
    Points : 90
    Points
    90
    Par défaut
    Mais dans le fichier binaire, comme je disais dans ma réplique précédente, tout cela est mit ensemble, comment le cpu sait que tel partie du code sont des instructions, la partie data_txt c'est une variable texte, etc ?
    Le cpu ne le sait pas : souvient toi toujours que le cpu est idiot. Il fait ce que tu lui demandes, c'est à toi de faire en sorte que les zones de code soient executées, et que les zones de données ne le soient pas !

    C'est déroutant quand on apprend l'assembleur, mais un même binaire peut être à la fois :
    • Une instruction
    • Une chaine de caractères ASCII
    • Une valeur entière
    • Une valeur flottante
    • ...

    Tu finiras par t'y faire : il n'y a aucune protection, tu es responsable de ton code (wow, je suis philosophe moi )

  20. #20
    Membre du Club
    Profil pro
    Inscrit en
    Juin 2005
    Messages
    309
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2005
    Messages : 309
    Points : 61
    Points
    61
    Par défaut
    Ok

    Mais pour que le IP soit incrémenté il doit connaître la taille de l'instruction qu'il pointe, alors si mon code démarre à 07C0h et que j'ai Mov ax, 12345678h le IP sera à 07C0h et après cette instruction il pointera à 07C0h + 6 octets :

    Si j'ai bien compris.

    Par contre, comment savoir si c'est un mot, un doube mot que l'on doit lire ??

    Tu dis que c'est moi qui décide ce qui est interprété comme du code, du texte, etc. ? Dans le sens ou les instructions sont exécuté selon ce que j'ai décidé ?

    Mais par exemple, en mémoire il y a la chaîne 'Hello World!' comment le cpu sait ou aller chercher cette chaîne en mémoire ? J'ai de la misère à visualiser, à comprendre comment il va chercher le premier jusqu'au dernier caractère avec l'instruction qui utilise le int pour afficher du texte à l'écran. Car si c'est loader en mémoire dans le même ordre, c'est un peu comme si j'allais fouiller dans le fichier sur le hdd, mais moi je sais à quel octet elle commence ma chaîne quand je regarde mon fichier boot.bin avec un éditeur hex, mais une fois en mémoire comment il le sait :

    Plus que quelques détails du genre et je suis en voie de comprendre pas mal de chose sur l'asm, ce topic deviendra une référence

Discussions similaires

  1. [Vs.Net & SQL Serveur] Comment faire fonctionner le Débu
    Par MoTUmBo dans le forum MS SQL Server
    Réponses: 1
    Dernier message: 31/08/2005, 19h23
  2. Comment faire fonctionner une scroll bar ???
    Par toto4650 dans le forum MFC
    Réponses: 10
    Dernier message: 18/07/2005, 16h47
  3. [JToolTip] comment ca fonctionne ?
    Par Terminator dans le forum Composants
    Réponses: 2
    Dernier message: 29/05/2005, 15h18
  4. [Chat] Comment faire fonctionner Flash 7 sous Debian ?
    Par piff62 dans le forum Evolutions du club
    Réponses: 22
    Dernier message: 07/03/2005, 15h27
  5. comment faire fonctionner l'exe sur une autre machine
    Par brian79 dans le forum C++Builder
    Réponses: 8
    Dernier message: 28/05/2004, 14h00

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