我正在阅读另一个有关两行代码的效率的问题,OP表示他查看了代码后面的汇编,并且这两行在汇编中是相同的。除了题外话,我如何查看编译程序时创建的汇编代码。
我正在使用Microsoft的Visual C ++,但我也想知道是否可以查看用Visual Basic编写的代码背后的程序集。
那么,如何查看用高级语言(如C ++和Visual Basic)编写的程序背后的汇编代码?
我正在阅读另一个有关两行代码的效率的问题,OP表示他查看了代码后面的汇编,并且这两行在汇编中是相同的。除了题外话,我如何查看编译程序时创建的汇编代码。
我正在使用Microsoft的Visual C ++,但我也想知道是否可以查看用Visual Basic编写的代码背后的程序集。
那么,如何查看用高级语言(如C ++和Visual Basic)编写的程序背后的汇编代码?
Answers:
有几种方法:
您通常可以在Visual Studio中调试C ++时(也可以在Eclipse中)看到汇编代码。为此,在Visual Studio中,在有问题的代码上放置一个断点,并在调试器点击它时立即单击并找到“转到程序集”(或按CTRL + ALT + D)
第二种方法是在编译时生成程序集列表。为此,请转到项目设置-> C / C ++->输出文件-> ASM列表位置,然后填写文件名。还要选择“汇编输出”到“用源代码汇编”。
编译程序并使用任何第三方调试器。您可以为此使用OllyDbg或WinDbg。您也可以使用IDA(交互式反汇编程序)。但这是做到这一点的硬性方法。
由于http://gcc.godbolt.org/为ARM,x86和x86-64(针对Windows调用约定)提供了CL 19 RC,因此该答案的较早版本(rextester.com的“ hack”)大部分是多余的。,与该网站上的gcc,clang和icc不同)。
Godbolt编译器资源管理器旨在很好地格式化编译器的asm输出格式,消除了指令的“噪音”,因此,我强烈建议使用它来查看带有args并返回值的简单函数的asm(因此它们不会优化掉)。
有一段时间,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 ...
type
是的DOS版本cat
。我不想包含更多的代码,这将使查找我想要查看asm的功能变得更加困难。(虽然使用的std :: string和升压背道而驰的那些目标!某些C风格的字符串操作,使得关于它的处理(和字符串更多的假设通过对结果使用大缓存)忽略最大长度安全/配置GetModuleFileNameA
会少得多的总机器代码。)
IDK为什么,但cout << p.string() << endl
仅显示基本名称(即文件名,不包含目录),即使打印其长度显示它也不只是裸名。(在Ubuntu 15.10上为Chromium48)。在中的某个位置cout
或程序的stdout与网络浏览器之间可能存在一些反斜杠转义处理。
.c_str()
打印看起来像指针的东西。如果您点击链接,则会看到将a十六进制转储的代码std::string
(已禁用#if 0
)。事实证明,该字符串很好,但cout
没有将其发送到Web浏览器。也没有任何非ASCII字符,只是反斜杠。
subdir--; p /= *subdir;
是否将p减小为仅文件名?也许我误会了您要打印的内容。
subdir--
随后的p /= *subdir
时间subdir
是什么时间p.end()
GetModuleFileNameA
只是回来了a.exe
。直到我将其十六进制转储并打印出我知道它正在工作的长度,然后我才可以让程序来操纵路径,我只是无法打印出路径
\\r
(\r
当编译器输出时),在为Web浏览器渲染时,文件名翻译不佳。使用p.generic_string()
Works,但反斜杠为正斜杠。