Como você recebe saída assembler de C / C ++ fonte gcc?
Pergunta
Como se faz isso?
Se eu quiser analisar como algo está sendo compilado, como eu iria obter o código de montagem emitida?
Solução
Use a opção -S
para gcc (ou g ++).
gcc -S helloworld.c
Isto irá executar o pré-processador (CPP) sobre helloworld.c, execute a compilação inicial e, em seguida, parar antes do assembler é executado.
Por padrão, essa saída será um helloworld.s
arquivo. O arquivo de saída pode ser ainda ser definida usando a opção -o
.
gcc -S -o my_asm_output.s helloworld.c
Claro que isso só funciona se você tiver a fonte original.
Uma alternativa se você tiver apenas o arquivo objeto resultante é usar objdump
, definindo a opção --disassemble
(ou -d
para a forma abreviada).
objdump -S --disassemble helloworld > helloworld.dump
Esta opção funciona melhor se a opção de depuração está habilitado para o arquivo objeto (-g
em tempo de compilação) e o arquivo não foi retirada.
Running file helloworld
lhe dará alguma indicação quanto ao nível de detalhe que você vai ficar usando objdump.
Outras dicas
Isso irá gerar o código asm com o C números de código + linha entrelaçada para ver mais facilmente o que linhas gerar o código.
# 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
Algoritmos para programadores , página 3 (o qual é a página global de 15 o PDF).
O seguinte linha de comando é de Christian Garbin de blogue
g++ -g -O -Wa,-aslh horton_ex2_05.cpp >list.txt
Eu corri G ++ a partir de uma janela do DOS no Win-XP, contra uma rotina que contenha uma conversão implícita ??p>
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'
código A saída é gerado asssembled iterspersed com o código original C ++ (o código C ++ é mostrado como comentários no fluxo gerado ASM)
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)
Se o que você quer ver depende da ligação da saída, então objdump no arquivo objeto de saída / executável pode também ser útil além do gcc referido -S. Aqui está um script muito útil por Loren Merritt que converte a sintaxe objdump padrão na sintaxe nasm mais legível:
#!/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;
Eu suspeito que isso também pode ser usado na produção de gcc -S.
Bem, como todos diziam, use a opção -S. Se você usar -Save-temps arquivo de opção, você também pode obter pré-processados ??( .i), montagem de arquivos ( .s) e objeto de arquivo (*. O). (Obter cada um deles usando -E, -S, e -c.)
Como toda a gente tem a pontas, use a opção -S
a GCC. Eu também gostaria de acrescentar que os resultados podem variar (descontroladamente!) Dependendo ou não adiciona opções de otimização (-O0
para nenhum, -O2
para otimização agressivo).
arquiteturas Em RISC em particular, o compilador, muitas vezes, transformar o código quase irreconhecível em fazer otimização. É impressionante e fascinante olhar para os resultados!
Como mencionado antes, olhar para a bandeira -S.
Também vale a pena olhar para a família '-fdump-árvore' de bandeiras, em particular '--fdump-árvore all', que permite que você veja algumas das formas intermediárias do GCC. Estes, muitas vezes pode ser mais legível do que assembler (pelo menos para mim), e deixá-lo ver como passes de otimização executar.
Use a opção -s:
gcc -S program.c
Se você está procurando LLVM assembly:
llvm-gcc -emit-llvm -S hello.c
Não vejo essa possibilidade entre as respostas, provavelmente porque a questão é de 2008, mas em 2018 você pode usar o site on-line de Matt Goldbolt https://godbolt.org
Você pode clonar também localmente git e executar seu projeto https://github.com/mattgodbolt/compiler- explorador
De: http://www.delorie.com/djgpp/v2faq/faq8_20 .html
gcc -c -g -Wa, -a, -AD [outras opções do CCG] foo.c> foo.lst
em alternativa a resposta de PhirePhly Ou apenas uso -S como todo mundo disse.
Aqui estão os passos para ver / imprimir o código de montagem de qualquer programa C no seu Windows
console / terminal / prompt de comando:
-
Escreva um programa C em um editor de código C como codeblocks e guardá-lo com uma extensão .c
-
Compilar e executá-lo.
-
Uma vez executado com êxito, vá para a pasta onde você instalou o seu compilador gcc e dar o
comando a seguir para obter um arquivo '.s' do arquivo '.c'
C: \ gcc> gcc -S caminho completo do arquivo C ENTER
Um exemplo de comando (como no meu caso)
C: \ gcc> gcc -S D: \ Aa_C_Certified \ alternate_letters.c
Esta saídas de um arquivo '.s' do original arquivo '.c'
4. Após isso, digite o seguinte comando
C; \ gcc> CPP filename.s ENTER
comando Exemplo (como no meu caso)
C; \ gcc> CPP alternate_letters.s
Isto irá imprimir / output todo o código do seu programa C linguagem Assembly.
Use "-S" como uma opção. Ele exibe a saída de montagem no terminal.
Recentemente eu queria saber a montagem de cada função em um programa
isto é como eu fiz isso.
$ 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
Isto foi mencionado em https://stackoverflow.com/a/17083009/895245 mas me deixou ainda mais exemplificam-lo . Quando você faz:
gcc -save-temps -c -o main.o main.c
main.c
#define INC 1
int myfunc(int i) {
return i + INC;
}
e agora, além da main.o
saída normal, o diretório de trabalho atual também contém os seguintes arquivos:
-
main.i
é um bônus e contém é o arquivo prepossessed desejado:# 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
contém o desejado gerado montagem:.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 você quiser fazê-lo para um grande número de arquivos, considere usar em vez disso:
-save-temps=obj
que salva os arquivos intermediários para o mesmo diretório como a saída -o
objeto em vez do diretório de trabalho atual, evitando assim potenciais conflitos basename.
A vantagem desta opção sobre -S
é que é fácil de adicioná-lo a qualquer script de construção, sem interferir muito na própria construção.
Outra coisa legal sobre esta opção é se você adicionar -v
:
gcc -save-temps -c -o main.o -v main.c
que realmente mostra os arquivos explícitas sendo usado em vez de temporários feias sob /tmp
, por isso é fácil saber exatamente o que está acontecendo, o que inclui o pré-processamento / compilação / montagem etapas:
/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
Testado no Ubuntu 19.04 amd64, GCC 8.3.0.
Aqui está uma solução para C usando gcc:
gcc -S program.c && gcc program.c -o output
-
Aqui as primeiras lojas de peças a saída montagem do programa no mesmo nome de arquivo do programa, mas com uma mudado .s extensão, você pode abri-lo como qualquer arquivo de texto normal.
-
A segunda parte aqui compila seu programa para uso real e gera um arquivo executável para o seu programa com um nome de arquivo especificado.
O program.c usado acima é o nome do seu programa e saída é o nome do executável que você deseja gerar.
BTW É o meu primeiro post sobre StackOverFlow: -}