如何使用Visual C++查看代码背后的程序集?

111 assembly visual-c++

我正在阅读另一个关于两行代码效率的问题,OP说他看了代码背后的程序集,两行在程序集中是相同的.除了离题之外,我如何查看编译程序时创建的汇编代码.

我正在使用Microsoft的Visual C++,但我也想知道是否可以查看用Visual Basic编写的代码后面的程序集.

那么,如何查看用C++和Visual Basic等高级语言编写的程序背后的汇编代码?

ina*_*ruk 143

有几种方法:

  1. 你可以在visual studio中调试C++时看到汇编代码(也可以看到eclipse).为此,在Visual Studio中为相关代码设置断点,当调试器点击它时,点击并找到"Go To Assembly"(或按CTRL + ALT + D)

  2. 第二种方法是在编译时生成汇编列表.为此,请转到项目设置 - > C/C++ - >输出文件 - > ASM列表位置并填写文件名.同时选择"装配输出"到"使用源代码装配".

  3. 编译程序并使用任何第三方调试程序.您可以使用OllyDbg或WinDbg.您也可以使用IDA(交互式反汇编程序).但这是做这件事的核心方式.

  • 请注意,在编译启用了整个程序优化的静态库时,方法#2不起作用(至少在VS2010中).这是有道理的 - 编译器尚未生成最终代码. (5认同)
  • 它在Visual Studio 2017中称为"Goto Disassembly" (3认同)

Vla*_*zan 28

补充说明:Debug汇编程序输出和Release 1之间存在很大差异.第一个是很好的学习编译器如何从C++生成汇编代码.第二个是很好的学习编译器如何优化各种C++结构.在这种情况下,一些C++ - to-asm转换并不明显.

  • 这绝对是真的.但它根本没有回答这个问题. (9认同)

ste*_*eve 22

为cl编译器指定/ FA开关.根据交换机的值,只集成汇编代码或高级代码和汇编代码.文件名获取.asm文件扩展名.以下是支持的值:


  • / FA汇编代码; .ASM
  • / FAc机器和汇编代码; .COD
  • / FAs源代码和汇编代码; .ASM
  • / FAcs机器,源和汇编代码; .COD


dia*_*pir 10

最简单的方法是触发调试器并检查反汇编窗口.


Pet*_*des 7

这个答案的早期版本(rextester.com的"hack")现在大多数是多余的,因为http://gcc.godbolt.org/为ARM,x86和x86-64 提供了CL 19 RC(针对Windows调用约定) ,不像那个网站上的gcc,clang和icc).

Godbolt编译器浏览器设计用于很好地格式化编译器asm输出,删除指令的"噪音",因此我强烈建议使用它来查看asm以获取带有args并返回值的简单函数(因此它们不会优化了).

有一段时间,CL可以在http://gcc.beta.godbolt.org/上找到,但不是主站点,但现在它都在两者上.


要从http://rextester.com/l/cpp_online_compiler_visual在线编译器获取MSVC asm输出:添加/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 ...
Run Code Online (Sandbox Code Playgroud)

type是DOS版本的cat.我不想包含更多的代码,这些代码会更难找到我想要查看asm的函数.(虽然使用的std :: string,促进违背这些目标!某些C风格的字符串操作,使得关于它的处理(和字符串更多的假设通过对结果使用大缓存)忽略最大长度安全/配置GetModuleFileNameA会总机器代码要少得多.)

IDK为什么,但cout << p.string() << endl只显示基名(即文件名,没有目录),即使打印它的长度显示它不仅仅是裸名.(Ubuntu 15.10上的Chromium48).cout在程序的stdout和Web浏览器之间,或者在程序的stdout和Web浏览器之间可能存在一些反斜杠转义处理.


小智 5

在Visual C ++中,我相信“输出文件”下的项目选项有一个选项,用于输出带有源代码的ASM清单。因此,您将在同一文件中看到C / C ++源代码和生成的ASM。


Ste*_*ner 5

对于MSVC,您可以使用链接器。

link.exe /转储/行号/disasm/out:foo.dis foo.dll

foo.pdb需要可用于获取符号