it-swarm.com.ru

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

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

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

313
Doug T.

Используйте параметр -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.

365
Andrew Edgecombe

Это сгенерирует ассемблерный код с переплетенными номерами кода 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).

160
PhirePhly

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

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)
44
Cr McDonough

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

g++ -S main.cpp

или также с GCC

gcc -S main.c

Также смотрите это

22
Doug T.

Если то, что вы хотите увидеть, зависит от связывания выходных данных, тогда 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.

12
Dark Shikari

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

8
METADATA

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

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

7
Dan Lenski

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

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

7
Chris Jefferson

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

gcc -S program.c
6
Jeremy Ruten

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

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

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

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

5
Antonin GAVREL

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

gcc -c -g -Wa, -a, -ad [другие опции GCC] foo.c> foo.lst

в качестве альтернативы ответу PhirePhly Или просто используйте -S, как все говорили.

4
Anonymous

 Output of these commnads

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

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

  1. Напишите C-программу в редакторе C-кода, например, кодовые блоки, и сохраните ее с расширением .c

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

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

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

    C:\gcc> gcc -S полный путь к C-файлу ENTER

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

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

    Это выводит файл «.s» исходного файла «.c»

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

C;\gcc> cpp filename.s ENTER

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

C;\gcc> cpp alternate_letters.s 

Это напечатает/выведет весь код на ассемблере вашей C-программы.

2
Ashutosh K Singh

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

1
Pizearke

недавно я хотел знать сборку каждой функции в программе
Вот как я это сделал.

$ 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
1
Abhishek D K

Вот решение для C с использованием gcc:

gcc -S program.c && gcc program.c -o output
  1. Здесь первая часть хранит вывод сборки программы в том же имени файла, что и программа, но с измененным расширением .s , вы можете открыть его как любой обычный текстовый файл.

  2. Вторая часть здесь компилирует вашу программу для фактического использования и генерирует исполняемый файл для вашей Программы с указанным именем файла.

Используемый выше program.c - это имя вашей программы, а output - имя исполняемого файла, который вы хотите сгенерировать.

Кстати, это мой первый пост на StackOverFlow: -}

0
Himanshu Pal