Question

Comment fait-on cela?

Si je veux analyser comment quelque chose est en train d'être compilé, comment pourrais-je obtenir le code d'assembly émis?

Était-ce utile?

La solution

Utilisez l'option -S pour gcc (ou g ++).

gcc -S helloworld.c

Ceci exécutera le préprocesseur (cpp) sur helloworld.c, effectuera la compilation initiale, puis s'arrêtera avant l'exécution de l'assembleur.

Par défaut, le fichier helloworld.s sera généré. Le fichier de sortie peut toujours être défini à l'aide de l'option -o .

gcc -S -o my_asm_output.s helloworld.c

Bien sûr, cela ne fonctionne que si vous avez la source originale. Si vous ne disposez que du fichier objet résultant, vous pouvez également utiliser objdump , en définissant l'option - disassemble (ou -d pour le code abrégé. formulaire).

objdump -S --disassemble helloworld > helloworld.dump

Cette option fonctionne mieux si l'option de débogage est activée pour le fichier objet ( -g au moment de la compilation) et que le fichier n'a pas été supprimé.

L'exécution de fichier helloworld vous indiquera le niveau de détail que vous obtiendrez en utilisant objdump.

Autres conseils

Ceci générera le code asm avec le code C + les numéros de ligne entrelacés pour voir plus facilement quelles lignes génèrent quel code.

# create assembler code:
c++ -S -fverbose-asm -g -O2 test.cc -o test.s
# create asm interlaced with source lines:
as -alhnd test.s > test.lst

Trouvé dans Algorithmes pour les programmeurs , page 3 (qui est la 15ème page globale de le PDF).

La ligne de commande suivante provient de de Christian Garbin blog

g++ -g -O -Wa,-aslh horton_ex2_05.cpp >list.txt

J'ai exécuté G ++ à partir d'une fenêtre DOS sous Win-XP, avec une routine contenant une conversion implicite

c:\gpp_code>g++ -g -O -Wa,-aslh horton_ex2_05.cpp >list.txt
horton_ex2_05.cpp: In function `int main()':
horton_ex2_05.cpp:92: warning: assignment to `int' from `double'

