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

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

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

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

11 ответов

Решение

Есть несколько подходов:

  1. Обычно вы можете увидеть ассемблерный код при отладке C++ в Visual Studio (и также затмить). Для этого в Visual Studio установите точку останова для рассматриваемого кода, и когда отладчик нажмет его, щелкните правой кнопкой мыши и найдите "Перейти к сборке" (или нажмите CTRL+ALT+D).

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

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

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


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

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

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

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

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

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

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

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

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

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

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

Если вы говорите об отладке, чтобы увидеть код сборки, самый простой способ - это Debug->Windows->Disassembly (или Alt-8). Это позволит вам войти в вызываемую функцию и остаться в разборке.

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

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

Использование Visual Studio 6.0

Нажмите на пункт меню «Проект».

Нажмите "Настройки".

Выбрать заголовок вкладки C / C++

В разделе «Тип файла списка» измените поле со списком с «Нет в списке» на «Сборка с машинным кодом».

Файлы исходного кода сборки появятся в папке «Release» в виде файлов .cod.

Если вы пытаетесь увидеть коды операций, а также адрес и мнемонику ассемблера, щелкните правой кнопкой мыши одну из строк ассемблера и в меню выберите «Показать байты кода».

Другие вопросы по тегам