




Используйте переключатель -S
g++ -S main.cpp
или также с gcc
gcc -S main.c
Также см. это
Ознакомьтесь с FAQ: «Также совершенно нормально задать свой собственный вопрос по программированию и ответить на него». Дело в том, что теперь StackOverflow содержит вопросы и ответы в качестве ресурса для других.
И, может быть, кто-то другой придет и удивит вас лучшим ответом, хотя мой иногда может быть немного многословным ...
Есть даже кнопка ответа на свой вопрос.
Используйте параметр -S:
gcc -S program.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.
Тем не менее, этот сценарий представляет собой грязный прием, который не полностью преобразует синтаксис. Например. mov eax,ds:0x804b794 не очень NASMish. Кроме того, иногда он просто удаляет полезную информацию: movzx eax,[edx+0x1] дает читателю возможность догадаться, был ли операнд памяти byte или word.
Для дизассемблирования в синтаксисе NASM в первую очередь используйте objconv Агнера Фога. Вы можете заставить его дизассемблировать в стандартный вывод с помощью output file = /dev/stdout, чтобы вы могли перенаправить его в less для просмотра. Также есть ndisasm, но он разбирает только плоские двоичные файлы и не знает об объектных файлах (ELF / PE).
Используйте параметр -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.
Хотя это правильно, я нашел результаты ответа Cr McDonough более полезными.
дополнительное использование: objdump -M intel -S --disassemble helloworld> helloworld.dump, чтобы получить дамп объекта в синтаксисе Intel, совместимом с nasm в Linux.
Если у вас есть одна функция для оптимизации / проверки, вы можете попробовать интерактивные интерактивные компиляторы C++, то есть Godbolt
@touchStone: GAS .intel_syntaxнет совместим с NASM. Это больше похоже на MASM (например, mov eax, symbol - это нагрузка, в отличие от NASM, где это mov r32, imm32 адреса), но также не полностью совместим с MASM. Я настоятельно рекомендую его как удобный для чтения формат, особенно если вы любите писать в синтаксисе NASM. objdump -drwC -Mintel | less или gcc foo.c -O1 -fverbose-asm -masm=intel -S -o- | less полезны. (См. Также Как убрать «шум» из вывода сборки GCC / clang?). -masm=intel тоже работает с лязгом.
Лучше используйте gcc -O -fverbose-asm -S
Как все отметили, используйте опцию -S для GCC. Я также хотел бы добавить, что результаты могут отличаться (сильно!) В зависимости от того, добавляете ли вы параметры оптимизации (-O0 - нет, -O2 - агрессивная оптимизация).
В частности, в архитектурах RISC компилятор часто преобразует код почти до неузнаваемости при выполнении оптимизации. Смотреть на результаты впечатляюще и увлекательно!
Это сгенерирует ассемблерный код с переплетением кода C + номеров строк, чтобы было легче увидеть, какие строки генерируют какой код:
# create assembler code:
g++ -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-файла).
(На самом деле это страница (пронумерованная) 3 (это 15-я страница PDF-файла))
К сожалению, as в OS X не знает этих флагов. Однако если бы это было так, вы, вероятно, могли бы однострочно использовать -Wa для передачи параметров в as.
g++ -g -O0 -c -fverbose-asm -Wa,-adhln test.cpp > test.lst будет сокращенной версией этого.
Вы также можете использовать gcc -c -g -Wa,-ahl=test.s test.c или gcc -c -g -Wa,-a,-ad test.c > test.txt.
Сообщение блога, объясняющий это более подробно, включая версию с одной командой, такую как легенды и опубликованные Lu'u. Но почему -O0? Он полон загрузок / хранилищ, которые затрудняют отслеживание значения и ничего не говорят вам о том, насколько эффективным будет оптимизированный код.
Как упоминалось ранее, посмотрите на флаг -S.
Также стоит взглянуть на семейство флагов «-fdump-tree», в частности «-fdump-tree-all», которое позволяет вам увидеть некоторые промежуточные формы gcc. Часто они могут быть более читабельны, чем ассемблер (по крайней мере, для меня), и позволяют увидеть, как работают этапы оптимизации.
Используйте "-S" в качестве опции. Он отображает вывод сборки в терминале.
Для отображения в терминале используйте gcc foo.c -masm=intel -fverbose-asm -O3 -S -o- |less. -S сам по себе создает foo.s.
От: http://www.delorie.com/djgpp/v2faq/faq8_20.html
gcc -c -g -Wa, -a, -ad [другие параметры GCC] foo.c> foo.lst
в качестве альтернативы ответу PhirePhly Или просто используйте -S, как все сказали.
Если вы ищете сборку LLVM:
llvm-gcc -emit-llvm -S hello.c
Ну, как все говорили, используйте параметр -S. Если вы используете опцию -save-temps, вы также можете получить предварительно обработанный файл (.i), файл сборки (.s) и объектный файл (*. O). (получите каждый из них, используя -E, -S и -c.)
Следующая командная строка взята из Блог Кристиана Гарбина
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)
@Paladin - Не обязательно. OP был о получении выходного эквивалента ассемблера исходного кода C / C++, он получает листинг, который, я согласен, более полезен для понимания того, что делают компилятор и оптимизатор. Но это приведет к тому, что сам ассемблер отключится, поскольку он не ожидает номеров строк и скомпилирует байты, оставшиеся от инструкций сборки.
Используйте по крайней мере -O2 или любые другие параметры оптимизации, которые вы действительно используете при создании проекта, если вы хотите увидеть, как gcc оптимизирует ваш код. (Или, если вы используете LTO, как и следовало бы, тогда вам придется дизассемблировать вывод компоновщика, чтобы увидеть, что вы действительно получите.)
Я не вижу такой возможности среди ответов, вероятно, потому что вопрос из 2008 года, но в 2018 году вы можете использовать онлайн-сайт Мэтта Голдболта https://godbolt.org
Вы также можете локально git clone и запустить его проект https://github.com/mattgodbolt/compiler-explorer
Вот шаги, чтобы увидеть / распечатать ассемблерный код любой программы на C в вашей 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 filename.s ENTER
Пример команды (как в моем случае)
C; \ gcc> cpp alternate_letters.s
Это напечатает / выведет весь код языка ассемблера вашей программы C.
недавно я хотел узнать сборку каждой функции в программе
вот как я это сделал.
$ 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
Вот решение для C с использованием gcc:
gcc -S program.c && gcc program.c -o output
Здесь первая часть сохраняет вывод сборки программы под тем же именем файла, что и Program, но с измененным расширением .s, вы можете открыть его как любой обычный текстовый файл.
Вторая часть здесь компилирует вашу программу для фактического использования и генерирует исполняемый файл для вашей Программы с указанным именем файла.
program.c, использованный выше, - это имя вашей программы, а выход - имя исполняемого файла, который вы хотите сгенерировать.
Кстати, это мой первый пост на StackOverFlow: -}
-save-temps
Об этом упоминалось в https://stackoverflow.com/a/17083009/895245, но позвольте мне еще раз проиллюстрировать это.
Большим преимуществом этой опции перед -S является то, что ее очень легко добавить в любой скрипт сборки, не сильно влияя на саму сборку.
Когда вы это сделаете:
gcc -save-temps -c -o main.o main.c
main.c
#define INC 1
int myfunc(int i) {
return i + INC;
}
и теперь, помимо обычного вывода main.o, текущий рабочий каталог также содержит следующие файлы:
main.i является бонусом и содержит предварительно оцененный файл:
# 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 содержит желаемую сгенерированную сборку:
.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 , %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
Если вы хотите сделать это для большого количества файлов, рассмотрите возможность использования вместо этого:
-save-temps=obj
который сохраняет промежуточные файлы в том же каталоге, что и выходные данные объекта -o, вместо текущего рабочего каталога, что позволяет избежать потенциальных конфликтов базовых имен.
Еще одна интересная особенность этой опции - добавить -v:
gcc -save-temps -c -o main.o -v main.c
он фактически показывает явные файлы, используемые вместо уродливых временных файлов в /tmp, поэтому легко узнать, что именно происходит, включая этапы предварительной обработки / компиляции / сборки:
/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
Протестировано в Ubuntu 19.04 amd64, GCC 8.3.0.
Предварительно определенные цели CMake
CMake автоматически предоставляет цели для предварительно обработанного файла:
make help
показывает нам, что мы можем:
make main.s
и эта цель запускается:
Compiling C source to assembly CMakeFiles/main.dir/main.c.s
/usr/bin/cc -S /home/ciro/hello/main.c -o CMakeFiles/main.dir/main.c.s
так что файл можно увидеть на CMakeFiles/main.dir/main.c.s
Проверено на cmake 3.16.1.
Советы по сделать вывод asm удобочитаемым см. Также: Как убрать «шум» из вывода сборки GCC / clang?