Как просмотреть сборку за кодом с помощью Visual C ++? - PullRequest
104 голосов
/ 20 июня 2009

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

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

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

Ответы [ 8 ]

140 голосов
/ 20 июня 2009

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

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

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

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

26 голосов
/ 20 июня 2009

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

21 голосов
/ 20 июня 2009

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


  • / FA Сборочный код; .asm
  • / FAc Машинный и монтажный код; .COD
  • / FA Исходный и монтажный код; .asm
  • / FAcs Код машины, исходного кода и сборки; .COD
9 голосов
/ 20 июня 2009

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

6 голосов
/ 09 февраля 2016

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

Проводник компилятора Godbolt предназначен для удобного форматирования вывода asm компилятора, удаляя «шум» директив, поэтому я настоятельно рекомендую использовать его для поиска в 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 будет намного меньше общего машинного кода.)

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

4 голосов
/ 12 февраля 2012

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

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

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

4 голосов
/ 20 июня 2009

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

1 голос
/ 20 июня 2009

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

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

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