La sortie est un code généré assemblé qui est remplacé par le code C ++ d'origine (le code C ++ est affiché sous forme de commentaires dans le flux asm généré)

  16:horton_ex2_05.cpp **** using std::setw;
  17:horton_ex2_05.cpp ****
  18:horton_ex2_05.cpp **** void disp_Time_Line (void);
  19:horton_ex2_05.cpp ****
  20:horton_ex2_05.cpp **** int main(void)
  21:horton_ex2_05.cpp **** {
 164                    %ebp
 165                            subl $128,%esp
?GAS LISTING C:\DOCUME~1\CRAIGM~1\LOCALS~1\Temp\ccx52rCc.s
166 0128 55                    call ___main
167 0129 89E5          .stabn 68,0,21,LM2-_main
168 012b 81EC8000      LM2:
168      0000
169 0131 E8000000      LBB2:
169      00
170                    .stabn 68,0,25,LM3-_main
171                    LM3:
172                            movl <*>,-16(%ebp)

Utilisez le commutateur -S

g++ -S main.cpp

ou aussi avec gcc

gcc -S main.c

Voir aussi this

Si ce que vous voulez voir dépend de la liaison de la sortie, alors objdump sur le fichier objet / exécutable de sortie peut également être utile en plus du gcc -S susmentionné. Voici un script très utile de Loren Merritt qui convertit la syntaxe par défaut objdump en syntaxe plus lisible: nasm:

#!/usr/bin/perl -w
$ptr='(BYTE|WORD|DWORD|QWORD|XMMWORD) PTR ';
$reg='(?:[er]?(?:[abcd]x|[sd]i|[sb]p)|[abcd][hl]|r1?[0-589][dwb]?|mm[0-7]|xmm1?[0-9])';
open FH, '-|', '/usr/bin/objdump', '-w', '-M', 'intel', @ARGV or die;
$prev = "";
while(<FH>){
    if(/$ptr/o) {
        s/$ptr(\[[^\[\]]+\],$reg)/$2/o or
        s/($reg,)$ptr(\[[^\[\]]+\])/$1$3/o or
        s/$ptr/lc $1/oe;
    }
    if($prev =~ /\t(repz )?ret / and
       

Si ce que vous voulez voir dépend de la liaison de la sortie, alors objdump sur le fichier objet / exécutable de sortie peut également être utile en plus du gcc -S susmentionné. Voici un script très utile de Loren Merritt qui convertit la syntaxe par défaut objdump en syntaxe plus lisible: nasm:

<*>

Je suppose que cela peut également être utilisé sur la sortie de gcc -S.

=~ /\tnop |\txchg *ax,ax$/) { # drop this line } else { print $prev; $prev =

Si ce que vous voulez voir dépend de la liaison de la sortie, alors objdump sur le fichier objet / exécutable de sortie peut également être utile en plus du gcc -S susmentionné. Voici un script très utile de Loren Merritt qui convertit la syntaxe par défaut objdump en syntaxe plus lisible: nasm:

<*>

Je suppose que cela peut également être utilisé sur la sortie de gcc -S.

; } } print $prev; close FH;

Je suppose que cela peut également être utilisé sur la sortie de gcc -S.

Eh bien, comme tout le monde l’a dit, utilisez l’option -S. Si vous utilisez l'option -save-temps, vous pouvez également obtenir un fichier prétraité ( .i), un fichier d'assemblage ( .s) et un fichier objet (*. O). (obtenez chacun d’eux en utilisant -E, -S et -c.)

Comme tout le monde l’a fait remarquer, utilisez l’option -S pour GCC. J'aimerais également ajouter que les résultats peuvent varier (énormément!) Selon que vous ajoutez ou non des options d'optimisation ( -O0 pour aucune, -O2 pour une optimisation agressive) .

Sur les architectures RISC en particulier, le compilateur va souvent transformer le code presque au-delà de la reconnaissance en faisant de l'optimisation. C'est impressionnant et fascinant de regarder les résultats!

Comme mentionné précédemment, regardez le drapeau -S.

Cela vaut également la peine de regarder la famille de drapeaux '-fdump-tree', en particulier '-fdump-tree-all', qui vous permet de voir certaines formes intermédiaires de gcc. Celles-ci sont souvent plus lisibles que l’assembleur (du moins pour moi) et vous permettent de voir le fonctionnement des passes d’optimisation.

Utilisez l'option -S:

gcc -S program.c

Si vous recherchez un assemblage LLVM:

llvm-gcc -emit-llvm -S hello.c

Je ne vois pas cette possibilité parmi les réponses, probablement parce que la question date de 2008, mais en 2018, vous pouvez utiliser le site Web en ligne de Matt Goldbolt, https://godbolt.org

Vous pouvez également localement cloner et exécuter son projet https://github.com/mattgodbolt/compiler- explorateur

De: http://www.delorie.com/djgpp/v2faq/faq8_20 .html

gcc -c -g -Wa, -a, -ad [autres options GCC] foo.c > foo.lst

en alternative à la réponse de PhirePhly Ou utilisez simplement -S comme tout le monde le dit.

 Sortie de ces commandes

Voici les étapes à suivre pour voir / imprimer le code d'assemblage de tout programme C sur votre Windows

console / terminal / invite de commande:

  1. Ecrivez un programme C dans un éditeur de code C similaire à Codeblocks et enregistrez-le avec une extension .c

  2. Compilez et exécutez-le.

  3. Une fois exécuté avec succès, allez dans le dossier où vous avez installé votre compilateur gcc et donnez le

    commande suivante pour obtenir un fichier '.s' du fichier '.c'

    C: \ gcc > gcc -S chemin complet du fichier C ENTER

    Un exemple de commande (comme dans mon cas)

    C: \ gcc > gcc -S D: \ Aa_C_Certified \ alternate_letters.c

    Ceci génère un fichier '.s' du fichier '.c' d'origine

4. Après cela, tapez la commande suivante

C; \ gcc > cpp nomfichier.s ENTREE

Exemple de commande (comme dans mon cas)

C; \ gcc > cpp alternate_letters.s

Ceci imprimera / affichera le code de langue d'assemblage complet de votre programme C.

Utilisez " -S " Comme une option. Il affiche la sortie de l'assemblage dans le terminal.

récemment, je voulais connaître l'assemblage de chaque fonction dans un programme
Voici comment je l'ai fait.

$ gcc main.c                      // main.c source file
$ gdb a.exe                       // gdb a.out in linux
  (gdb) disass main               // note here main is a function
                                  // similary it can be done for other functions

-save-temps

Ceci a été mentionné à l'adresse https://stackoverflow.com/a/17083009/895245 , mais laissez-moi l'illustrer davantage . Quand vous faites:

gcc -save-temps -c -o main.o main.c

main.c

#define INC 1

int myfunc(int i) {
    return i + INC;
}

et maintenant, outre la sortie normale main.o , le répertoire de travail actuel contient également les fichiers suivants:

  • main.i est un bonus qui contient le fichier prépayé souhaité:

    # 1 "main.c"
    # 1 "<built-in>"
    # 1 "<command-line>"
    # 31 "<command-line>"
    # 1 "/usr/include/stdc-predef.h" 1 3 4
    # 32 "<command-line>" 2
    # 1 "main.c"
    
    
    int myfunc(int i) {
        return i + 1;
    }
    
  • main.s contient l'assemblage généré souhaité:

        .file   "main.c"
        .text
        .globl  myfunc
        .type   myfunc, @function
    myfunc:
    .LFB0:
        .cfi_startproc
        pushq   %rbp
        .cfi_def_cfa_offset 16
        .cfi_offset 6, -16
        movq    %rsp, %rbp
        .cfi_def_cfa_register 6
        movl    %edi, -4(%rbp)
        movl    -4(%rbp), %eax
        addl    $1, %eax
        popq    %rbp
        .cfi_def_cfa 7, 8
        ret
        .cfi_endproc
    .LFE0:
        .size   myfunc, .-myfunc
        .ident  "GCC: (Ubuntu 8.3.0-6ubuntu1) 8.3.0"
        .section    .note.GNU-stack,"",@progbits
    

Si vous souhaitez le faire pour un grand nombre de fichiers, utilisez plutôt:

 -save-temps=obj

qui enregistre les fichiers intermédiaires dans le même répertoire que la sortie de l'objet -o au lieu du répertoire de travail actuel, évitant ainsi des conflits potentiels entre le nom de base et les noms de bases.

L'avantage de cette option sur -S est qu'il est facile de l'ajouter à n'importe quel script de construction, sans trop interférer dans la construction elle-même.

Un autre avantage de cette option est que vous ajoutez -v :

.
gcc -save-temps -c -o main.o -v main.c

il montre en fait les fichiers explicites utilisés à la place des horribles temporaires sous / tmp , il est donc facile de savoir exactement ce qui se passe, ce qui inclut les étapes de prétraitement / compilation / assemblage:

/usr/lib/gcc/x86_64-linux-gnu/8/cc1 -E -quiet -v -imultiarch x86_64-linux-gnu main.c -mtune=generic -march=x86-64 -fpch-preprocess -fstack-protector-strong -Wformat -Wformat-security -o main.i
/usr/lib/gcc/x86_64-linux-gnu/8/cc1 -fpreprocessed main.i -quiet -dumpbase main.c -mtune=generic -march=x86-64 -auxbase-strip main.o -version -fstack-protector-strong -Wformat -Wformat-security -o main.s
as -v --64 -o main.o main.s

Testé sous Ubuntu 19.04 amd64, GCC 8.3.0.

Voici une solution pour C utilisant gcc:

gcc -S program.c && gcc program.c -o output
  1. Ici, la première partie stocke la sortie d'assembly du programme dans le même nom de fichier que Programme, mais avec l'extension .s modifiée, vous pouvez l'ouvrir comme n'importe quel fichier texte normal.

  2. La deuxième partie compile votre programme pour son utilisation réelle et génère un exécutable pour votre programme avec un nom de fichier spécifié.

Le programme.c utilisé ci-dessus est le nom de votre programme et sortie est le nom de l'exécutable que vous souhaitez générer.

BTW c'est mon premier post sur StackOverFlow: -}

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top