使用WinDbg获得托管方法的汇编代码

这是一个没有多大价值的小实验,对于大家了解.NET编程等方面几乎没有任何 好处,尽管老赵一直强调“基础”,例如扎实的算法和数据结构能力,并且对一 些必要的支持,例如操作系统,计算机体系结构,计算机网络有足够的了解,拥 有“常识”,在需要的时候有足够的能力去深入了解便可;但是对于还有一些科 目,例如“编译原理”,它虽然可以加强对于一个人对程序的理解,但是我也并 不觉得这是一条“必经之路”。了解黑盒内部肯定是有好处的,但是是否值得学 习还要进行权衡,至少要考虑(1)了解这些对于一个人究竟好处有多大,是否真 那么关键;(2)同样了解这些知识,需要了解到多深,是否我们走的是了解这些 的“必经之路”。同样,对于那种动辄一个问题就深入“IL”,“系统底层”的 做法,老赵对此持保留态度1。当然,对于亲手进行一番尝试和探索 的做法,我总是支持的,这表明了一种严谨的治学态度——但是,前提是我们并 不是“以此为荣”而去搞这些(老赵也一直强调,谁说搞应用层的技术含量就比 搞所谓“底层”要差了),在搞这些之前也已经有必要的根基。我们是为了探索 而去研究,不是为了研究而去研究。

有时候,我们需要查看一个托管方法的汇编指令是怎么样的。记得在大学的时 候,我们使用gcc -s和objdump来获得一个c程序代码的汇编指令。但是对于.NET 程序来说,我们肯定无法轻松地获得这些内容。因为所有的.NET程序都是编译成 IL代码的,而只有在运行时才会被JIT编译成本机代码。因此,我们必须要在程序 运行之后,再使用某种方式去“探得”汇编指令为何——除非我们可以让JIT在不 运行程序的时候编译IL代码,老赵不知道该怎么做,可能需要朋友的提点。

为了进行这个实验,我们先来写一些简单的示例代码:

namespace TestAsm
{
  public static class  TestClass
  {
    public static int TestMethod(int i)
    {
      return i;
    }
  }

   class Program
  {
    static void Main(string[]  args)
    {
      Console.WriteLine("Before  JIT.");
      Console.ReadLine();

       TestClass.TestMethod(1);

      Console.WriteLine("After  JIT");
      Console.ReadLine();

       TestClass.TestMethod(1);
    }
  }
}

大家可以新建一个TestAsm项目,将以上代码复制粘贴,并使用Debug模式编译 (避免TestMethod方法被内联,这会导致TestMethod永远不会被JIT) 2,便可以得到一个TestAsm.exe,这就是我们的试验目标。可以看到 代码中调用了两遍TestClass.TestMethod方法,并且分别在调用前使用 Console.ReadLine中断,这使我们有了有机会使用WinDbg来进行一番探索。我们 先进行一番准备工作:

运行TestAsm.exe,看到Before JIT字样(最好不要在VS里调试运行,因为这 会加入VS的的调试模块——虽然这并不影响试验)。

打开WinDbg(假设您已经设好了Symbol Path),按F6(或File - Attach to a Process),选择TestAsm.exe并确定。

加载SOS(例如.load C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727 \sos.dll)。

现在我们就已经做好了准备。那么我们第一步是什么呢?自然是要找出 TestClass.TestMethod方法的“位置”,于是先使用!name2ee命令获得TestClass 类的信息:

0:003> !name2ee *!TestAsm.TestClass
Module: 70ca1000  (mscorlib.dll)
--------------------------------------
Module:  00942c5c (TestAsm.exe)
Token: 0x02000002
MethodTable:  0094306c
EEClass: 0094133c
Name: TestAsm.TestClass

“!name2ee *!TestAsm.TestClass”命令的含义是“遍历所有已加载模块,查 找TestAsm.TestClass类型”。如果需要的话,您也可以使用“!name2ee modulename typename”的方式来查找指定模块中的指定类型。从输出中我们可以 看到MethodTable的地址是0028306c。于是我们使用!dumpmt -md <address>命令来查看TestClass类型的方法描述符(Method Descriptor) :

0:003> !dumpmt -md 0094306c
EEClass:  0094133c
Module: 00942c5c
Name: TestAsm.TestClass
mdToken: 02000002 (C:\...\TestAsm\bin\Debug\TestAsm.exe)
BaseSize:  0xc
ComponentSize: 0x0
Number of IFaces in IFaceMap:  0
Slots in VTable: 5
--------------------------------------
MethodDesc Table
  Entry MethodDesc   JIT  Name
70e66a70  70ce4934  PreJIT System.Object.ToString()
70e66a90  70ce493c  PreJIT System.Object.Equals (System.Object)
70e66b00  70ce496c  PreJIT  System.Object.GetHashCode()
70ed72f0  70ce4990  PreJIT  System.Object.Finalize()
0094c040  00943060   NONE  TestAsm.TestClass.TestMethod(Int32)

且看TestMethod的JIT栏的状态:“NONE”,这意味着这个方法还没有经过JIT 的编译,如果我们此时通过!u <address>命令来查看方法的汇编指令就会 看到:

0:003> !u 0094c040
Unmanaged code
0094c040  e8755d9571   call  mscorwks!PrecodeFixupThunk (722a1dba)
0094c045 5e       pop   esi
0094c046 0000       add   byte ptr [eax],al
0094c048 60        pushad
0094c049 30940000000000 xor   byte ptr  [eax+eax],dl
0094c050 0000      add   byte ptr  [eax],al
0094c052 0000      add   byte ptr  [eax],al
0094c054 0000      add   byte ptr  [eax],al
0094c056 0000      add   byte ptr  [eax],al
0094c058 0000      add   byte ptr  [eax],al

