Как вы получаете вывод на ассемблере из источника C / C ++ в gcc? - PullRequest
321 голосов
/ 26 сентября 2008

Как это сделать?

Если я хочу проанализировать, как что-то компилируется, как бы я получил испущенный код сборки?

Ответы [ 16 ]

371 голосов
/ 26 сентября 2008

Используйте параметр -S для gcc (или g ++).

gcc -S helloworld.c

Это запустит препроцессор (cpp) над helloworld.c, выполнит первоначальную компиляцию и затем остановится до запуска ассемблера.

По умолчанию будет выведен файл helloworld.s. Выходной файл все еще можно настроить с помощью опции -o.

gcc -S -o my_asm_output.s helloworld.c

Конечно, это работает, только если у вас есть оригинальный источник. Альтернативой, если у вас есть только результирующий объектный файл, является использование objdump путем установки опции --disassemble (или -d для сокращенной формы).

objdump -S --disassemble helloworld > helloworld.dump

Этот параметр лучше всего работает, если для объектного файла включена опция отладки (-g во время компиляции) и файл не был извлечен.

Запуск file helloworld даст вам некоторое представление об уровне детализации, который вы получите, используя objdump.

163 голосов
/ 26 сентября 2008

При этом будет сгенерирован код asm с переплетенными номерами кода C +, чтобы легче было видеть, какие строки генерируют какой код.

# 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

Найдено в Алгоритмы для программистов , стр. 3 (общая 15-я страница PDF).

44 голосов
/ 30 сентября 2013

Следующая командная строка из блога Кристиана Гарбина

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

Я запускал G ++ из окна DOS на Win-XP против подпрограммы, содержащей неявное приведение

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 ++ (код C ++ отображается в виде комментариев в сгенерированном потоке 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)
22 голосов
/ 26 сентября 2008

Используйте переключатель -S

g++ -S main.cpp

или также с gcc

gcc -S main.c

Также см. это

12 голосов
/ 26 сентября 2008

Если то, что вы хотите увидеть, зависит от связывания вывода, то objdump для выходного объектного файла / исполняемого файла также может быть полезен в дополнение к вышеупомянутому gcc -S. Вот очень полезный скрипт Лорен Мерритт, который преобразует синтаксис objdump по умолчанию в более читаемый синтаксис nasm:

#!/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;

Я подозреваю, что это также может быть использовано на выходе gcc -S.

8 голосов
/ 13 июня 2013

Ну, как все говорили, используйте опцию -S. Если вы используете опцию -save-temps, вы также можете получить предварительно обработанный файл ( .i), файл сборки ( .s) и объектный файл (*. O). (получите каждый из них, используя -E, -S и -c.)

7 голосов
/ 11 октября 2008

Как упоминалось ранее, посмотрите на флаг -S.

Также стоит взглянуть на семейство флагов '-fdump-tree', в частности, '-fdump-tree-all', которое позволяет увидеть некоторые промежуточные формы gcc. Они часто могут быть более удобочитаемыми, чем ассемблер (по крайней мере, для меня), и позволяют увидеть, как проходят этапы оптимизации.

7 голосов
/ 26 сентября 2008

Как все отметили, используйте опцию -S для GCC. Я также хотел бы добавить, что результаты могут отличаться (дико!) В зависимости от того, добавляете ли вы опции оптимизации (-O0 ни для одного, -O2 для агрессивной оптимизации).

В частности, на архитектурах RISC компилятор часто преобразует код практически до неузнаваемости при выполнении оптимизации. Смотреть на результаты впечатляюще и увлекательно!

6 голосов
/ 24 октября 2011

Если вы ищете сборку LLVM:

llvm-gcc -emit-llvm -S hello.c
6 голосов
/ 26 сентября 2008

Используйте опцию -S:

gcc -S program.c
...