[visual-c++] How to view the assembly behind the code using Visual C++?

I was reading another question pertaining the efficiency of two lines of code, and the OP said that he looked at the assembly behind the code and both lines were identical in assembly. Digression aside, how could I view the assembly code created when a program is compiled.

I'm using Microsoft's Visual C++, but I would also like to know if it's possible to view the assembly behind code written in Visual Basic.

So, how do I view the assembly code behind a program written in higher level languages like C++ and Visual Basic?

This question is related to visual-c++ assembly

The answer is


There are several approaches:

  1. You can normally see assembly code while debugging C++ in visual studio (and eclipse too). For this in Visual Studio put a breakpoint on code in question and when debugger hits it rigth click and find "Go To Assembly" ( or press CTRL+ALT+D )

  2. Second approach is to generate assembly listings while compiling. For this go to project settings -> C/C++ -> Output Files -> ASM List Location and fill in file name. Also select "Assembly Output" to "Assembly With Source Code".

  3. Compile the program and use any third-party debugger. You can use OllyDbg or WinDbg for this. Also you can use IDA (interactive disassembler). But this is hardcore way of doing it.


Red Gate's .NET Reflector is a pretty awesome tool that has helped me out more than a few times. The plus side of this utility outside of easily showing you MSIL is that you can analyze a lot of third-party DLLs and have the Reflector take care of converting MSIL to C# and VB.

I'm not promising the code will be as clear as source but you shouldn't have much trouble following it.


For MSVC you can use the linker.

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

foo.pdb needs to be available to get symbols


The easiest way is to fire the debugger and check the disassembly window.


If you are talking about debugging to see the assembly code, the easiest way is Debug->Windows->Disassembly (or Alt-8). This will let you step into a called function and stay in Disassembly.


In Visual C++ the project options under, Output Files I believe has an option for outputing the ASM listing with source code. So you will see the C/C++ source code and the resulting ASM all in the same file.


Specify the /FA switch for the cl compiler. Depending on the value of the switch either only assembly code or high-level code and assembly code is integrated. The filename gets .asm file extension. Here are the supported values:


  • /FA Assembly code; .asm
  • /FAc Machine and assembly code; .cod
  • /FAs Source and assembly code; .asm
  • /FAcs Machine, source, and assembly code; .cod

The earlier version of this answer (a "hack" for rextester.com) is mostly redundant now that http://gcc.godbolt.org/ provides CL 19 RC for ARM, x86, and x86-64 (targeting the Windows calling convention, unlike gcc, clang, and icc on that site).

The Godbolt compiler explorer is designed for nicely formatting compiler asm output, removing the "noise" of directives, so I'd highly recommend using it to look at asm for simple functions that take args and return a value (so they won't be optimized away).

For a while, CL was available on http://gcc.beta.godbolt.org/ but not the main site, but now it's on both.


To get MSVC asm output from the http://rextester.com/l/cpp_online_compiler_visual online compiler: Add /FAs to the command line options. Have your program find its own path and work out the path to the .asm and dump it. Or run a disassembler on the .exe.

e.g. 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 is the DOS version of cat. I didn't want to include more code that would make it harder to find the functions I wanted to see the asm for. (Although using std::string and boost run counter to those goals! Some C-style string manipulation that makes more assumptions about the string it's processing (and ignores max-length safety / allocation by using a big buffer) on the result of GetModuleFileNameA would be much less total machine code.)

IDK why, but cout << p.string() << endl only shows the basename (i.e. the filename, without the directories), even though printing its length shows it's not just the bare name. (Chromium48 on Ubuntu 15.10). There's probably some backslash-escape processing at some point in cout, or between the program's stdout and the web browser.


Additional note: there is big difference between Debug assembler output and Release one. The first one is good to learn how compiler produces assembler code from C++. The second one is good to learn how compiler optimizes various C++ constructs. In this case some C++-to-asm transformations are not obvious.