Come si ottiene l’output dell’assembler dalla sorgente C / C ++ in gcc?

Come si fa a fare questo?

Se voglio analizzare come viene compilato qualcosa, come posso ottenere il codice assembly emesso?

Usa l’opzione -S per gcc (o g ++).

 gcc -S helloworld.c 

Questo eseguirà il preprocessore (cpp) su helloworld.c, eseguirà la compilazione iniziale e si fermerà prima dell’esecuzione dell’assembler.

Di default questo produrrà un file helloworld.s . Il file di output può essere ancora impostato usando l’opzione -o .

 gcc -S -o my_asm_output.s helloworld.c 

Ovviamente questo funziona solo se hai la fonte originale. Un’alternativa se si ha il file object risultante è usare objdump , impostando l’opzione --disassemble (o -d per la forma abbreviata).

 objdump -S --disassemble helloworld > helloworld.dump 

Questa opzione funziona meglio se l’opzione di debug è abilitata per il file object ( -g al momento della compilazione) e il file non è stato rimosso.

L’esecuzione del file helloworld ti darà qualche indicazione sul livello di dettaglio che otterrai usando objdump.

Questo genererà l’asm con il codice C + i numeri di linea intrecciati per vedere più facilmente quali linee generano quale codice.

 # 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 

Trovato in Algoritmi per programmatori , pagina 4.

La seguente riga di comando proviene dal blog di Christian Garbin

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

Ho eseguito G ++ da una finestra DOS su Win-XP, contro una routine che contiene un cast implicito

 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' 

L’output è un codice generato da asssembled con il codice originale C ++ (il codice C ++ è mostrato come commenti nel stream asm generato)

  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 $0,-16(%ebp) 

Usa l’interruttore -S

 g++ -S main.cpp 

o anche con gcc

 gcc -S main.c 

Vedi anche questo

Se ciò che si vuole vedere dipende dal collegamento dell’output, allora anche objdump sul file / file eseguibile dell’object può essere utile in aggiunta al summenzionato gcc -S. Ecco uno script molto utile di Loren Merritt che converte la syntax objdump predefinita nella syntax del nas più leggibile:

 #!/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(){ 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 $_ =~ /\tnop |\txchg *ax,ax$/) { # drop this line } else { print $prev; $prev = $_; } } print $prev; close FH; 

Sospetto che questo possa essere usato anche sull’output di gcc -S.

Come tutti hanno sottolineato, usa l’opzione -S per GCC. Vorrei anche aggiungere che i risultati possono variare (in modo selvaggio!) A seconda che si aggiungano o meno le opzioni di ottimizzazione ( -O0 per nessuno, -O2 per l’ottimizzazione aggressiva).

In particolare sulle architetture RISC, il compilatore spesso trasforma il codice quasi oltre il riconoscimento nell’ottimizzazione. È impressionante e affascinante guardare i risultati!

Bene, come tutti hanno detto, usa l’opzione -S. Se si utilizza l’opzione -save-temps, è anche ansible ottenere file pre-elaborato ( .i), file assembly ( .s) e file object (*. O). (ottieni ognuno di essi usando -E, -S e -c.)

Usa l’opzione -S:

 gcc -S program.c 

Come accennato in precedenza, guarda il flag -S.

Vale anche la pena guardare la famiglia di flag “-fdump-tree”, in particolare “-fdump-tree-all”, che consente di vedere alcune delle forms intermedie di gcc. Questi possono essere più facilmente leggibili rispetto all’assemblatore (almeno per me) e ti permettono di vedere come funzionano le passate di ottimizzazione.

Se stai cercando un assemblaggio LLVM:

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

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

gcc -c -g -Wa, -a, -ad [altre opzioni GCC] foo.c> foo.lst

in alternativa alla risposta di PhirePhly O basta usare -S come tutti hanno detto.

Non vedo questa possibilità tra le risposte, probabilmente perché la domanda è del 2008, ma nel 2018 puoi usare il sito web online di Matt Goldbolt https://godbolt.org

Puoi anche clonare git localmente ed eseguire il suo progetto https://github.com/mattgodbolt/compiler-explorer

Uscita di questi commnad

Ecco i passaggi per vedere / stampare il codice assembly di qualsiasi programma C su Windows

console / terminale / prompt dei comandi:

  1. Scrivi un programma in C in un editor di codice C come codeblocks e salvalo con un’estensione .c

  2. Compilalo ed eseguilo.

  3. Una volta eseguita con successo, vai nella cartella in cui hai installato il tuo compilatore gcc e dai il

    seguente comando per ottenere un file ‘.s’ del file ‘.c’

    C: \ gcc> gcc -S percorso completo del file C ENTER

    Un comando di esempio (come nel mio caso)

    C: \ gcc> gcc -SD: \ Aa_C_Certified \ alternate_letters.c

    Questo produce un file “.s” del file originale “.c”

4. Dopo questo, digita il seguente comando

C; \ gcc> cpp filename.s INVIO

Comando di esempio (come nel mio caso)

C; \ gcc> cpp alternate_letters.s

Questo stamperà / produrrà l’intero codice linguaggio Assembly del tuo programma C.

Usa “-S” come opzione. Visualizza l’output dell’assieme nel terminale.