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


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

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

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

8 90

8 ответов:

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

  1. обычно вы можете видеть ассемблерный код при отладке C++ в visual studio (и eclipse тоже). Для этого в Visual Studio поставьте точку останова на рассматриваемом коде и когда отладчик ударит по нему rigth нажмите и найдите "перейти к сборке" (или нажмите CTRL+ALT+D )

  2. второй подход заключается в создании списков сборок при компиляции. Для этого перейдите в настройки проекта - > C / C++ - > выходные файлы - > расположение списка ASM и заполните имя файла. Также выберите " вывод сборки "в"сборка с исходным кодом".

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

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

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


  • / FA Assembly code; .АСМ
  • / FAc машинный и сборочный код; .треска
  • / Fas исходный и ассемблерный код; .АСМ
  • / FAcs машина, источник и код сборки;.треска

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

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

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

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


чтобы получить вывод MSVC asm из 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\bar34\a.exe 
    // into      c:\foo\bar3434.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 и boost противоречит этим целям! Некоторые строковые манипуляции в стиле C, которые делают больше предположений о строке, которую он обрабатывает (и игнорирует безопасность максимальной длины / выделение с помощью большого буфера) на результат GetModuleFileNameA было бы гораздо меньше общего машинного кода.)

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

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

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

ссылка.exe / dump /linenumbers /disasm / out:foo.Дис фу.dll

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

рефлектор .NET Красных Ворот это довольно удивительный инструмент, который помог мне больше, чем несколько раз. Плюсом этой утилиты за пределами простого показа MSIL является то, что вы можете анализировать множество сторонних DLL и иметь отражатель, который заботится о преобразовании MSIL в C# и VB.

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