[译]怎样用VisualStudio查看非托管代码 解决思路
发布时间:2011-06-20 18:40:40 文章来源:www.iduyao.cn 采编人员:星星草
[译]怎样用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
友情提示:
信息收集于互联网,如果您发现错误或造成侵权,请及时通知本站更正或删除,具体联系方式见页面底部联系我们,谢谢。
其他相似内容:
-
---VS2008,单元测试,无法读取web.config配置中的数据库链接字符串!
我想在VS2008中,对DAL层的数据处理函数,做单元测试,以验证所写的函数...
-
如何在TFS项目门户网站显示任务
安装配置好TFS08以后,新建一团队项目,可是在项目门户网站中无法查询通过使用团队资源管理器发布的...
-
着急~~~~VSTS源代码管理的问题 orz
Exception Message: TF50309: The following account does not have sufficient permissions ...
-
关于vs2008 的web自动化功能上的测试问题
请问我要测试vs2008 上的 web项目
我要研究一下如何自动的 测试功能上问题
例如: 点了...
-
怎么获取最近有哪些迁入 checkins
如果想看看最近有哪些迁入, 该怎么做?
首先我已经试过了 Project Alerts, 可以 一有迁入就通...
-
TFS2010在重装系统后,如何把重装前的tfs数据库文件导入到tfs中
TFS2010我用的是basic模式,怎么把重装前的tfs2010生成的数据库Tfs_C...
-
终于找到这个地方啦~~~都来看都来看~~vs2008的2个问题
大家好!
NO1:
菜鸟级的一个问题,建好的解决方案里(win32),怎么查看win32一开始...
-
有多少人在用vsts?
我们项目组在用,不过现在只用它做代码管理,初步感觉还不错
代码分析和单元测试的功能还没有使用,很想深入的使用...
-
VSTS中权限的设置
什么都没有操作,突然有一天,所有的人都可以看到VSTS里面的项目了,在安排工作项的时候,所有域成员都可以选择了,这个...
-
关于TFS的生成代理的问题
大家谁 使用过TFS的Team Build,
我使用的时候,老是说出现 TF209011:无法创建放置位置 ... 找不到网络位置...