Як переглянути збірку за кодом за допомогою Visual C ++?


117

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

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

Отже, як я бачу код складання за програмою, написаною мовами вищого рівня, такими як C ++ та Visual Basic?


Це називається список складання в msvc, як вже згадували інші. Я створив простий плагін, додаючи записи до контекстного меню редактора, щоб автоматизувати ці нудні кроки: marketplace.visualstudio.com/items?itemName=Trass3r.DevUtils
Trass3r

Відповіді:


149

Існує кілька підходів:

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

  2. Другий підхід полягає у створенні списків складання під час компіляції. Для цього перейдіть до налаштувань проекту -> C / C ++ -> Файли виводу -> Розташування списку ASM та заповніть ім'я файлу. Виберіть також "Виведення з монтажу" до "Збір з вихідним кодом".

  3. Складіть програму та використовуйте будь-який сторонній налагоджувач. Ви можете використовувати OllyDbg або WinDbg для цього. Також ви можете використовувати IDA (інтерактивний розбирач). Але це жорсткий спосіб зробити це.


5
Зверніть увагу, що підхід №2 не працює при складанні статичної бібліотеки з увімкненою оптимізацією для всіх програм (як мінімум у VS2010). Що має сенс - компілятор ще не створив остаточний код.
dhaffey

3
Його називають "Goto Disassembly" у Visual Studio 2017
Маттіас

З підходом №2, як я бачу збірку?
користувач1507435

Потрібно побачити .asm файл у режимі налагодження, якщо ви використовували місце за замовчуванням.
користувач3015682

28

Додаткова примітка: велика різниця між виходом асемблера налагодження та випуском одного. Перший добре дізнатися, як компілятор виробляє код асемблера з C ++. Другий - добре дізнатися, як компілятор оптимізує різні C ++ конструкції. У цьому випадку деякі перетворення С ++ на асм не очевидні.


Я помітив, що при розбиранні виконуваної програми Debug, здається, розпаковується код під час його запуску, у версії Release цього не відбувається. Також при відкритті обох із PEiD просто налагоджена версія показує "Microsoft Visual C ++ 8.0 [Debug]".
jyz

9
Це абсолютно правда. Але це зовсім не відповідає на питання.
imallett

25

Вкажіть перемикач / FA для компілятора cl. Залежно від значення комутатора інтегрується лише код складання або код високого рівня та код складання. Ім'я файлу отримує розширення .asm. Ось підтримувані значення:


  • / Код Асамблеї FA; .азм
  • / Код машини та збірки FAc; .cod
  • / Вихідний та збірний код ФА; .азм
  • / FAcs код машини, джерела та збірки; .cod

10

Найпростіший спосіб - запустити налагоджувач і перевірити вікно демонтажу .


8

Рання версія цієї відповіді ("хак" для 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/, але не на основному веб-сайті, але зараз він є на обох.


Щоб отримати вихід 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. (Хоча використання ЗОГО :: рядки і лічильника підштовхування запуску для цих цілей! Деякий C-стиль рядок маніпуляції , що робить більше припущень про послідовність це обробки (і ігнорує макс довжиною безпеки / розподіл, використовуючи великий буфер) в результаті GetModuleFileNameAWould бути набагато меншим загальним машинним кодом.)

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


@MichaelPetch: о, виявляється, це те, що я спробував. .c_str()друкує те, що схоже на вказівник. Якщо ви перейдете за посиланням, ви побачите код для hexdump a std::string(вимкнено #if 0). Виявляється, рядок добре, але coutне потрапляє до веб-браузера. Немає жодних символів, які не є ascii, лише зворотні риски.
Пітер Кордес

Я міг би бути що - то відсутня , але коли ви зробили subdir--; p /= *subdir;ви не зменшити р на тільки ім'я файлу? А може, я нерозумію те, що ви намагаєтеся надрукувати.
Майкл Петч

Я думаю, я не зовсім розумію, за subdir--яким пішов, p /= *subdirколи subdirбув спочаткуp.end()
Майкл Петч

@MichaelPetch: оновлені коментарі. Мені потрібно було отримати останній компонент каталогу шляху, який слід використовувати як ім'я файлу. Це працює, але мені знадобилося багато часу, тому що я думав, що GetModuleFileNameAпросто повертаюся a.exe. Це було, доки я не впустив це в дію і надрукував довжину, яку я знав, що це працює, і я міг змусити програму маніпулювати контуром, я просто не міг надрукувати шлях
Пітер Кордес,

1
Так, здається, \\r(добре, \rколи компілятор виводить її) частина імені файлу, яку вона погано переклала при візуалізації для веб-браузера. Використовуючи p.generic_string()роботи, але косою косою рисою є нахил вперед.
Майкл Петч

5

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


5

Для MSVC можна використовувати лінкер.

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

foo.pdb повинен бути доступний, щоб отримати символи


1

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

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


2
Примітка. Застосовується лише для керованих збірок, щоб не розбирати, як у асемблері, asm.
sean e

Добре, я читаю це як "два рядки коду однакові в зборі", а не "чи два рядки коду однакові в зборах"
Дейв Л

Він буде працювати лише в додатках dotnet, а не в Visual C ++-лінкері чи компіляторі.
Мухаммед Алі

1

Якщо ви говорите про налагодження, щоб побачити код складання, найпростішим способом є налагодження-> Windows-> демонтаж (або Alt-8). Це дозволить вам вступити в функцію, що називається, і залишитися в розборці.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.