Pergunta

Como se faz isso?

Se eu quiser analisar como algo está sendo compilado, como eu iria obter o código de montagem emitida?

Foi útil?

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

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)

Use a opção -s

g++ -S main.cpp

ou também com gcc

gcc -S main.c

Veja também este

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.

Output desses commnads

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:

  1. Escreva um programa C em um editor de código C como codeblocks e guardá-lo com uma extensão .c

  2. Compilar e executá-lo.

  3. 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
  1. 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.

  2. 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: -}

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top