Как вы получаете вывод ассемблера из источника C/C++ в gcc?


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

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

14 300

14 ответов:

использовать -S опция для gcc (или g++).

gcc -S helloworld.c

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

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

gcc -S -o my_asm_output.s helloworld.c

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

objdump -S --disassemble helloworld > helloworld.dump

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

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

Это создаст 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

нашли в алгоритмы для программистов, стр. 4.

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

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'

на выходе получается ассемблированный сгенерированный код iterspersed с исходным кодом 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 8,%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 ,-16(%ebp)

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

g++ -S main.cpp

или также с gcc

gcc -S main.c

см. Также этой

Если то, что вы хотите увидеть, зависит от связывания вывода, то 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)//o or
        s/($reg,)$ptr(\[[^\[\]]+\])//o or
        s/$ptr/lc /oe;
    }
    if($prev =~ /\t(repz )?ret / and
       $_ =~ /\tnop |\txchg *ax,ax$/) {
       # drop this line
    } else {
       print $prev;
       $prev = $_;
    }
}
print $prev;
close FH;

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

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

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

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

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

gcc -S program.c

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

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

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

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

от:http://www.delorie.com/djgpp/v2faq/faq8_20.html

gcc-c-g-Wa,-a, - ad [другие варианты GCC] foo.c > foo.lst

в альтернативе ответу Фирефли Или просто использовать-S, как все говорили.

Я не вижу такой возможности среди ответов, вероятно, потому что вопрос с 2008 года, но в 2018 году вы можете использовать онлайн-сайт Мэтта Голдболта https://godbolt.org

вы также можете локально клонировать git и запустить его проект https://github.com/mattgodbolt/compiler-explorer

Output of these commnads

вот шаги, чтобы увидеть / распечатать ассемблерный код любой программы C на вашем Windows

консоль /терминал/ командную строку :

  1. напишите программу C в редакторе кода C, например codeblocks, и сохраните ее с расширением .c

  2. скомпилировать и запустить его.

  3. после успешного запуска перейдите в папку, в которой вы установили компилятор gcc, и дайте

    следующая команда, чтобы получить ' .s 'file of the'.c ' file

    C:\ gcc> GCC-S полный путь к файлу C введите

    пример команды ( как в моем случае)

    C:\gcc> gcc-S D:\Aa_C_Certified\alternate_letters.c

    это выводит a'.файл s' оригинала ' .c ' file

4 . После этого введите следующую команду

C;\gcc> cpp filename.s введите

пример команды ( как в моем случае)

C;\gcc> cpp alternate_letters.s

Это будет печатать / выводить весь код языка ассемблера вашей программы C.

используйте "- S " в качестве опции. Он отображает вывод сборки в терминале.