MyException - 我的异常网
当前位置:我的异常网» VSTS » [译]怎样用VisualStudio查看非托管代码 解决思路

[译]怎样用VisualStudio查看非托管代码 解决思路

www.MyException.Cn  网友分享于:2013-03-01  浏览:27次
[译]怎样用VisualStudio查看非托管代码 - 软件工程/管理 / 休闲广场
http://yizhu2000.cnblogs.com
[译]怎样用VisualStudio查看非托管代码 
(译者:这篇文章作者是一位美国的MVP,这是他的系列文章"Under the cover"的第一篇,文章的本意从最底层的角度来优化代码的性能,并作为阅读作者其他文章的技术基础,这种通过这样的做法虽然初看起来有些过分,但是对读者了解.Net许多底层运作是十分有益的) 

我们从使用visual studio进行非托管代码调试的基础开始,以便大家可以更容易的学习今后的例子,并让这篇文章作为我以后文章的基础,虽然我也使用windbg,但visual studio已经成为了一个功能强大的调试工具,对于简单的代码优化问题反而更容易使用 

当我们需要校调对性能要求很高的代码时,查看IL通常不是最好的做法,因为JIT优化器会默默的优化我们的代码,使用reflector或者ildasm你能很快发现release和debug模式下产生的IL代码几乎完全相同,那么是什么让release模式的代码运行起来如此迅速呢?这就是JIT优化的结果,通过查看managed代码(IL代码),我们没有办法看到这些优化,所以我们将通过native code(本地代码)来查找蛛丝马迹。 

必须说明我不提倡大家经常这样做,我不赞成过早的进行优化,你必须使你的代码先工作起来,你必须清楚的知道哪些代码是不值得优化的,当你的代码完成后再来找那些需要提速的地方,当你发现有的地方10% 的代码却使用了70%的时间的时候,再回过头去优化那10%的代码.同时你总是应该把判断的依据建立在对速度的实际测量上,而非仅仅是阅读代码,最后,其实数据结构的选择比底层的优化重要的多 

当然话又说回来,了解隐藏在.Net底层的秘密是非常有趣的,那就让我们开始设置visualstudio,并动手试验一个简单的例子 

首先我们需要一些试验代码 

  static void Main(string[] args) { 

  for (int i = 0; i < 10; i++) { 

  Console.WriteLine("Hello World!"); 

  } 

  } 

为了打开非托管代码调试,我们需要对visual studio进行设置.打开项目的属性并进入Debug Tab,选择该页上的“Enable unmanaged code debugging”复选框 

 

(注意,这个选项只对当前使用的配置有效,因此我们应该为我们使用的所有配置设置这个选项.)在循环的开始处插入一个断点,并运行程序,你将会像往常一样击中一个断点。这时你的屏幕应该看起来如图二(译者:原文缺图)如果你没有stack窗口,可以通过menu -> windows -> call stack (或者 ctrl + d c)将其呼出,打开call stack后,我们就可以通过右击鼠标,选择go to disassembly进入下面的代码
   

