Come visualizzare l’assembly dietro il codice utilizzando Visual C ++?

Stavo leggendo un’altra domanda riguardante l’efficienza di due righe di codice, e l’OP ha detto che ha guardato l’assemblea dietro il codice ed entrambe le linee erano identiche in assemblea. Digressione a parte, come potrei vedere il codice assembly creato quando un programma è compilato.

Sto usando Microsoft Visual C ++, ma vorrei anche sapere se è ansible visualizzare l’assembly dietro il codice scritto in Visual Basic.

Quindi, come posso visualizzare il codice assembly dietro un programma scritto in linguaggi di livello superiore come C ++ e Visual Basic?

Ci sono diversi approcci:

  1. Normalmente si può vedere il codice assembly durante il debug di C ++ in Visual Studio (ed anche eclipse). Per questo in Visual Studio inserire un punto di interruzione sul codice in questione e quando il debugger fa clic su di esso, fai clic su “Vai a gruppo” (o premi CTRL + ALT + D)

  2. Il secondo approccio consiste nel generare elenchi di assiemi durante la compilazione. Per questo vai alle impostazioni del progetto -> C / C ++ -> File di output -> Posizione elenco ASM e inserisci il nome del file. Seleziona anche “Output di assembly” su “Assemblaggio con codice sorgente”.

  3. Compilare il programma e utilizzare qualsiasi debugger di terze parti. Puoi usare OllyDbg o WinDbg per questo. Inoltre è ansible utilizzare IDA (disassemblatore interattivo). Ma questo è un modo hardcore per farlo.

Nota aggiuntiva: c’è una grande differenza tra l’output dell’assembler di Debug e quello di rilascio uno. Il primo è utile per imparare come il compilatore produce codice assembler da C ++. Il secondo è utile per imparare come il compilatore ottimizza vari costrutti C ++. In questo caso alcune trasformazioni C ++-to-asm non sono ovvie.

Specificare l’opzione / FA per il compilatore cl. A seconda del valore dello switch, sono integrati solo il codice assembly o codice di alto livello e codice assembly. Il nome del file ottiene estensione del file .asm. Ecco i valori supportati:


  • / Codice assembly FA; .asm
  • / FAc Macchina e codice assembly; .merluzzo
  • / Fonti Codice sorgente e assembly; .asm
  • / FAcs Macchina, codice sorgente e assieme; .merluzzo

Il modo più semplice è sparare al debugger e controllare la finestra di disassemblaggio .

La versione precedente di questa risposta (un “hack” per rextester.com) è per lo più ridondante ora che http://gcc.godbolt.org/ fornisce CL 19 RC per ARM, x86 e x86-64 (che si rivolge alla convenzione di chiamata di Windows , a differenza di gcc, clang e icc su quel sito).

Il explorer del compilatore Godbolt è progettato per una buona formattazione dell’output del compilatore asm, rimuovendo il “rumore” delle direttive, quindi raccomando vivamente di usarlo per guardare asm per funzioni semplici che accettano argomenti e restituiscono un valore (quindi non saranno ottimizzato via).

Per un po ‘, CL era disponibile su http://gcc.beta.godbolt.org/ ma non sul sito principale, ma ora è su entrambi.


Per ottenere l’output MSVC asm dal compilatore online http://rextester.com/l/cpp_online_compiler_visual : Aggiungi /FAs alle opzioni della riga di comando. Fai in modo che il tuo programma trovi il proprio percorso e .asm il percorso verso il .asm e lo .asm . Oppure esegui un disassemblatore su .exe .

ad es. http://rextester.com/OKI40941

 #include  #include  #include  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 è la versione DOS di cat . Non volevo includere più codice che rendesse più difficile trovare le funzioni per le quali volevo vedere l'asm. (Sebbene std :: string e boost eseguano il conteggio di questi obiettivi! Qualche manipolazione di stringhe in stile C che fa più ipotesi sulla stringa che sta elaborando (e ignora la sicurezza / allocazione di lunghezza massima usando un grande buffer) sul risultato di GetModuleFileNameA sarebbe molto meno codice macchina totale.)

IDK perché, ma cout << p.string() << endl mostra solo il basename (cioè il nome del file, senza le directory), anche se la stampa della sua lunghezza mostra che non è solo il nome nudo. (Chromium48 su Ubuntu 15.10). Probabilmente c'è qualche operazione di backslash-escape a un certo punto in cout , o tra lo stdout del programma e il browser web.

In Visual C ++ le opzioni del progetto sotto, Output Files credo abbia un’opzione per l’output dell’elenco ASM con il codice sorgente. Quindi vedrai il codice sorgente C / C ++ e l’ASM risultante tutti nello stesso file.

Per MSVC puoi usare il linker.

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

foo.pdb deve essere disponibile per ottenere i simboli

.NET Reflector di Red Gate è uno strumento davvero eccezionale che mi ha aiutato a risolvere più volte. Il lato positivo di questa utility al di fuori della semplice visualizzazione di MSIL è che è ansible analizzare molte DLL di terze parti e far sì che Reflector si occupi della conversione di MSIL in C # e VB.

Non sto promettendo che il codice sarà chiaro come sorgente ma non dovresti avere molti problemi a seguirlo.