时间: 2024-07-30 18:16:09

使用WinDbg获得托管方法的汇编代码的相关文章

解析四则表达式的编译过程及生成汇编代码

1.前序这是编译原理的实验,自认为是上大学以来做过的最难的一个实验. 实验用到的基础知识:C语言.数据结构.汇编(只需简单的了解). 开发工具:VC 2.问题描述编译整数四则运算表达式,将整数四则运算表达式翻译为汇编语言代码. 消除左递归后的文法: E→TE' E'→+TE' |ε T→FT' T'→*FT' |ε F→(E) | i 消除左递归后的翻译模式: E ::= T {E'.i:=T.nptr} E' {E.nptr:=E'.s} E'::= + T {E'1.i:=mknode('+

解析四则表达式的编译过程及生成汇编代码_C 语言

1.前序这是编译原理的实验,自认为是上大学以来做过的最难的一个实验.实验用到的基础知识:C语言.数据结构.汇编(只需简单的了解).开发工具:VC 2.问题描述编译整数四则运算表达式,将整数四则运算表达式翻译为汇编语言代码.消除左递归后的文法:E→TE'E'→+TE' |εT→FT'T'→*FT' |εF→(E) | i消除左递归后的翻译模式:E ::=     T    {E'.i:=T.nptr}E'    {E.nptr:=E'.s}E'::=      + T  {E'1.i:=mknod

远线程运行汇编代码

VB.NET 2008 写的代码,主要是前几天看人家写的VB6什么的代码,运行起来 不错,可改成VB.NET 2008一写,直接坏事了,在XP系统D325的U上跑的都挺好, 可放到VISTA系统TK55的本子上,VB6的还行,.NET的直接非法.针对这个,完整 重写了一下代码. 简单介绍步骤: 1.通过ID获取进程句柄,并替它申请一块内存: '获取对方进程 RemoteProcess = Process.GetProcessById (PID) '为对方进程申请4KB内存 AllocBaseAd

C语言中的数组和指针汇编代码分析实例

  这篇文章主要介绍了C语言中的数组和指针汇编代码分析实例,本文用一则C语言例子来得到对应的汇编代码,并一一注解每句汇编代码的含义,需要的朋友可以参考下 今天看<程序员面试宝典>时偶然看到讲数组和指针的存取效率,闲着无聊,就自己写了段小代码,简单分析一下C语言背后的汇编,可能很多人只注重C语言,但在实际应用当中,当出现问题时,有时候还是通过分析汇编代码能够解决问题.本文只是为初学者,大牛可以飘过~ C源代码如下: 代码如下: #include "stdafx.h" int

求解释-求大神帮看看这段汇编代码

问题描述 求大神帮看看这段汇编代码 学校课程设计,这段是步进电机的控制代码,用键盘输入,在六位LED七段数码显示管上显示,求大神把下面代码加上注释,实在不行就帮忙看下键盘显示那部分是怎么回事,有重谢. ORG 0A30H ;? MONIT: MOV SP,#50H MOV 7EH,#00H MOV 7DH,#02H MOV R0,#7CH MOV A,#08H MOV R4,#04H MONIT1: MOV @R0,A DEC R0 DJNZ R4,MONIT1 MOV A,#7EH MOV D

MFC下如何快速找到界面的方法对应的代码????

问题描述 MFC下如何快速找到界面的方法对应的代码???? MFC下如何快速找到界面的方法对应的代码,大神们请指教!!! 解决方案 再资源中,双击界面上的按钮等,就可以自动定位到编译器中的按钮代码 解决方案二: 用classwizard,或者直接双击对话框设计器中的控件.

汇编语言-求教以下汇编代码里面的^表示什么意思。

问题描述 求教以下汇编代码里面的^表示什么意思. 想请教下大神,代码最后一行的^符号表示什么意思? irq: sub lr, lr, #4 stmfd sp!, {r0-r12, lr} bl handle_int ldmfd sp!, {r0-r12, pc}^ 解决方案 arm汇编 参考:http://wenku.baidu.com/link?url=d11DHDolvKbXs_jtOfWgsvMHvPTNOb4-2fPHcS-5_KHniRakqsJKkyzjBVvctNKu9h5L0LH

des 加解密-暴力破解des的方法或者c代码。

问题描述 暴力破解des的方法或者c代码. 当明文为纯英文文档,密钥为纯数字时,完成暴力破解密文破解实验,要求20秒内完成. 解决方案 纯数字还分一个5位10位.每多一位,耗时增加10倍.谁能保证20秒完成. 解决方案二: 1.这个问题可以这么的分析,对于des算法来说,如果确定秘钥为纯数字,则秘钥的空间最大为100000000,即1亿. 2.目前普通pc,一个核des加密性能在40MB以上,这样一个核每秒至少可以测试的秘钥为500万,20秒就可以测试1亿个秘钥. 从以上分析可以看出,如果可以确

汇编 c语言转换-深入理解计算机系统练习题3.22,不明白下面汇编代码的作用?

问题描述 深入理解计算机系统练习题3.22,不明白下面汇编代码的作用? movl 8(%ebp) %edxmovl $0%eaxtestl %edx%edxje .L7.L10:xorl %edx%eaxshrl %edxjne .L10.L7:andl $1%eax 解决方案 不明白其中那一点还是全部都不会i?