Как просмотреть сборку за кодом с помощью Visual С++?

Я читал еще один вопрос, касающийся эффективности двух строк кода, и OP сказал, что он посмотрел на сборку за кодом, и обе линии были идентичны в сборке. Отвлечение в сторону, как я мог просмотреть код сборки, созданный при компиляции программы.

Я использую Microsoft Visual С++, но мне также хотелось бы узнать, можно ли просмотреть сборку за кодом, написанным на Visual Basic.

Итак, как мне просмотреть код сборки за программой, написанной на языках более высокого уровня, таких как С++ и Visual Basic?

Ответ 1

Существует несколько подходов:

  • Обычно вы можете увидеть код сборки во время отладки С++ в visual studio (и затмение тоже). Для этого в Visual Studio поставьте точку останова на код, о котором идет речь, и когда отладчик ударит его по щелчку и найдите "Go To Assembly" (или нажмите CTRL + ALT + D)

  • Второй подход заключается в создании списков сборки при компиляции. Для этого перейдите к настройкам проекта → C/С++ → Output Files → ASM List Location и заполните имя файла. Также выберите "Сборочный вывод" на "Сборка с исходным кодом".

  • Скомпилируйте программу и используйте сторонний отладчик. Вы можете использовать OllyDbg или WinDbg для этого. Также вы можете использовать IDA (интерактивный дизассемблер). Но это хардкорный способ сделать это.

Ответ 2

Дополнительное примечание: существует большая разница между выходом ассемблера Debug и Release one. Первый из них хорош, чтобы узнать, как компилятор создает код ассемблера с С++. Во-вторых, хорошо узнать, как компилятор оптимизирует различные конструкции С++. В этом случае некоторые преобразования С++-to-asm не очевидны.

Ответ 3

Укажите ключ /FA для компилятора cl. В зависимости от значения коммутатора интегрируется только код сборки или код высокого уровня и код сборки. Имя файла получает расширение .asm файла. Вот поддерживаемые значения:


  • /код сборки FA;.asm
  • /FAc Машина и код сборки;.COD
  • /FAs Код источника и сборки;.asm
  • /FAcs Машина, источник и код сборки;.COD

Ответ 4

Самый простой способ - запустить отладчик и проверить окно разборки.

Ответ 5

Более ранняя версия этого ответа ( "взломать" для rextester.com) в основном избыточна, теперь http://gcc.godbolt.org/ предоставляет CL 19 RC для ARM, x86 и x86-64 (ориентируясь на соглашение о вызове Windows, в отличие от gcc, clang и icc на этом сайте).

Исследователь компилятора Godbolt разработан для удобного форматирования компилятора asm output, устраняя "шум" директив, поэтому я настоятельно рекомендую использовать его для просмотра asm для простых функций, которые принимают аргументы и возвращают значение (поэтому они выиграли 't быть оптимизированным прочь).

Некоторое время CL был доступен на http://gcc.beta.godbolt.org/, но не на главном сайте, но теперь он на обоих.


Чтобы получить вывод ASM из MSVC из http://rextester.com/l/cpp_online_compiler_visual онлайн-компилятор: добавьте /FAs в параметры командной строки. Попросите свою программу найти свой собственный путь и выработать путь к .asm и сбросить его. Или запустите дизассемблер на .exe.

например. http://rextester.com/OKI40941

#include <string>
#include <boost/filesystem.hpp>
#include <Windows.h>

using namespace std;

static string my_exe(void){
    char buf[MAX_PATH];
    DWORD tmp = GetModuleFileNameA( NULL, // self
                                  buf, MAX_PATH);
    return buf;
}

int main() {
    string dircmd = "dir ";
    boost::filesystem::path p( my_exe() );
    //boost::filesystem::path dir = p.parent_path();

    // transform c:\foo\bar\1234\a.exe 
    // into      c:\foo\bar\1234\1234.asm
    p.remove_filename();
    system ( (dircmd + p.string()).c_str() );

    auto subdir = p.end();      // pointing at one-past the end
    subdir--;                   // pointing at the last directory name
    p /= *subdir;               // append the last dir name as a filename
    p.replace_extension(".asm");
    system ( (string("type ") + p.string()).c_str() );
//    std::cout << "Hello, world!\n";
}

... code of functions you want to see the asm for goes here ...

type - это версия DOS cat. Я не хотел включать больше кода, который затруднял бы поиск функций, которые я хотел увидеть для asm. (Хотя использование std::string и ускорение запуска счетчика для этих целей! Некоторые C-стиль строки манипуляции, которая делает больше предположений о обрабатываемой им строке (и игнорирует безопасность/распределение максимальной длины с помощью большого буфера) по результату GetModuleFileNameA будет намного меньше всего машинного кода.)

IDK почему, но cout << p.string() << endl показывает только базовое имя (то есть имя файла, без каталогов), хотя печать его длины показывает не просто голого имени. (Chromium48 на Ubuntu 15.10). Вероятно, в какой-то момент в cout, или между программой stdout и веб-браузером, может быть обработана некоторая обратная косая черта.

Ответ 6

В Visual С++ параметры проекта в разделе "Выходные файлы", на которые я верю, имеют возможность выводить список ASM с исходным кодом. Таким образом, вы увидите исходный код C/С++ и итоговую ASM в одном файле.

Ответ 7

Для MSVC вы можете использовать компоновщик.

link.exe/dump/linenumbers/disasm/out:foo.dis foo.dll

foo.pdb должен быть доступен для получения символов

Ответ 8

Red Gate.NET Reflector - довольно устрашающий инструмент, который помог мне больше, чем несколько раз. Плюс к этой утилите за пределами простой демонстрации вашего MSIL заключается в том, что вы можете анализировать множество сторонних DLL и рефлектор заботится о преобразовании MSIL в С# и VB.

Я не обещаю, что код будет таким же понятным, как и исходный, но вы не должны сильно беспокоиться о нем.