static void Main(string[] args) {
00000000 push ebp
00000001 mov ebp,esp
00000003 push edi
00000004 push esi
00000005 push ebx
00000006 sub esp,38h
00000009 xor eax,eax
0000000b mov dword ptr [ebp-10h],eax
0000000e xor eax,eax
00000010 mov dword ptr [ebp-1Ch],eax
00000013 mov dword ptr [ebp-3Ch],ecx
00000016 cmp dword ptr ds:[00912DC8h],0
0000001d je 00000024
0000001f call 792B228E
00000024 xor esi,esi
00000026 xor edi,edi
00000028 nop
for (int i = 0; i < 10; i++) {
00000029 xor esi,esi
0000002b nop
0000002c jmp 0000003D
0000002e nop
Console.WriteLine("Hello World!");
0000002f mov ecx,dword ptr ds:[022B303Ch]
00000035 call 785D9074
0000003a nop
}
0000003b nop
for (int i = 0; i < 10; i++) {
0000003c inc esi
0000003d cmp esi,0Ah
00000040 setl al
00000043 movzx eax,al
00000046 mov edi,eax
00000048 test edi,edi
0000004a jne 0000002E
}
0000004c nop
0000004d lea esp,[ebp-0Ch]
00000050 pop ebx
00000051 pop esi
00000052 pop edi
00000053 pop



 我们正在查看的就是JIT为我们的代码产生的native code(本地代码),我们可以看到简单的循环在native code层次上怎么运行的,如果你从来没有研究过native code,这些本来很普通的代码可能看起来相当的奇怪,让我们来自己看看这里发生了什么 

00000029 xor esi,esi 

0000002b nop  

0000002c jmp 0000003D 

上面代码初始化我们在ESI中的计数器,ESI是一个索引寄存器,可以用来索引数组,你可以看到这里用了一个很古老的"把戏"来把计数器清0,代码没有使用把0值放入寄存器,而是让寄存器自己异或(xor)自己来达到清0的目的,接下来的一行Nop,意思是"没有操作",而他们的作用就和他们的名字一样,什么也不做,代码接下来立即跳转到3D.有时候像这样的跳转使得我们的代码不是自上而下的运行(就象许多高级语言比如c,vb,c#里面一样),如果跟着这个跳转进入这个循环的另外一个部分,就可以继续分析我们的代码 

0000003c inc esi  

0000003c后面第一个指令把ESI中的计数器加一(通过register窗口或者组合键ctrl+D R 你可以看到它的值),在第一次循环时代码会跳过这行,因为上面的跳转指令直接指向了0000003D


0000003d cmp esi,0Ah 

00000040 setl al  

00000043 movzx eax,al 

00000046 mov edi,eax 

00000048 test edi,edi 

文章评论

程序员的鄙视链
程序员的鄙视链
“肮脏的”IT工作排行榜
“肮脏的”IT工作排行榜
我的丈夫是个程序员
我的丈夫是个程序员
为什么程序员都是夜猫子
为什么程序员都是夜猫子
编程语言是女人
编程语言是女人
10个调试和排错的小建议
10个调试和排错的小建议
程序员眼里IE浏览器是什么样的
程序员眼里IE浏览器是什么样的
程序员周末都喜欢做什么?
程序员周末都喜欢做什么?
Web开发人员为什么越来越懒了?
Web开发人员为什么越来越懒了?
总结2014中国互联网十大段子
总结2014中国互联网十大段子
科技史上最臭名昭著的13大罪犯
科技史上最臭名昭著的13大罪犯
一个程序员的时间管理
一个程序员的时间管理
Java程序员必看电影
Java程序员必看电影
老美怎么看待阿里赴美上市
老美怎么看待阿里赴美上市
程序员的一天:一寸光阴一寸金
程序员的一天:一寸光阴一寸金
聊聊HTTPS和SSL/TLS协议
聊聊HTTPS和SSL/TLS协议
程序员应该关注的一些事儿
程序员应该关注的一些事儿
5款最佳正则表达式编辑调试器
5款最佳正则表达式编辑调试器
看13位CEO、创始人和高管如何提高工作效率
看13位CEO、创始人和高管如何提高工作效率
程序员最害怕的5件事 你中招了吗?
程序员最害怕的5件事 你中招了吗?
要嫁就嫁程序猿—钱多话少死的早
要嫁就嫁程序猿—钱多话少死的早
当下全球最炙手可热的八位少年创业者
当下全球最炙手可热的八位少年创业者
漫画:程序员的工作
漫画:程序员的工作
程序员都该阅读的书
程序员都该阅读的书
 程序员的样子
程序员的样子
程序猿的崛起——Growth Hacker
程序猿的崛起——Growth Hacker
10个帮程序员减压放松的网站
10个帮程序员减压放松的网站
做程序猿的老婆应该注意的一些事情
做程序猿的老婆应该注意的一些事情
为啥Android手机总会越用越慢?
为啥Android手机总会越用越慢?
60个开发者不容错过的免费资源库
60个开发者不容错过的免费资源库
旅行,写作,编程
旅行,写作,编程
那些争议最大的编程观点
那些争议最大的编程观点
中美印日四国程序员比较
中美印日四国程序员比较
鲜为人知的编程真相
鲜为人知的编程真相
亲爱的项目经理,我恨你
亲爱的项目经理,我恨你
每天工作4小时的程序员
每天工作4小时的程序员
Web开发者需具备的8个好习惯
Web开发者需具备的8个好习惯
什么才是优秀的用户界面设计
什么才是优秀的用户界面设计
我跳槽是因为他们的显示器更大
我跳槽是因为他们的显示器更大
不懂技术不要对懂技术的人说这很容易实现
不懂技术不要对懂技术的人说这很容易实现
程序员必看的十大电影
程序员必看的十大电影
程序员和编码员之间的区别
程序员和编码员之间的区别
Java 与 .NET 的平台发展之争
Java 与 .NET 的平台发展之争
如何成为一名黑客
如何成为一名黑客
写给自己也写给你 自己到底该何去何从
写给自己也写给你 自己到底该何去何从
软件开发程序错误异常ExceptionCopyright © 2009-2015 MyException 版权所有