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

278

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

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

Теги:
debugging
gcc
assembly

14 ответов

299
Лучший ответ

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

  • 3
    Хотя это правильно, я нашел, что результаты ответа Макдоноу были более полезными.
  • 3
    дополнительно используйте: objdump -M intel -S --disassemble helloworld> helloworld.dump, чтобы получить дамп объекта в синтаксисе intel, совместимый с nasm в linux.
Показать ещё 3 комментария
151

Это сгенерирует 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.

  • 3
    (Это фактически на странице (пронумерованной) 3 (которая является 15-ой страницей PDF))
  • 1
    К сожалению, as на OS X не знает эти флаги. Если это -Wa , вы, вероятно, могли бы сделать это одной строкой, используя -Wa для передачи параметров в as .
Показать ещё 3 комментария
39

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

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'

Вывод обработан сгенерированным кодом, переработанным исходным кодом С++ (код С++ отображается как комментарии в сгенерированном потоке 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)
  • 0
    @Paladin - Не обязательно. ОП был посвящен получению выходного кода ассемблера, эквивалентного исходному коду C / C ++, он получил листинг, который, я согласен, более полезен для понимания того, что делает компилятор и оптимизатор. Но это может привести к тому, что сам ассемблер прекратит работу, так как он не ожидает номеров строк и компилирует байты, оставшиеся от инструкций по сборке.
  • 0
    Используйте, по крайней мере, -O2 или любые другие опции оптимизации, которые вы фактически используете при создании проекта, если вы хотите увидеть, как gcc оптимизирует ваш код. (Или, если вы используете LTO, как и вы, то вам нужно разобрать вывод компоновщика, чтобы увидеть, что вы действительно получите.)
20

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

g++ -S main.cpp

а также с помощью gcc

gcc -S main.c

Также см. this

  • 6
    Ознакомьтесь с часто задаваемыми вопросами: «Также можно задавать и отвечать на свои вопросы по программированию». Дело в том, что теперь StackOverflow содержит вопросы и ответы в качестве ресурса для других.
  • 0
    И, может быть, кто-то еще придет и удивит вас лучшим ответом, хотя мой иногда может быть немного многословным ...
Показать ещё 1 комментарий
13

Если то, что вы хотите видеть, зависит от компоновки вывода, тогда objdump для файла/исполняемого файла вывода также может быть полезен в дополнение к вышеупомянутому gcc -S. Здесь очень полезный script Loren Merritt, который преобразует синтаксис 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.

  • 1
    Тем не менее, этот скрипт - грязный хак, который не полностью конвертирует синтаксис. Например, mov eax,ds:0x804b794 не очень NASMish. Кроме того, иногда он просто удаляет полезную информацию: movzx eax,[edx+0x1] оставляет читателю угадать, был ли операнд памяти byte или word .
  • 0
    Чтобы сначала разобрать синтаксис NASM, используйте objconv Агнера Фога . Вы можете заставить его разобрать в stdout с выходным файлом = /dev/stdout , так что вы можете перейти на less для просмотра. Есть также ndisasm , но он разбирает только плоские двоичные файлы и не знает об объектных файлах (ELF / PE).
7

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

7

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

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

6

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

llvm-gcc -emit-llvm -S hello.c
  • 1
    или та же команда с лязгом
6

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

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

5

Используйте параметр -S:

gcc -S program.c
4

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

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

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

3

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

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

1

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

  • 0
    Для отображения в терминале используйте gcc foo.c -masm=intel -fverbose-asm -O3 -S -o- |less . -S сам создает foo.s
0

Изображение 1261

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

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

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

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

  • После успешного запуска перейдите в папку, в которой вы установили свой компилятор 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 имя_файла .s ВВОД

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

C;\gcc > cpp alternate_letters.s

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

Сообщество Overcoder
Наверх
Меню