Это запустит препроцессор (cpp) поверх helloworld.c, выполнит первоначальную компиляцию и затем остановится перед запуском ассемблера.
По умолчанию это выведет файл helloworld.s. Выходной файл все еще может быть установлен с помощью -oопции.
gcc -S -o my_asm_output.s helloworld.c
Конечно, это работает, только если у вас есть оригинальный источник. Альтернативой, если у вас есть только результирующий объектный файл, является использование objdump, установив --disassembleпараметр (или -dдля сокращенной формы).
Хотя это правильно, я нашел, что результаты ответа Макдоноу были более полезными.
Рис Улерих
3
дополнительно используйте: objdump -M intel -S --disassemble helloworld> helloworld.dump для получения дампа объекта в синтаксисе intel, совместимого с nasm в linux.
TouchStone
2
Если у вас есть одна функция для оптимизации / проверки, то вы можете попробовать интерактивные интерактивные компиляторы C ++, т.е. godbolt
fiorentinoing
1
@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тоже работает с лязгом
Питер Кордес
3
Лучше использоватьgcc -O -fverbose-asm -S
Старынкевич
173
Это сгенерирует ассемблерный код с переплетенными номерами кода C +, чтобы легче было увидеть, какие строки генерируют какой код:
(Это на самом деле на странице (пронумерованной) 3 (которая является 15-й страницей PDF))
Grumdrig
1
К сожалению, asв OS X эти флаги не известны. Если это произойдет, вы, вероятно, можете сделать это одной строкой, используя -Waдля передачи параметров as.
Вы также можете использовать любой gcc -c -g -Wa,-ahl=test.s test.cилиgcc -c -g -Wa,-a,-ad test.c > test.txt
phuclv
1
Блоге объясняя это более подробно, в том числе версии одной-команды , как легенды и Lu'u вывешенным. Но почему -O0? Он полон загрузок / хранилищ, которые затрудняют отслеживание значения, и ничего не говорит о том, насколько эффективным будет оптимизированный код.
Я запускал G ++ из окна DOS на Win-XP против подпрограммы, содержащей неявное приведение
c:\gpp_code>g++-g -O -Wa,-aslh horton_ex2_05.cpp >list.txt
horton_ex2_05.cpp:Infunction`int main()':
horton_ex2_05.cpp:92: warning: assignment to `int' from `double'
Выходные данные представляют собой сгенерированный код, объединенный с исходным кодом C ++ (код C ++ отображается в виде комментариев в созданном потоке asm)
@Paladin - Не обязательно. ОП был посвящен получению выходного кода ассемблера, эквивалентного исходному коду C / C ++, он получил листинг, который, я согласен, более полезен для понимания того, что делает компилятор и оптимизатор. Но это приведет к тому, что сам ассемблер прекратит работу, так как он не ожидает номеров строк и компилирует байты, оставшиеся от инструкций по сборке.
Джесси Чисхолм
По крайней мере -O2, используйте те опции оптимизации, которые вы используете при создании проекта, если вы хотите увидеть, как gcc оптимизирует ваш код. (Или, если вы используете LTO, как и вы, то вам нужно разобрать вывод компоновщика, чтобы увидеть, что вы на самом деле получаете.)
Проверьте FAQ: «Также прекрасно задавать и отвечать на свои вопросы программирования». Дело в том, что теперь StackOverflow содержит вопросы и ответы в качестве ресурса для других.
Стив Джессоп
И, может быть, кто-то другой придет и удивит вас лучшим ответом, хотя мой иногда может быть немного многословным ...
PhirePhly
Есть даже кнопка ответа на свой вопрос.
Сиро Сантилли 郝海东 冠状 病 六四 事件 法轮功
13
Если то, что вы хотите увидеть, зависит от связывания выходных данных, тогда 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',@ARGVordie;
$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.
Тем не менее, этот скрипт - грязный хак, который не полностью конвертирует синтаксис. Например mov eax,ds:0x804b794, не очень NASMish. Кроме того, иногда он просто удаляет полезную информацию: movzx eax,[edx+0x1]оставляет читателю угадать, был ли операнд памяти byteили word.
Руслан
Чтобы разобрать синтаксис в NASM, используйте Agner Fog'sobjconv . Вы можете заставить его разбирать на стандартный вывод с выходным файлом = /dev/stdout, так что вы можете перейти lessк просмотру. Также есть ndisasm, но он разбирает только плоские двоичные файлы и не знает об объектных файлах (ELF / PE).
Питер Кордес
9
Как все уже отметили, используйте -Sопцию GCC. Я также хотел бы добавить, что результаты могут отличаться (дико!) В зависимости от того, добавляете ли вы опции оптимизации ( -O0ни для одного, -O2для агрессивной оптимизации).
В частности, на архитектурах RISC компилятор часто преобразует код практически до неузнаваемости при выполнении оптимизации. Это впечатляет и интересно смотреть на результаты!
Ну, как все говорили, используйте опцию -S. Если вы используете опцию -save-temps, вы также можете получить предварительно обработанный файл ( .i), файл сборки ( .s) и объектный файл (*. O). (получите каждый из них, используя -E, -S и -c.)
Также стоит взглянуть на семейство флагов -fdump-tree, в частности, -fdump-tree-all, которое позволяет увидеть некоторые промежуточные формы gcc. Они часто могут быть более удобочитаемыми, чем ассемблер (по крайней мере, для меня), и позволяют увидеть, как выполняются проходы оптимизации.
Я не вижу такой возможности среди ответов, возможно, потому что вопрос с 2008 года, но в 2018 году вы можете использовать онлайн-сайт Мэтта Голдболта https://godbolt.org
Если вы хотите сделать это для большого количества файлов, попробуйте вместо этого:
-save-temps=obj
который сохраняет промежуточные файлы в том же каталоге, что и -oвыходные данные объекта, вместо текущего рабочего каталога, что позволяет избежать потенциальных конфликтов базовых имен.
Еще одна интересная вещь об этой опции, если вы добавите -v:
gcc -save-temps -c -o main.o -v main.c
фактически он показывает явные файлы, которые используются вместо некрасивых временных /tmp, поэтому легко точно узнать, что происходит, включая этапы предварительной обработки / компиляции / сборки:
Для отображения в терминале используйте gcc foo.c -masm=intel -fverbose-asm -O3 -S -o- |less. -Sсам по себе создает foo.s.
Питер Кордес
2
недавно я хотел знать сборку каждой функции в программе,
вот как я это сделал.
$ 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
Здесь первая часть хранит вывод сборки программы с тем же именем файла, что и у Program, но с измененным расширением .s , вы можете открыть его как любой обычный текстовый файл.
Вторая часть здесь компилирует вашу программу для фактического использования и генерирует исполняемый файл для вашей Программы с указанным именем файла.
Program.c использованное выше название вашей программы и вывода является имя исполняемого вы хотите создать.
Ответы:
Используйте
-S
опцию для gcc (или g ++).Это запустит препроцессор (cpp) поверх helloworld.c, выполнит первоначальную компиляцию и затем остановится перед запуском ассемблера.
По умолчанию это выведет файл
helloworld.s
. Выходной файл все еще может быть установлен с помощью-o
опции.Конечно, это работает, только если у вас есть оригинальный источник. Альтернативой, если у вас есть только результирующий объектный файл, является использование
objdump
, установив--disassemble
параметр (или-d
для сокращенной формы).Этот параметр работает лучше всего, если для объектного файла включена опция отладки (
-g
во время компиляции), и файл не был удален.Запуск
file helloworld
даст вам некоторое представление об уровне детализации, который вы получите, используя objdump.источник
.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
Это сгенерирует ассемблерный код с переплетенными номерами кода C +, чтобы легче было увидеть, какие строки генерируют какой код:
Находится в разделе Алгоритмы для программистов , стр. 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
-O0
? Он полон загрузок / хранилищ, которые затрудняют отслеживание значения, и ничего не говорит о том, насколько эффективным будет оптимизированный код.Следующая командная строка из блога Кристиана Гарбина
Я запускал G ++ из окна DOS на Win-XP против подпрограммы, содержащей неявное приведение
Выходные данные представляют собой сгенерированный код, объединенный с исходным кодом C ++ (код C ++ отображается в виде комментариев в созданном потоке asm)
источник
-O2
, используйте те опции оптимизации, которые вы используете при создании проекта, если вы хотите увидеть, как gcc оптимизирует ваш код. (Или, если вы используете LTO, как и вы, то вам нужно разобрать вывод компоновщика, чтобы увидеть, что вы на самом деле получаете.)Используйте переключатель -S
или также с GCC
Также посмотрите это
источник
Если то, что вы хотите увидеть, зависит от связывания выходных данных, тогда objdump для выходного объектного файла / исполняемого файла также может быть полезен в дополнение к вышеупомянутому gcc -S. Вот очень полезный скрипт Лорен Мерритт, который преобразует синтаксис objdump по умолчанию в более читаемый синтаксис nasm:
Я подозреваю, что это также может быть использовано на выходе gcc -S.
источник
mov eax,ds:0x804b794
, не очень NASMish. Кроме того, иногда он просто удаляет полезную информацию:movzx eax,[edx+0x1]
оставляет читателю угадать, был ли операнд памятиbyte
илиword
.objconv
. Вы можете заставить его разбирать на стандартный вывод с выходным файлом =/dev/stdout
, так что вы можете перейтиless
к просмотру. Также естьndisasm
, но он разбирает только плоские двоичные файлы и не знает об объектных файлах (ELF / PE).Как все уже отметили, используйте
-S
опцию GCC. Я также хотел бы добавить, что результаты могут отличаться (дико!) В зависимости от того, добавляете ли вы опции оптимизации (-O0
ни для одного,-O2
для агрессивной оптимизации).В частности, на архитектурах RISC компилятор часто преобразует код практически до неузнаваемости при выполнении оптимизации. Это впечатляет и интересно смотреть на результаты!
источник
Ну, как все говорили, используйте опцию -S. Если вы используете опцию -save-temps, вы также можете получить предварительно обработанный файл ( .i), файл сборки ( .s) и объектный файл (*. O). (получите каждый из них, используя -E, -S и -c.)
источник
Как упоминалось ранее, посмотрите на флаг -S.
Также стоит взглянуть на семейство флагов -fdump-tree, в частности, -fdump-tree-all, которое позволяет увидеть некоторые промежуточные формы gcc. Они часто могут быть более удобочитаемыми, чем ассемблер (по крайней мере, для меня), и позволяют увидеть, как выполняются проходы оптимизации.
источник
Если вы ищете сборку LLVM:
источник
Я не вижу такой возможности среди ответов, возможно, потому что вопрос с 2008 года, но в 2018 году вы можете использовать онлайн-сайт Мэтта Голдболта https://godbolt.org
Вы также можете локально git clone и запустить его проект https://github.com/mattgodbolt/compiler-explorer
источник
-save-temps
Это было упомянуто на https://stackoverflow.com/a/17083009/895245, но позвольте мне далее проиллюстрировать это.
Большим преимуществом этой опции
-S
является то, что ее очень легко добавить в любой скрипт сборки, не сильно влияя на саму сборку.Когда вы делаете:
main.c
и теперь, кроме обычного вывода
main.o
, текущий рабочий каталог также содержит следующие файлы:main.i
является бонусом и содержит предварительно оцененный файл:main.s
содержит желаемую сгенерированную сборку:Если вы хотите сделать это для большого количества файлов, попробуйте вместо этого:
который сохраняет промежуточные файлы в том же каталоге, что и
-o
выходные данные объекта, вместо текущего рабочего каталога, что позволяет избежать потенциальных конфликтов базовых имен.Еще одна интересная вещь об этой опции, если вы добавите
-v
:фактически он показывает явные файлы, которые используются вместо некрасивых временных
/tmp
, поэтому легко точно узнать, что происходит, включая этапы предварительной обработки / компиляции / сборки:Протестировано в Ubuntu 19.04 amd64, GCC 8.3.0.
источник
Используйте опцию -S:
источник
От: http://www.delorie.com/djgpp/v2faq/faq8_20.html
gcc -c -g -Wa, -a, -ad [другие опции GCC] foo.c> foo.lst
в качестве альтернативы ответу PhirePhly или просто используйте -S, как все сказали.
источник
Вот шаги, чтобы увидеть / распечатать ассемблерный код любой программы на C в вашей Windows
консоль / терминал / командная строка:
Напишите C-программу в редакторе C-кода, например, кодовые блоки, и сохраните ее с расширением .c
Скомпилируйте и запустите его.
После успешного запуска перейдите в папку, в которую вы установили компилятор gcc, и введите
Следующая команда, чтобы получить файл .s из файла .c
C: \ gcc> gcc -S полный путь к C-файлу ENTER
Пример команды (как в моем случае)
C: \ gcc> gcc -SD: \ Aa_C_Certified \ alternate_letters.c
Это выводит файл «.s» исходного файла «.c»
4 После этого введите следующую команду
C; \ gcc> cpp filename.s ENTER
Пример команды (как в моем случае)
C; \ gcc> cpp alternate_letters.s
Это напечатает / выведет весь код на ассемблере вашей C-программы.
источник
Используйте «-S» в качестве опции. Он отображает вывод сборки в терминале.
источник
gcc foo.c -masm=intel -fverbose-asm -O3 -S -o- |less
.-S
сам по себе создаетfoo.s
.недавно я хотел знать сборку каждой функции в программе,
вот как я это сделал.
источник
Вот решение для C с использованием gcc:
Здесь первая часть хранит вывод сборки программы с тем же именем файла, что и у Program, но с измененным расширением .s , вы можете открыть его как любой обычный текстовый файл.
Вторая часть здесь компилирует вашу программу для фактического использования и генерирует исполняемый файл для вашей Программы с указанным именем файла.
Program.c использованное выше название вашей программы и вывода является имя исполняемого вы хотите создать.
Кстати, это мой первый пост на StackOverFlow: -}
источник