Как просмотреть сборку за кодом с помощью Visual C++?
Я читал еще один вопрос, касающийся эффективности двух строк кода, и ОП сказал, что он посмотрел на сборку за кодом, и обе строки были идентичны в сборке. Отступление в сторону, как я могу просмотреть ассемблерный код, созданный при компиляции программы.
Я использую Microsoft Visual C++, но я также хотел бы знать, возможно ли просмотреть сборку за кодом, написанным на Visual Basic.
Итак, как мне посмотреть ассемблерный код программы, написанной на языках более высокого уровня, таких как C++ и Visual Basic?
11 ответов
Есть несколько подходов:
Обычно вы можете увидеть ассемблерный код при отладке C++ в Visual Studio (и также затмить). Для этого в Visual Studio установите точку останова для рассматриваемого кода, и когда отладчик нажмет его, щелкните правой кнопкой мыши и найдите "Перейти к сборке" (или нажмите CTRL+ALT+D).
Второй подход заключается в создании списков сборок во время компиляции. Для этого зайдите в настройки проекта -> C/C++ -> Output Files -> ASM List Location и введите имя файла. Также выберите "Сборочный вывод" в "Сборка с исходным кодом".
Скомпилируйте программу и используйте любой сторонний отладчик. Вы можете использовать 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.
Если вы пытаетесь увидеть коды операций, а также адрес и мнемонику ассемблера, щелкните правой кнопкой мыши одну из строк ассемблера и в меню выберите «Показать байты кода».