Risposte:
Usa l' -S
opzione per gcc (o g ++).
gcc -S helloworld.c
Ciò eseguirà il preprocessore (cpp) su helloworld.c, eseguirà la compilazione iniziale e quindi si arresterà prima che venga eseguito l'assemblatore.
Per impostazione predefinita, questo genererà un file helloworld.s
. Il file di output può essere comunque impostato utilizzando l' -o
opzione.
gcc -S -o my_asm_output.s helloworld.c
Ovviamente questo funziona solo se hai la fonte originale. Un'alternativa se hai solo il file oggetto risultante è quella di usare objdump
, impostando l' --disassemble
opzione (o -d
per il modulo abbreviato).
objdump -S --disassemble helloworld > helloworld.dump
Questa opzione funziona meglio se l'opzione di debug è abilitata per il file oggetto ( -g
al momento della compilazione) e il file non è stato rimosso.
La corsa file helloworld
ti darà alcune indicazioni sul livello di dettaglio che otterrai usando objdump.
.intel_syntax
è compatibile con NASM . È più simile a MASM (ad esempio mov eax, symbol
è un carico, a differenza di NASM dove è un mov r32, imm32
indirizzo), ma non è totalmente compatibile con MASM. Lo consiglio vivamente come un bel formato da leggere, soprattutto se ti piace scrivere nella sintassi NASM. objdump -drwC -Mintel | less
o gcc foo.c -O1 -fverbose-asm -masm=intel -S -o- | less
sono utili. (Vedi anche Come rimuovere il "rumore" dall'uscita dell'assieme GCC / clang? ). -masm=intel
funziona anche con clang.
gcc -O -fverbose-asm -S
Questo genererà il codice assembly con il codice C + numeri di riga intrecciati, per vedere più facilmente quali righe generano quale codice:
# create assembler code:
g++ -S -fverbose-asm -g -O2 test.cc -o test.s
# create asm interlaced with source lines:
as -alhnd test.s > test.lst
Trovato in Algorithms for programmers , pagina 3 (che è la 15a pagina complessiva del PDF).
as
su OS X non si conoscono questi flag. Se così fosse, però, si potrebbe probabilmente una riga questo utilizzando -Wa
passare alcuna opzione al as
.
g++ -g -O0 -c -fverbose-asm -Wa,-adhln test.cpp > test.lst
sarebbe la versione abbreviata di questo.
gcc -c -g -Wa,-ahl=test.s test.c
ogcc -c -g -Wa,-a,-ad test.c > test.txt
-O0
? È pieno di carichi / negozi che rendono difficile tenere traccia di un valore e non ti dice nulla sull'efficienza del codice ottimizzato.
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 è assemblato codice generato assemblato con il codice C ++ originale (il codice C ++ viene mostrato come commenti nel flusso 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)
-O2
, o qualsiasi altra opzione di ottimizzazione utilizzi effettivamente quando costruisci il tuo progetto, se vuoi vedere come gcc ottimizza il tuo codice. (O se usi LTO, come dovresti, devi smontare l'output del linker per vedere cosa ottieni veramente.)
Se ciò che si desidera vedere dipende dal collegamento dell'output, anche objdump sul file / eseguibile dell'oggetto di output può essere utile in aggiunta al summenzionato gcc -S. Ecco uno script molto utile di Loren Merritt che converte la sintassi objdump predefinita nella sintassi nasm 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(<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
$_ =~ /\tnop |\txchg *ax,ax$/) {
# drop this line
} else {
print $prev;
$prev = $_;
}
}
print $prev;
close FH;
Sospetto che questo possa essere utilizzato anche sull'output di gcc -S.
mov eax,ds:0x804b794
non è molto NASMish. Inoltre, a volte toglie solo informazioni utili: movzx eax,[edx+0x1]
lascia al lettore di indovinare se l'operando di memoria fosse byte
o word
.
objconv
. Puoi farlo disassemblare in stdout con il file di output = /dev/stdout
, in modo da poter eseguire il pipe less
per la visualizzazione. C'è anche ndisasm
, ma smonta solo i binari piatti e non conosce i file oggetto (ELF / PE).
Come tutti hanno sottolineato, utilizzare l' -S
opzione per GCC. Vorrei anche aggiungere che i risultati possono variare (selvaggiamente!) 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 al di là del riconoscimento nel fare l'ottimizzazione. È impressionante e affascinante guardare i risultati!
Come accennato in precedenza, guarda la bandiera -S.
Vale anche la pena guardare la famiglia di flag '-fdump-tree', in particolare '-fdump-tree-all', che ti permette di vedere alcune delle forme intermedie di gcc. Questi possono spesso essere più leggibili dell'assemblatore (almeno per me) e farti vedere come funzionano i passaggi di ottimizzazione.
Non vedo questa possibilità tra le risposte, probabilmente perché la domanda è del 2008, ma nel 2018 è possibile utilizzare il sito Web online di Matt Goldbolt https://godbolt.org
Puoi anche localizzare git clone ed eseguire il suo progetto https://github.com/mattgodbolt/compiler-explorer
-save-temps
Questo è stato menzionato su https://stackoverflow.com/a/17083009/895245 ma lasciatemi esemplificare ulteriormente.
Il grande vantaggio di questa opzione -S
è che è molto facile aggiungerlo a qualsiasi script di build, senza interferire molto nella build stessa.
Quando lo fai:
gcc -save-temps -c -o main.o main.c
main.c
#define INC 1
int myfunc(int i) {
return i + INC;
}
e ora, oltre al normale output main.o
, la directory di lavoro corrente contiene anche i seguenti file:
main.i
è un bonus e contiene il file prestampato:
# 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
contiene l'assemblaggio generato desiderato:
.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
Se vuoi farlo per un gran numero di file, considera invece di usare:
-save-temps=obj
che salva i file intermedi nella stessa directory -o
dell'output dell'oggetto anziché nella directory di lavoro corrente, evitando così potenziali conflitti di nome di base.
Un'altra cosa interessante di questa opzione è se aggiungi -v
:
gcc -save-temps -c -o main.o -v main.c
mostra in realtà i file espliciti utilizzati al posto dei brutti temporanei sotto /tmp
, quindi è facile sapere esattamente cosa sta succedendo, che include i passaggi di pre-elaborazione / compilazione / assemblaggio:
/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
Testato in Ubuntu 19.04 amd64, GCC 8.3.0.
Utilizzare l'opzione -S:
gcc -S program.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 semplicemente usa -S come dicevano tutti.
Ecco i passaggi per visualizzare / stampare il codice assembly di qualsiasi programma C su Windows
console / terminale / prompt dei comandi:
Scrivi un programma C in un editor di codice C come i blocchi di codice e salvalo con estensione .c
Compilalo ed eseguilo.
Una volta eseguito correttamente, vai alla 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 INVIO
Un comando di esempio (come nel mio caso)
C: \ gcc> gcc -SD: \ Aa_C_Certified \ alternate_letters.c
Questo genera un file '.s' del file '.c' originale
4 Successivamente, digitare il comando seguente
C; \ gcc> cpp nomefile.s INVIO
Esempio di comando (come nel mio caso)
C; \ gcc> cpp alternate_letters.s
Ciò stamperà / produrrà l'intero codice in linguaggio Assembly del tuo programma C.
Usa "-S" come opzione. Visualizza l'output dell'assemblaggio nel terminale.
gcc foo.c -masm=intel -fverbose-asm -O3 -S -o- |less
. -S
da solo crea foo.s
.
recentemente ho voluto conoscere l'assemblaggio di ciascuna funzione in un programma,
è così che l'ho fatto.
$ 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
Ecco una soluzione per C usando gcc:
gcc -S program.c && gcc program.c -o output
Qui la prima parte memorizza l'output dell'assembly del programma con lo stesso nome di file di Program ma con un'estensione .s modificata , è possibile aprirlo come qualsiasi normale file di testo.
La seconda parte qui compila il tuo programma per l'utilizzo effettivo e genera un eseguibile per il tuo Programma con un nome file specificato.
Il programma.c usato sopra è il nome del programma e l' output è il nome dell'eseguibile che si desidera generare.
A proposito, è il mio primo post su StackOverFlow: -}