Je me demandais comment utiliser GCC sur mon fichier source C pour vider une version mnémonique du code machine afin que je puisse voir en quoi mon code était compilé. Vous pouvez le faire avec Java mais je n’ai pas trouvé de solution avec GCC.
J'essaie de réécrire une méthode C dans Assembly et voir comment GCC y parviendrait serait d'une grande aide.
Si vous compilez avec des symboles de débogage, vous pouvez utiliser objdump
pour produire un désassemblage plus lisible.
>objdump --help
[...]
-S, --source Intermix source code with disassembly
-l, --line-numbers Include line numbers and filenames in output
objdump -drwC -Mintel
is Nice:
-r
affiche les noms des symboles sur les relocalisations (vous verrez donc puts
dans l'instruction call
ci-dessous)-R
affiche les relocalisations/noms de symboles à liaison dynamique (utile dans les bibliothèques partagées)-C
démêle les noms de symbole C++-w
est le mode "Wide": il ne met pas à la ligne les octets de code machine-Mintel
: utilise la syntaxe .intel_syntax noprefix
de GAS/binutils de type MASM, à la place de AT & T-S
: entrelace les lignes source avec désassemblage.Vous pouvez mettre quelque chose comme alias disas="objdump -drwCS -Mintel"
dans votre ~/.bashrc
Exemple:
> gcc -g -c test.c
> objdump -d -M intel -S test.o
test.o: file format elf32-i386
Disassembly of section .text:
00000000 <main>:
#include <stdio.h>
int main(void)
{
0: 55 Push ebp
1: 89 e5 mov ebp,esp
3: 83 e4 f0 and esp,0xfffffff0
6: 83 ec 10 sub esp,0x10
puts("test");
9: c7 04 24 00 00 00 00 mov DWORD PTR [esp],0x0
10: e8 fc ff ff ff call 11 <main+0x11>
return 0;
15: b8 00 00 00 00 mov eax,0x0
}
1a: c9 leave
1b: c3 ret
J'aimerais ajouter à ces réponses que si vous donnez à gcc le drapeau -fverbose-asm
, l'assembleur qu'il émet sera beaucoup plus clair à lire.
Utilisez le commutateur -S (note: majuscule S) sur GCC, qui émettra le code d'assemblage dans un fichier portant l'extension .s. Par exemple, la commande suivante:
gcc -O2 -S foo.c
laissera le code d'assemblage généré sur le fichier foo.s.
Arraché directement de http://www.delorie.com/djgpp/v2faq/faq8_20.html (mais en supprimant les _ (codes erronés) -c
)
L'utilisation du commutateur -S
vers GCC sur les systèmes x86 génère une sauvegarde de la syntaxe AT & T, qui peut être spécifiée avec le commutateur -masm=att
, comme suit:
gcc -S -masm=att code.c
Alors que si vous souhaitez produire un cliché en syntaxe Intel, vous pouvez utiliser le commutateur -masm=intel
, comme suit:
gcc -S -masm=intel code.c
(Les deux produisent des dumps de code.c
dans leurs différentes syntaxes, dans le fichier code.s
respectivement)
Afin de produire des effets similaires avec objdump, vous souhaiterez utiliser le commutateur --disassembler-options=
intel
/att
, avec un exemple (avec des copies de code pour illustrer les différences de syntaxe):
$ objdump -d --disassembler-options=att code.c
080483c4 <main>:
80483c4: 8d 4c 24 04 lea 0x4(%esp),%ecx
80483c8: 83 e4 f0 and $0xfffffff0,%esp
80483cb: ff 71 fc pushl -0x4(%ecx)
80483ce: 55 Push %ebp
80483cf: 89 e5 mov %esp,%ebp
80483d1: 51 Push %ecx
80483d2: 83 ec 04 sub $0x4,%esp
80483d5: c7 04 24 b0 84 04 08 movl $0x80484b0,(%esp)
80483dc: e8 13 ff ff ff call 80482f4 <puts@plt>
80483e1: b8 00 00 00 00 mov $0x0,%eax
80483e6: 83 c4 04 add $0x4,%esp
80483e9: 59 pop %ecx
80483ea: 5d pop %ebp
80483eb: 8d 61 fc lea -0x4(%ecx),%esp
80483ee: c3 ret
80483ef: 90 nop
et
$ objdump -d --disassembler-options=intel code.c
080483c4 <main>:
80483c4: 8d 4c 24 04 lea ecx,[esp+0x4]
80483c8: 83 e4 f0 and esp,0xfffffff0
80483cb: ff 71 fc Push DWORD PTR [ecx-0x4]
80483ce: 55 Push ebp
80483cf: 89 e5 mov ebp,esp
80483d1: 51 Push ecx
80483d2: 83 ec 04 sub esp,0x4
80483d5: c7 04 24 b0 84 04 08 mov DWORD PTR [esp],0x80484b0
80483dc: e8 13 ff ff ff call 80482f4 <puts@plt>
80483e1: b8 00 00 00 00 mov eax,0x0
80483e6: 83 c4 04 add esp,0x4
80483e9: 59 pop ecx
80483ea: 5d pop ebp
80483eb: 8d 61 fc lea esp,[ecx-0x4]
80483ee: c3 ret
80483ef: 90 nop
godbolt est un outil très utile, leur liste n’a que des compilateurs C++ mais vous pouvez utiliser le drapeau -x c
pour le traiter en tant que code C. Il générera ensuite une liste Assembly pour votre code côte à côte et vous pouvez utiliser l’option Colourise
pour générer des barres de couleur afin d’indiquer visuellement le code source mappé sur l’Assemblée générée. Par exemple le code suivant:
#include <stdio.h>
void func()
{
printf( "hello world\n" ) ;
}
en utilisant la ligne de commande suivante:
-x c -std=c99 -O3
et Colourise
générerait ce qui suit:
Avez-vous essayé gcc -S -fverbose-asm -O source.c
puis avez-vous consulté le fichier assembleur source.s
généré?
Le code assembleur généré va dans source.s
(vous pouvez le remplacer par -o
nom_fichier_assembleur ); l'option -fverbose-asm
demande au compilateur d'émettre des commentaires d'assembleur "expliquant" le code assembleur généré. L'option -O
demande au compilateur d'optimiser un bit (il pourrait en optimiser davantage avec -O2
ou -O3
).
Si vous voulez comprendre ce que gcc
fait, essayez de passer -fdump-tree-all
mais soyez prudent: vous obtiendrez des centaines de fichiers de vidage.
BTW, GCC est extensible via plugins ou avec MELT (langage spécifique au domaine de haut niveau pour étendre GCC; que j'ai abandonné en 2017)
Vous pouvez utiliser gdb pour cela comme objdump.
Cet extrait est tiré de http://sources.redhat.com/gdb/current/onlinedocs/gdb_9.html#SEC64
Voici un exemple montrant une source mixte + Assembly pour Intel x86:
(gdb) disas/m main Dump du code assembleur pour la fonction main: 5 { 0x08048330: Appuyez sur% ebp 0x08048331: mov % esp,% ebp 0x08048333: sub $ 0x8,% esp 0x08048336: et $ 0xfffffff0,% esp 0x08048339: sub $ 0x10,% esp 6 printf ("Hello.\N"); 0x0804833c: movl $ 0x8048440, (% esp) 0x08048343: appelez 0x8048284 7 return 0; 8} 0x08048348: mov $ 0x0,% eax 0x0804834d: laissez 0x0804834e: ret Fin d'assembleur dump.
Utilisez le commutateur -S (note: majuscule S) sur GCC, qui émettra le code d'assemblage dans un fichier portant l'extension .s. Par exemple, la commande suivante:
gcc -O2 -S -c toto.c
Je n'ai pas essayé de gcc, mais en cas de g ++. La commande ci-dessous fonctionne pour moi. -g pour la construction de débogage et -Wa, -adhln est passé à l'assembleur pour la liste avec le code source
g ++ -g -Wa, -adhln src.cpp