Hello World
Spiga

老赵谈IL(1):IL是什么,它又不是什么?那么汇编呢?

2009-06-01 21:00 by 老赵, 28861 visits

我们.NET开发人员必定离不开IL,就算您没有学习,也一定可以在各处看到它的身影。最近在博客园上活跃的IL文章译者包建强同学的一些看法让我大为震惊,决定独立开篇,希望可以让大家看到不同的声音。真理越辩越明,也欢迎大家来一起讨论,发表自己意见。我也会尽量把朋友们留在我博客上的看法汇总起来,并加以回应。

《我谈IL》也是系列文章,目前的计划有4篇,依次是:

  1. IL是什么,它又不是什么?那么汇编呢?。
  2. CLR内部有太多太多IL看不到的东西,包括您平时必须了解的那些(示例)。
  3. IL可以看到的东西,基本上都可以使用C#等高级语言来发现(示例)。
  4. 什么时候应该学IL,该怎么学IL。

您现在看到的便是本系列的第1篇:IL是什么,它又不是什么?那么汇编呢?。

我曾经在博客《浅谈尾递归的优化方式》和《使用WinDbg获得托管方法的汇编代码》涉及到了一些x86汇编,包同学在文章后留言,认为通过UltraEdit32此类编辑器观察到x86汇编:

我第三次仔细看了一遍最后这段代码,这段代码应该是从UltraEdit32中看到的,所以里面很多word不是IL中的关键字……

……就像我昨天提到用UltraEdit32这个工具来解读汇编代码,道理是一样的……

同样的事情发生在我最近写的一篇文章《从汇编入手,探究泛型的性能问题》以及包同学自己的文章后面的回复中:

如果不熟悉IL,又怎么能自己动手分析性能呢?你这篇文章不就证明了学习一点IL的重要性了么?

其实IL就是一门汇编语言,很奇怪有人一边在用IL Assembler分析性能,一边又在讲不要学习IL的话……

包同学作为微软MVP,是许多IL文章的译者,还有一本译作《Expert .NET 2.0 IL Assembler》即将出版,本应是这方面的专家。但是我现在非常担心这位专家的话会给许多学习.NET的朋友们一些较为严重的误导。从包同学之前的话来看,他对于IL和汇编的概念,从各自的作用到获取方式几乎完全混淆起来。因此冲动的我每次看到这样的言论都忍不住跳出来批驳一番,而这次更决定独立成文进行详细说明。

IL是微软.NET平台上衍生出来的一门中间语言,.NET平台上的各种高级语言(如C#,VB,F#)的编译器会将各自的文字表述方式转化为IL。各种不同的文字形式最终被统一到了IL的表述方式,其中包含了.NET平台上的各种元素,如“范型”,“类”、、“接口”、“模块”、“属性”等等。值得注意的是,各种高级语言本身可能根本没有这些“概念”在里头,如IronScheme是一个在.NET平台上的Scheme语言实现,其中根本没有前面提到的这些IL——亦或说是.NET平台上的名词。IL本身并不知道自己是由哪种高级语言转化而来的,哪种语言中有哪些特性,IL也根本不会关心。

谁来关心这些呢?自然是各语言的编译器了。这就是.NET平台上的高级语言的第一次转化:高级语言 => IL

而我们平时说的“汇编”则要简单得多,这个简单并不代表“容易掌握,方便使用”,这个“简单”是指它的“定义”。汇编是让CPU直接使用的“语言”,请注意“直接”二字:一条汇编指令便是让CPU作一件事情(如寄存器的复制,从内存中读取数据等等),毫无二义。不同族CPU拥有不同的指令集,但是它们都有一样的特征:指令的数量相对较少,每个指令功能都简单之至。这也是为什么现在几乎没有人直接使用汇编写程序的原因,试想一下给您红、绿、蓝三原色,让您绘制一幅色彩绚丽的图画有多么困难。

由于CPU只认识汇编代码,因此就算是IL也需要再次进行转化,才能被CPU执行。这次转化便由“JIT Compiler”完成。CLR加载了IL之后,当每个方法——请注意这是IL中的概念——第一次被执行时,就会使用JIT将IL代码进行编译为机器码——对了,刚才我忘了提,机器码和汇编其实也是一一对应的,您可以这样理解:汇编是机器码的文字表现形式,提供了一些方便人们记忆的“助记符”。与IL不同的是,CLR,JIT都是真正了解CPU的,对于同样的IL,JIT会把它为不同的CPU架构(如x86/IA64等等)生成不同的机器码。这也是Java/.NET中“Compile Once,Run Everywhere”这一口号的技术基础:它们为不同的CPU架构提供了不同的“IL转化器”,仅此而已。与高级语言到IL的转化类似,CPU也完全不知道自己在执行的指令是从哪里来的,可能是JIT从IL转化而来,可能是JVM从Java Bytecode转化而来,也有可能是C语言编译得来,也有可能是由MIT/GNU Scheme解释而来。

这就是.NET平台上的高级语言在机器上运行的第二次转化:IL => 汇编(机器码)

因此,IL和汇编的区别是显著的。IL拥有各种高级特性,它知道什么是范型,什么是类和方法(以及它们的“名称”),什么是继承,什么是字符串,布尔值,什么是User对象。而CPU只知道寄存器,地址,内存,01010101。与汇编相比,IL简直太高级了,几乎完全是一个高级语言,比C语言还要高级。因此,您会看到.NET Reflector几乎可以把IL代码“一五一十”地反编译为可读性良好的C#代码,包括类,属性,方法等等;而从汇编只能勉勉强强地反编译为C语言——而且其中的“方法名”等信息已经完全不可恢复了,更别说“模块”等高级抽象的内容。您想要把汇编反编译成C#代码?相信在将来这是可行的,不过现在这还是天方夜谭。

那么我们再来看看包同学的观点,例如首先他认为“用UltraEdit32这个工具来解读汇编代码”。如果您理解了我之前的解释,应该可以意识到这完全是一种谬论。IL是一种高度抽象,在运行之前,还需要由JIT转化为机器码才行。同样的IL代码,可以由不同CPU架构下的JIT编译成不同的机器码(同样的IL代码在同样的机器上是否也生成同样的机器码呢?答案是否定的,例如“泛型”……下一篇文章中我们会对此进行观察)。甚至于,CLR在运行了一段时间之后,可以让JIT重新生成一段更适合当前环境,性能更高的机器码供CPU执行。从这个角度上说,IL是静态的,而汇编是动态的。设法使用一个静态查看工具UltraEdit32来阅读一个动态的,不确定的内容,这又该如何实现呢?

不过真要说起来,使用UltraEdit32从理论上的确可以阅读一个编译后的IL代码,因为此时IL已经以二进制的形式存储在程序集文件中。例如IL Disassembler(ildasm.exe)和.NET Reflector便是通过读取程序集文件的数据(而不是在将程序集加载到CLR中)来获得IL代码,微软也发布了Common Compiler Infrastructure: MetadataCCI: Code and AST两个和.NET基础结构有关的开源项目。而近在“博客园”中,也有Anders Liu大牛写过一个CliPeViewer,从程序集的物理结构中读取其元数据,再进一步便可获取到IL代码了。

虽然已经有了多次请求,但是包同学还是没有公布他使用UltraEdit32获取汇编代码的做法。窃以为,是因为“这个真无法实现”的原因吧。

至于包同学的另一个看法是,我使用IL Assembler(他应该是指IL Disassembler)查看汇编代码所犯的错误同样是混淆了IL和汇编两种截然不同的东西。那些都是我在程序运行之后,使用WinDbg观察汇编的结果,也就是说,是JIT将IL进行再次编译(第一次是指高级语言编译器生成IL)的结果。由于JIT每次进行处理的最小单元是“方法”,因此如果一个.NET方法还没有执行过,则是无法获取它的汇编代码的。我在《使用WinDbg获得托管方法的汇编代码》一文中清楚地演示了目标方法在Before JIT和After JIT两个不同情况下,由WinDbg观察到的结果。

由于IL还是过于高级,因此很多真真切切的东西并无法看到,因此我也不得不用汇编从根本上证实了泛型不会降低性能——严格来说,由于IL在不同平台上生成的汇编不同,我其实也只是证实了在x86平台上的这个结论。请您回想一下,您看过的.NET书籍中有多少是使用IL来说明问题的呢?为了心中踏实,我刚才又去翻了翻《Essential .NET》、《CLR via C#》这《Customizing the .NET Common Language Runtime》这几本“偏底层”的书,证实了这一观点。其实理由很简单,一是大师能够用朴实的语言,或更易理解的高级代码把问题明明白白彻彻底底地讲清楚,二便是因为IL可以说明的东西实在有限。例如,泛型在运行期间是否生成了新类型?CLR对待引用类型和值类型的泛型时是否一样?

在包同学之前的文章中,横道天笑也回复了类似的看法:

……我觉得IL的作用就仅此而已,对于其他,甚至是虚方法调用等等从IL上都看不出来什么。因为你真的不知道callvir指令内部到底干了啥,更别说性能了,因为IL之后还有个JIT,JIT之后才得到的是我们传统上的汇编,汇编语言与机器指令是一一对应的,所以从汇编语言上才能发现一切的一切,比如多态靠的是对象地址加偏移,比如我的那篇汇编讨论性能的文章。

这篇文章的目的是“讲道理”,在接下来了两篇文章中,我还会通过示例,也就是“摆事实”来解释为什么说“CLR内部有太多太多IL看不到的东西,包括平时您必须了解的那些”,以及“IL可以看到的东西,基本上都可以使用C#等高级语言来发现”。

最后,为了避免给大家带来误导,我还是希望多补充几句。我的这几篇文章似乎是在“呼吁”大家不要学习IL,其实不然。我是希望在澄清事实的的基础上,探究出一些更有实践价值结论。例如学习IL和汇编有什么好处,什么是对IL和汇编的滥用,以及究竟该如何可以更快速方便地解决某些问题等等——例如我使用汇编来说明泛型的性能问题就是一种滥用,最好的方法应该是“编写试验代码”。

因此,本系列文章的最后一篇想讨论的话题便是“什么时候应该学IL,该怎么学IL”。在这里,我也请大家留下您的观点,真理便是在各种观点中总结出来的,不是吗? 

 

看了大家的评论,我觉得可能还需要把汇编和机器码的关系进行一些补充。

  1. 有朋友提出,汇编不是和机器码一一对应的,因为还有宏汇编,高级汇编等等。其实高级汇编其实已经是一种“语言”了,它最终还是被转换成机器码执行。我说的汇编是指汇编“指令”,由机器码简单一一替换成助记符给人看。
  2. 还有某位朋友指出的一点,如果JIT生成的是汇编,那么肯定无法给机器直接执行。文章里可能没有说清楚,我的意思是,JIT生成机器码,而汇编是机器码进行简单替换后,方便给人看的结果。阅读汇编代码,就完全了解了CPU是如何一步一步进行执行任务的,没有丝毫偏差。这也是我认为观察汇编就是阅读机器码的原因。

相关文章

所属话题:谈谈IL
Creative Commons License

本文基于署名 2.5 中国大陆许可协议发布,欢迎转载,演绎或用于商业目的,但是必须保留本文的署名赵劼(包含链接),具体操作方式可参考此处。如您有任何疑问或者授权方面的协商,请给我留言

Add your comment

192 条回复

  1. dodoasp.net[未注册用户]
    *.*.*.*
    链接

    dodoasp.net[未注册用户] 2009-06-01 21:05:00

    哦 ,这样啊

  2. 杨芹勍
    *.*.*.*
    链接

    杨芹勍 2009-06-01 21:09:00

    “IL是微软.NET平台上衍生出来的一门中间语言,.NET平台上的各种高级语言(如C#,VB,F#)的编译器会将各自的文字表述方式转化为IL。”

    说到点子上了。

  3. nicye
    *.*.*.*
    链接

    nicye 2009-06-01 21:13:00

    目前应用还没到研究 IL 的份上来

  4. 深山老林
    *.*.*.*
    链接

    深山老林 2009-06-01 21:16:00

    好久不见,十分想念。

  5. 度越僧
    *.*.*.*
    链接

    度越僧 2009-06-01 21:17:00

    老赵跟老包别秒头...

  6. Henley Gao
    *.*.*.*
    链接

    Henley Gao 2009-06-01 21:17:00

    节日快乐·

  7. 温景良(Jason)
    *.*.*.*
    链接

    温景良(Jason) 2009-06-01 21:18:00

    把我从迷糊的路上拉回来了,谢谢老赵

  8. Nick Wang (懒人王)
    *.*.*.*
    链接

    Nick Wang (懒人王) 2009-06-01 21:19:00

    “什么时候应该学IL,该怎么学IL”
    很多人不想知道“什么时候”应该学,而是“应不应该”学。他们只想要一个现成的结论,而不是自己思考。

    又习惯性的跑题了 :p

  9. hoodlum1980
    *.*.*.*
    链接

    hoodlum1980 2009-06-01 21:20:00

    难道有人会把IL认为是汇编语言?我觉得不可能犯这样的严重错误把?
    IL是.net 搞出来的东西。
    简单来说,使用专门的反汇编工具(直接对exe,dll等PE文件进行的反汇编)比如IDA,得到的就是汇编语言(ASM)。比如单片机开发的那种编译环境,这方面可以参考清华大学出版的那本讲解x86汇编的教材,名字清不太清楚了。

    汇编语言主要是引进了人类容易辨别的助记符(比如MOV等)代替CPU处理的二进制指令。本质上和二进制对应,一条指令可能有1个到多个字节组成。这些native code被编译器从程序员输入的高级语言代码编译(词法,语法分析等。。。需多次扫描代码)而生成的,然后组成和链接成为编译结果的code section。

    至于IL,那个是.net自带的那个工具打开.net编译出来的东西看到的才是。打开native code的东西恐怕不行。。。没试过。

  10. Nick Wang (懒人王)
    *.*.*.*
    链接

    Nick Wang (懒人王) 2009-06-01 21:23:00

    @度越僧
    只说客观事实,不结私人恩怨

  11. 横刀天笑
    *.*.*.*
    链接

    横刀天笑 2009-06-01 21:23:00

    荣幸,还引用了俺的评论,可惜俺把callvirt写错了。。

  12. 老赵
    admin
    链接

    老赵 2009-06-01 21:25:00

    @hoodlum1980
    我本也不相信有人会犯此严重错误,但是我实在不知道包同学的话该怎么理解,多次了啊……
    其实如果IL Dsam可以获取native code的话,方法早就出来了,可惜这是真做不到。
    当然,我可以写一个编辑器,host一个clr,然后jit一下IL代码,呵呵。

  13. 老赵
    admin
    链接

    老赵 2009-06-01 21:26:00

    --引用--------------------------------------------------
    度越僧: 老赵跟老包别秒头...
    --------------------------------------------------------
    我都是引用原话的……
    其实也是因为包子太有名了,有些话从他嘴里说出来误导性太强,我忍不住,呵呵。

  14. 老赵
    admin
    链接

    老赵 2009-06-01 21:27:00

    --引用--------------------------------------------------
    Nick Wang (懒人王): “什么时候应该学IL,该怎么学IL”
    很多人不想知道“什么时候”应该学,而是“应不应该”学。他们只想要一个现成的结论,而不是自己思考。
    --------------------------------------------------------
    所以,像你我这种想明白的人多多少少要努力一把,至少多呼吁呼吁……

  15. 老赵
    admin
    链接

    老赵 2009-06-01 21:28:00

    --引用--------------------------------------------------
    横刀天笑: 荣幸,还引用了俺的评论,可惜俺把callvirt写错了。。
    --------------------------------------------------------
    你把我想说的差不多一句话总结了,只能引用了,呵呵

  16. 钧梓昊逑
    *.*.*.*
    链接

    钧梓昊逑 2009-06-01 21:30:00

    唔~我的观点和老赵一致

  17. 老赵
    admin
    链接

    老赵 2009-06-01 21:31:00

    兄弟们我回家了,午夜见

  18. hoodlum1980
    *.*.*.*
    链接

    hoodlum1980 2009-06-01 21:38:00

    简单来说,要看懂对native code的反汇编,难度是要大于看懂IL的。
    因为反汇编不仅仅是懂得所有的汇编指令,还要了解编译器的习惯,了解一些“基本规则”才能进行的。看反汇编通常好比是进入“微观世界”,超级数量的没有可读名称的函数以及频繁跳转,关系错综芜杂,要想看清“全貌”或还原成“高级语言”是决不现实的,通常只是为了找到某些关键之处(可能是为了破解)进行修改,以前我曾把QQ里的一个函数调用给去掉了。从反汇编的代码还可以看到很多非常底层和本质性的东西,比如栈上空间的分配,函数的调用约定等东西。

  19. Henley Gao
    *.*.*.*
    链接

    Henley Gao 2009-06-01 21:46:00

    我是没有学过汇编的程序员,对这方便不了解,也不知道从哪里学习。
    希望老赵能带领我们学习。Thank you!

  20. 私家侦探
    *.*.*.*
    链接

    私家侦探 2009-06-01 21:56:00

    il是中间代码,介于语言(c#/vb.net等)和机器语言之间,c#代码被编译成这种中间代码,到时再转化为机器语言就非常快了,所以才叫il为类似机器语言,是基于性能提升而产生的语言,好像msdn中对il的作用已经介绍得很清楚了

  21. 谢慧琦
    *.*.*.*
    链接

    谢慧琦 2009-06-01 21:57:00

    好文,收藏下

  22. Ks.Int-Gel
    *.*.*.*
    链接

    Ks.Int-Gel 2009-06-01 21:59:00

    其实你说的这个从高级语言翻译到汇编的过程几乎在每一本.net书中都会讲到

    只是我们不是太注重这东西,只是想可以了解一下这中的执行过程经历哪几步就
    Ok了

    当然了,像你和包同学这样研究的比较透彻,比较深的就自然会发现这中间的一些“玄机”O(∩_∩)O哈哈~

    期待下面的示例,学学“牛人”是怎么学习的,支持支持,UPUP

  23. Grove.Chu
    *.*.*.*
    链接

    Grove.Chu 2009-06-01 22:00:00

    跟着老赵学IL,没有什么汇编基础,就看过《你必须知道.NET》一书讲了IL,感觉平时开发中也没有怎么用到,所有也没有多看。现在看来,这个还是有用的哇,嘿嘿,跟着你学了。Thanks.

  24. Nick Wang (懒人王)
    *.*.*.*
    链接

    Nick Wang (懒人王) 2009-06-01 22:00:00

    --引用--------------------------------------------------
    私家侦探: il是中间代码,介于语言(c#/vb.net等)和机器语言之间,c#代码被编译成这种中间代码,到时再转化为机器语言就非常快了,所以才叫il为类似机器语言,是基于性能提升而产生的语言,好像msdn中对il的作用已经介绍得很清楚了
    --------------------------------------------------------
    IL不是为了性能而产生的

  25. Nick Wang (懒人王)
    *.*.*.*
    链接

    Nick Wang (懒人王) 2009-06-01 22:03:00

    --引用--------------------------------------------------
    Grove.Chu: 跟着老赵学IL,没有什么汇编基础,就看过《你必须知道.NET》一书讲了IL,感觉平时开发中也没有怎么用到,所有也没有多看。现在看来,这个还是有用的哇,嘿嘿,跟着你学了。Thanks.
    --------------------------------------------------------
    有什么用?真的有用么?对你真的有用么?
    想好了在决定学不学

  26. 飞林沙
    *.*.*.*
    链接

    飞林沙 2009-06-01 22:03:00

    C#-->IL---->汇编--->机器码
    一层总是比一层低级的,但是对于老赵说汇编约等于机器码 这个我不赞同
    我认为这个和IL和汇编的关系近似,有很多汇编看不到,但是机器码可以看到的

  27. 飞林沙
    *.*.*.*
    链接

    飞林沙 2009-06-01 22:04:00

    @Nick Wang (懒人王)

    其实我不赞同您的说法,我认为并不一定要有用才学。
    知识皆有用,为了爱好而去学也不见得不是一件好事

  28. Nick Wang (懒人王)
    *.*.*.*
    链接

    Nick Wang (懒人王) 2009-06-01 22:05:00

    --引用--------------------------------------------------
    飞林沙:
    一层总是比一层低级的,但是对于老赵说汇编约等于机器码 这个我不赞同
    我认为这个和IL和汇编的关系近似,有很多汇编看不到,但是机器码可以看到的
    --------------------------------------------------------
    汇编本身就是机器码的符号表示,是一对一对应的
    机器码就是0101011010,你怎么看?

  29. Nick Wang (懒人王)
    *.*.*.*
    链接

    Nick Wang (懒人王) 2009-06-01 22:10:00

    @飞林沙
    为了爱好学是好事,但是你真的是为了爱好呢,还是因为老赵写了呢?
    你或许是因为爱好,但是其他人呢?

    总有些人只是因为某个“牛人”说这个东西有用,就去学,根本就不考虑一下对自己有没有用。如果是爱好,也不许要看到某某的文再开始“爱好”啊,又不是新东西,早就可以爱好了。

  30. Astral.Road
    *.*.*.*
    链接

    Astral.Road 2009-06-01 22:11:00

    汇编对我来说... 找一个下关键断点的, 比如messagebox,文件io的,按钮一类的. 一路跳出,或者跟进.找关键跳转, 运气好的话 JMP之... 搞定. 再复杂的么, 呃,玩不下去.

    话说il和汇编. 那根本不好用差别来说吧, 根本不是一个位面的东西啊

  31. Colin Han
    *.*.*.*
    链接

    Colin Han 2009-06-01 22:13:00

    呵呵,有时候还是要看一看IL代码的。下面是我遇到的几个场景:
    1. C#的一些关键字,我不明白对应的反射调用方法时。
    比如:我想知道如何区分我取到的MethodInfo是一个Method还是一个Property的get或set方法。我就会编译后查看它的IL,发现前面有一个specialname属性,于是,我猜测可以通过MethodInfo.IsSpecialName来判断。虽然,结果并不这么简单。我至今没有找到不需要遍历的判断一个方法是否属性的访问方法的方法。仅仅是举一个例子,希望不要对大家造成误导。
    2. 希望了解一些语法糖的实现细节的时候。
    比如:我想知道匿名方法是怎样工作的。因为我知道匿名方法仅仅是C#编译器搞出来的语法糖,于是,我可以编译成IL,然后,就可以看出来它的实现方法。最有趣的是查看yield的实现。
    3. 代码混淆的时候
    我们的产品代码需要使用代码混淆工具进行混淆。但是,有时候代码混淆工具会有Bug,于是,我就需要查看IL代码,以确认问题出在哪里。
    4. 其它
    印象中,最近的一次看IL是那次看到那个趣味题:-+-+-+-+- -+-+-+-的那个。

    其实,我觉的IL和C#已经太接近了,学好C#,对汇编有简单的了解,应该就很容易就可以看懂IL的。必要的时候,只要知道怎样可以看到IL代码,我觉的就够了。没必要深究。

    但是,一点不了解或不知道,我觉的是万万不行的。

  32. 飞林沙
    *.*.*.*
    链接

    飞林沙 2009-06-01 22:15:00

    @Nick Wang (懒人王)

    这么说 ,相同的汇编代码在32位机和在16位机上所对应的01代码是一样的么?

  33. 横刀天笑
    *.*.*.*
    链接

    横刀天笑 2009-06-01 22:17:00

    @飞林沙
    沙沙同学,汇编代码和机器码是一一对应的,一个MOV就对应着一串唯一的0101001(当然不是这个了),汇编就是助记符,如果你用0101001编写代码不要死人了?
    其实汇编器就是起一个直接转换的作用,所以可以认为汇编代码和机器码是等价的

  34. lovecherry
    *.*.*.*
    链接

    lovecherry 2009-06-01 22:17:00

    汇编应该就是机器码的助记符吧,一一对应

  35. 横刀天笑
    *.*.*.*
    链接

    横刀天笑 2009-06-01 22:20:00

    --引用--------------------------------------------------
    飞林沙: @Nick Wang (懒人王)

    这么说 ,相同的汇编代码在32位机和在16位机上所对应的01代码是一样的么?
    --------------------------------------------------------
    实际上不同架构的CPU连汇编都不一样,所以更别说01代码了,从这点也能看出汇编代码和机器码是一一对应的。

  36. 飞林沙
    *.*.*.*
    链接

    飞林沙 2009-06-01 22:25:00

    @横刀天笑


    8086到80X86,很多汇编代码依然继承下来了,但是他们对应的01并不相同。

  37. 挑痘针[未注册用户]
    *.*.*.*
    链接

    挑痘针[未注册用户] 2009-06-01 22:26:00

    老赵, 不好意思, 给你挑个刺, 你也犯了错, cpu也不认识汇编码, 它只认识机器码.
    不同架构的cpu支持的汇编指令集也不同, 即便同样是x86架构同样一条汇编指令, 16位机, 32位机, 64位机的目标机器码也是不同的(字长不同嘛).
    汇编可不仅仅是助记符啊, 别忘了还有宏汇编呢.

  38. 横刀天笑
    *.*.*.*
    链接

    横刀天笑 2009-06-01 22:32:00

    @飞林沙
    不好意思。。。什么是80X86?
    X86指的是一种CPU架构,8086只是其中一个

  39. 温景良(Jason)
    *.*.*.*
    链接

    温景良(Jason) 2009-06-01 22:33:00

    呵呵,讨论得很激烈,不过不太懂,所以只能看看!

  40. 银河
    *.*.*.*
    链接

    银河 2009-06-01 22:34:00

    学习了。
    确实,IL 和 汇编码是不同的。
    基本的汇编语言指令是和机器语言指令一一对应的。
    但是,有些汇编程序对汇编语言做了很大的扩充,如微软的宏汇编 MASM 等,有的甚至在汇编语言中引入结构化编程。这些扩充就使用得一条汇编语言(伪)指令可以对应多条机器语言指令了。

  41. 醉春风
    *.*.*.*
    链接

    醉春风 2009-06-01 22:37:00

    期待摆事实讲道理,IL解密到底。

  42. 银河
    *.*.*.*
    链接

    银河 2009-06-01 22:37:00

    @Jeffrey Zhao
    虽然已经有了多次请求,但是包同学还是公布他使用UltraEdit32获取汇编代码的做法。窃以为,是因为“这个真无法实现”的原因吧。

    这句话无法理解。可能应该是:
    但是包同学还是没有公布...


  43. 幸存者[未注册用户]
    *.*.*.*
    链接

    幸存者[未注册用户] 2009-06-01 22:40:00

    --引用--------------------------------------------------
    飞林沙: @横刀天笑


    8086到80X86,很多汇编代码依然继承下来了,但是他们对应的01并不相同。
    --------------------------------------------------------
    机器码也基本相同,除非是16位->32位或32位->64位这样的变化,即使如此,也只是扩展指令的位数,x86系的机器码基本上是向下兼容的。

  44. Teddy's Knowledge Bas…
    *.*.*.*
    链接

    Teddy's Knowledge Base 2009-06-01 22:40:00

    这个话题的确值得一说,jit运行时怎么将IL解释成汇编,这个的确只有运行时用windbg这样的工具才能看到.很多优化,尤其是和机器平台相关的优化,也只可能在jit这里发生.相对来说,编译器将C#这样的高级语言的语句翻译到IL的过程,则比较直接,基本上没有太多的优化的空间.但是很可惜,即使是对这个"相对直接"的翻译,其实很多同学coding时都没有sense,不清楚每一句c#语句会被翻译成什么IL,更不用说去思考这些IL会被jit怎么解释成汇编了.

    虽然,老赵同学本篇文章无数次challenge包子同学对IL和汇编的混淆,不过我还是更愿意相信是包子同学的很多留言用词不够严谨,而非其不了解两者的区别.不过我很惊奇,他明明在线半天了,怎么还没挑出来反驳呢?:)

  45. 飞林沙
    *.*.*.*
    链接

    飞林沙 2009-06-01 22:40:00

    @横刀天笑

    8086和80386是不同的吧???

  46. Nick Wang (懒人王)
    *.*.*.*
    链接

    Nick Wang (懒人王) 2009-06-01 22:41:00

    @飞林沙
    汇编不像C#一样是一门语言,而是一族语言,是一个统称,不同CPU的指令集不一样

    相同的汇编代码在32位机和在16位机上所对应的01代码是一样的么?
    就算不一样又如何,“this” 和 "这个” 也不一样啊,但是代表的意思是一样的啊

  47. renjf[未注册用户]
    *.*.*.*
    链接

    renjf[未注册用户] 2009-06-01 22:43:00

    终于有人站出来说话了。。。呵呵。。顶老赵。。

    那天看到有混淆il和asm的文章,顿感差异。。。这不知道是谁的悲哀呢。。。如果这个东西真要说明白,估计又得几本书了。。。

    画个图:
    c# f# vb.net j# .........
    | | | |
    - ------------
    |-----------------编译器
    il
    |-----------------JIT编译器
    asm

  48. hoodlum1980
    *.*.*.*
    链接

    hoodlum1980 2009-06-01 22:49:00

    --引用--------------------------------------------------
    飞林沙: C#-->IL---->汇编--->机器码
    一层总是比一层低级的,但是对于老赵说汇编约等于机器码 这个我不赞同
    我认为这个和IL和汇编的关系近似,有很多汇编看不到,但是机器码可以看到的
    --------------------------------------------------------
    汇编和机器码可以认为是同一个东西的不同视图,本质是一个东西。
    比如110对应某个汇编指令一个道理。文件里的二进制部分,被原样的加载到内存,并被映射到以某逻辑地址为起始的section(段)。所以你看到的汇编指令,切换下显示就是二进制的机器码。就和你用ultra edit查看文本文件的时候可以查看其二进制数据一样。

  49. zheciniming[未注册用户]
    *.*.*.*
    链接

    zheciniming[未注册用户] 2009-06-01 22:49:00

    不同脱离CLR的大环境来理解IL
    也不同脱离metadata的概念
    IL和汇编完全是两个类别,一个动物一个植物

    IL是属于CLR的metaData
    汇编是CPU执行的最小单元

  50. 飞林沙
    *.*.*.*
    链接

    飞林沙 2009-06-01 22:49:00

    话说这点上我也不赞同老赵的说法,我认为学习IL是非常必要的,不同的人爱好不同,有的人考虑的是学了这个我到底能干什么,比如老赵。很多人就是想学这个,不会去考虑这个对实际的工程项目影响,典型代表比如AnyTao。
    所以不应该盖个不该学IL的结论

  51. 横刀天笑
    *.*.*.*
    链接

    横刀天笑 2009-06-01 22:49:00

    @飞林沙
    汇编有个别名:助记符
    助记符是什么意思?帮助你记忆的,没有别的猫腻
    所以可以认为汇编和机器码等效

    当然,还有上面某位说了,汇编从最原生的,后来也不断的发展了,比如有一种叫做“高级汇编”的东东,甚至可以写if等语句了,这些又当别论。

    8086和80386指令集当然有些不同了,一个是另外一个的超集而已,对于8086而言,他的汇编和他的机器码一一对应,对于80386而言他的汇编和他的机器码一一对应,你为啥要强求8086的汇编和80386的机器码之间的关系呢

  52. zheciniming[未注册用户]
    *.*.*.*
    链接

    zheciniming[未注册用户] 2009-06-01 22:50:00

    为何
    C/C++为什么长远性能没有C#好
    C/C++为什么不能跨平台
    C/C++为什么不能很好的支持调试
    C/C++为什么不能在语言层面支持安全性声明
    C/C++为什么不能实现GC
    ...

    因为C/C++只有汇编,没有metaData

  53. zheciniming[未注册用户]
    *.*.*.*
    链接

    zheciniming[未注册用户] 2009-06-01 22:50:00

    学metadata,是站在最核心的地方, 理解CLR对jit, exception, memory layout, type system, GC, code sign, interop的支持
    换句话说, 学IL会让你知道CLR的实现基础
    如同学习ASM让你知道C/C++的最终归宿一样

    普通司机不一定要学发动机原理和机械装配
    但是专业车手就一定要会

  54. m j[未注册用户]
    *.*.*.*
    链接

    m j[未注册用户] 2009-06-01 22:51:00

    IL代码基本相当于Reflector出的源代码。。通常看IL能分析出的东西看源代码也能分析出来。。看各人爱好了。。

    我们这些远离底层的程序员确实可能会把IL想象得更类似汇编。。老赵的点选的很好。。想必包包看了也会理解更多的。。

  55. 飞林沙
    *.*.*.*
    链接

    飞林沙 2009-06-01 22:52:00

    @横刀天笑

    我寝室要熄灯了,回复最后一条明天来看结论,我这么说,这个例子不恰当,比如Add指令,在8086中对应的机器指令是2个字节位,而在80386中是4个字节位,那么是不是消耗的内存空间不等呢?
    如果你不看机器码,只看汇编,那么这个就被忽略了。当然实际中没人会去这么看,我只是说这个意思。

  56. 横刀天笑
    *.*.*.*
    链接

    横刀天笑 2009-06-01 22:53:00

    人的精力毕竟是有限的。
    经济学上有“机会成本”这个说法,衡量一个东西的成本是为了获得这个东西而失去的东西。
    要学习IL、汇编肯定会花费学习别的东西的时间,对于国内大部分开发人员这些东西貌似并没有多大用处(在面试的时候也许能忽悠一下)。在实际工作中也许工程方面的东西更值得我们去思索。

  57. 老赵
    admin
    链接

    老赵 2009-06-01 22:55:00

    --引用--------------------------------------------------
    zheciniming: 学metadata,是站在最核心的地方, 理解CLR对jit, exception, memory layout, type system, GC, code sign, interop的支持
    换句话说, 学IL会让你知道CLR的实现基础
    --------------------------------------------------------
    我觉得这话不对。
    从IL中是看不出JIT,Memory Layout,GC等问题的,因为这些是CLR的实现,是隐蔽的。IL只是可以认为是另一种高级语言,你看,连内存管理都没有在IL里体现,对吧?还有个例子,mono实现了另一个类CLR的东西,CLR很多东西IL是看不出来的。
    下一篇文章里我会详细谈一下。:)

  58. hoodlum1980
    *.*.*.*
    链接

    hoodlum1980 2009-06-01 22:57:00

    --引用--------------------------------------------------
    zheciniming: 为何
    C/C++为什么长远性能没有C#好
    C/C++为什么不能跨平台
    C/C++为什么不能很好的支持调试
    C/C++为什么不能在语言层面支持安全性声明
    C/C++为什么不能实现GC
    ...

    因为C/C++只有汇编,没有metaData
    --------------------------------------------------------
    你说的这些观点我不能同意。至少在目前的主流用户操作系统(XP)上,第一条显然不成立。第二条,C#也不能跨平台,跨的只是自己的平台!汗!第三第四什么意思,第五条,C/C++和C#的设计理念和宗旨导致的。就和你偏爱GC一样,C++偏爱效率和对底层的控制力。

  59. 老赵
    admin
    链接

    老赵 2009-06-01 22:58:00

    --引用--------------------------------------------------
    飞林沙: 话说这点上我也不赞同老赵的说法,我认为学习IL是非常必要的,不同的人爱好不同,有的人考虑的是学了这个我到底能干什么,比如老赵。很多人就是想学这个,不会去考虑这个对实际的工程项目影响,典型代表比如AnyTao。
    所以不应该盖个不该学IL的结论
    --------------------------------------------------------
    呵呵,其实我也学了无数我平时用不到的东西,比如AJAX。
    我也没有说不该学,我只是“建议”大家不必学,因为付出比不上回报。
    我相信anytao也不是不考虑这个问题的,可以问问他。
    我第4篇文章不是就要讨论这些问题吗?
    现在正是收集材料的时候,大家加油。

  60. zheciniming[未注册用户]
    *.*.*.*
    链接

    zheciniming[未注册用户] 2009-06-01 22:59:00

    @横刀天笑
    我认识的牛人,个个都是汇编等等底层技术的好手
    这才是最不忽悠的东西

  61. 老赵
    admin
    链接

    老赵 2009-06-01 23:00:00

    --引用--------------------------------------------------
    DiggingDeeply: IL会经JIT到汇编码吗?那样的话是不是还需要汇编器转换为机器码?还是直接到机器码,中间根本就没有汇编这一过程,而我们看到的汇编码则是由机器码转换而来?
    --------------------------------------------------------
    文章里提过了,下面的评论也说了,汇编其实就是机器码的助记符,可以完全看作一个东西,不需要“转化”这个过程。
    当然,其实JIT生成的是机器码,我们看汇编(比如用WinDbg),是被简单转化为文字形式了。

  62. 横刀天笑
    *.*.*.*
    链接

    横刀天笑 2009-06-01 23:01:00

    @zheciniming
    那要看所处的行业了,在底层开发,比如嵌入式等行业,那当然是了,但是企业级之类也许就不是了,我相信博客园里几位大牛级别的都不会是“汇编好手”。

  63. 老赵
    admin
    链接

    老赵 2009-06-01 23:02:00

    --引用--------------------------------------------------
    hoodlum1980:
    你说的这些观点我不能同意。至少在目前的主流用户操作系统(XP)上,第一条显然不成立。第二条,C#也不能跨平台,跨的只是自己的平台!汗!第三第四什么意思,第五条,C/C++和C#的设计理念和宗旨导致的。就和你偏爱GC一样,C++偏爱效率和对底层的控制力。
    --------------------------------------------------------
    其实IL可以认为是实现了跨平台,只是说没有去做而已,技术上和Java是类似的对巴,商业策略上讨论技术时不考虑,我觉得。
    而且,其实跨CPU平台也算是跨平台啊,呵呵。
    C++是源代码级别的跨平台,需要在不同平台上编译。C#,Java这种是二进制的跨平台,编译一次,四处运行。

  64. 老赵
    admin
    链接

    老赵 2009-06-01 23:03:00

    --引用--------------------------------------------------
    zheciniming: @横刀天笑
    我认识的牛人,个个都是汇编等等底层技术的好手
    这才是最不忽悠的东西
    --------------------------------------------------------
    不忽悠的东西有很多,比如你说Martin Fowler,DHH此类人,搞得东西是不是在忽悠呢?
    忽悠不忽悠不是看搞什么,而是看“怎么搞”。

  65. 幸存者[未注册用户]
    *.*.*.*
    链接

    幸存者[未注册用户] 2009-06-01 23:04:00

    @zheciniming
    我记得Bjarne Stroustrup曾经说过,Java不是真正的跨平台,因为JVM本身就是平台,而Java只能跑在JVM上;C#情况类似

    C/C++怎么不能很好的支持调试了?

    "C/C++为什么不能在语言层面支持安全性声明" 这句没看懂

    C/C++有GC的实现,虽然比JVM和CLR差远了,但在某些情况下够用了。

  66. zheciniming[未注册用户]
    *.*.*.*
    链接

    zheciniming[未注册用户] 2009-06-01 23:05:00

    @Jeffrey Zhao
    那时因为你把IL和metadata分开看了
    实现GC的还有一个VB
    VB里面编译出来其实也是metaData. 需要VB6runtime的帮助才可以实现具体的运行和GC
    把IL单独看,对别人的帮助是不负责任的
    你觉得CLR可以通过metaData+汇编实现么?

  67. 老赵
    admin
    链接

    老赵 2009-06-01 23:06:00

    @挑痘针
    我的看法是:
    你说的“宏汇编”,“高级汇编”是一种经过扩展的汇编“语言”,是一种语言,最后还是要被转化为机器码。
    我说的“汇编”是指汇编“指令”,是和机器码一一对应的东西。

  68. zheciniming[未注册用户]
    *.*.*.*
    链接

    zheciniming[未注册用户] 2009-06-01 23:09:00

    rotor有linux上的实现.helloworld.exe直接可以上去跑
    CLR都有开源的. 不过好像没有人研究下去.
    c++的异常处理? 你连callstack都看不到
    c++的程序你可以!dumpheap 么
    c++可以支持[StaThread]么?


    Martin Fowler,DHH此类人,你怎么就不知道不是个中好手?

  69. 屌毛[未注册用户]
    *.*.*.*
    链接

    屌毛[未注册用户] 2009-06-01 23:10:00

    老赵真是越来越屌了 说个话都是自称老赵 你有多老啊

  70. 幸存者[未注册用户]
    *.*.*.*
    链接

    幸存者[未注册用户] 2009-06-01 23:10:00

    @zheciniming
    我知道我们的祖师爷阿兰图灵肯定不懂汇编,不知道他算不算高手呢?

  71. 老赵
    admin
    链接

    老赵 2009-06-01 23:10:00

    @zheciniming
    我没有听懂你的意思。我并没有说IL和CLR是应该剥离看得,我的意思是从IL上看不出很多东西的实现,GC是其中一个。
    你觉得IL是从哪里体现出GC了呢?IL和C#等语言一样,关心的是分配,有关分配在什么地方,GC是怎么处理的,都是CLR做的。

  72. 老赵
    admin
    链接

    老赵 2009-06-01 23:13:00

    --引用--------------------------------------------------
    zheciniming: Martin Fowler,DHH此类人,你怎么就不知道不是个中好手?
    --------------------------------------------------------
    我是说“比如你说Martin Fowler,DHH此类人,搞得东西是不是在忽悠呢?”
    我并没有说他们不是汇编的中个好手,我的意思是,他们搞得东西肯定不能算是忽悠。
    或者说,就算他们不是汇编的个中好手,也不影响他们对业界的贡献。

  73. 老赵
    admin
    链接

    老赵 2009-06-01 23:14:00

    @DiggingDeeply
    汇编器其实只是一个一对一的翻译过程,替换过程——或者说,我们说的不是一回事情?
    上面已经有太多朋友解释过这个问题了,你可以参考一下他们的补充。

  74. 幸存者[未注册用户]
    *.*.*.*
    链接

    幸存者[未注册用户] 2009-06-01 23:15:00

    --引用--------------------------------------------------
    DiggingDeeply: --引用--------------------------------------------------
    Jeffrey Zhao: --引用--------------------------------------------------
    DiggingDeeply: IL会经JIT到汇编码吗?那样的话是不是还需要汇编器转换为机器码?还是直接到机器码,中间根本就没有汇编这一过程,而我们看到的汇编码则是由机器码转换而来?
    --------------------------------------------------------
    文章里提过了,下面的评论也说了,汇编其实就是机器码的助记符,可以完全看作一个东西,不需要“转化”这个过程。
    当然,其实JIT生成的是机器码,我们看汇编(比如用WinDbg),是被简单转化为文字形式了。
    --------------------------------------------------------
    我不同意你的观点。比如加法指令,加法指令比如编码是0001,但是对着的机器指令不一定是0001,需要汇编器来翻译成机器码。你说的助记符是有意义上的助记,不是格式上的。我参考的是C/C++的编译过程,期间是有汇编这一过程的,由汇编器将汇编码翻译为机器码。对于C#究竟是怎么由JIT解释执行的,这个我觉得还得看JIT是怎么实现的。也许JIT包含了汇编器的功能。
    --------------------------------------------------------
    助记符和机器码是一一对应的啊,你说的加法指令0001其实就是加法的机器指令啊。汇编的过程就是把助记符翻译成二进制01码,是一一对应的翻译。

  75. 老赵
    admin
    链接

    老赵 2009-06-01 23:28:00

    @DiggingDeeply
    汇编码自然不能被机器直接执行,机器执行的永远是机器码,汇编是给人看的,字符串,嗯嗯。
    我可能应该这么说,我们通过查看汇编,就可以知道机器是怎么在执行的了,一步一步对应,不会有偏差。
    // 文章结尾我做了一点补充,你看如何?

  76. zheciniming [未注册用户]
    *.*.*.*
    链接

    zheciniming [未注册用户] 2009-06-01 23:37:00

    阿兰图灵懂汇编

    你觉得在reflecotor里面看到的class定义, 是属于IL呢还是属于什么?

  77. 老赵
    admin
    链接

    老赵 2009-06-01 23:39:00

    --引用--------------------------------------------------
    zheciniming: 你觉得在reflecotor里面看到的class定义, 是属于IL呢还是属于什么?
    --------------------------------------------------------
    自然是属于IL(或者说,metadata),但是并无法看出CLR是如何处理它,如何创建它,如何回收他的阿。
    IL其实也是种高级语言,隐藏大量执行细节的一种高级语言。

  78. zheciniming [未注册用户]
    *.*.*.*
    链接

    zheciniming [未注册用户] 2009-06-01 23:49:00

    那你觉得没有metaData, GC能够实现吗,!dumpheap能够实现吗?
    你能看到的, 不应该只是“运行中”, 还应该包括能够运行的能力
    IL不单单描述了执行步骤, 还描述了type和其他的一些东西, 比如[STAThread]
    但是汇编只能描述执行
    我的建议是把眼光放IL对于在整个CLR的重要性来理解

  79. ocean
    *.*.*.*
    链接

    ocean 2009-06-01 23:49:00

    总体而言,老赵的文章还是很不错的,至少从概念上没有错误,而且论点和论据比较充分,发挥了我们所常说的always evidence your point的特点。

    对于IL,我也不太懂,虽然看过,但是没有怎么研究过,但是这个过程老赵确实说的是没有任何错误的,这点毋庸置疑。

    对于IL跨平台的问题,我想多说一句,CLR和JVM实际上是差不多的,所以我们只要在不同的操作系统上实现不同的CLR,就可以让我们的IL,也就是我们的托管程序集到处运行,只不过从微软自身的角度上来说,指实现了windows操作系统下的CLR,这个并不是说我们不能在其它操作系统上做,而是这个不能指望微软做,可能更多要期望开源组织吧。传说中的mono我没有用过,也没有研究过,但是貌似做了类似的事情。

    至于汇编,大家也不用较真了,老赵的意思实际上很清楚,对于汇编指令来说,和机器码确实是一一对应的。至于JIT是把IL翻译成汇编还是直接翻译成机器码,那肯定是翻译成机器码,cpu是只认0和1的。至于用windug看到的汇编指令,当然是windug这个软件将二进制的机器码翻译成了汇编指令以方便我们阅读。至于高级汇编,宏汇编之类的,就不在这个讨论范围了。

    至于学不学的问题,那要看你到底准备做什么。如果大家互相嘲笑的话,那就没头了,什么是真正的底层?
    会C#的有必要会IL吗?
    会IL有必要会汇编吗?
    会汇编有必要知道CPU是怎么设计的吗?
    会设计CPU有必要知道单晶硅是怎么提炼的吗?
    提炼单晶硅的有必要知道怎么淘沙子吗?

    在你有精力的情况下,多懂一点是好的,但是每个人的精力是有限的,把精力放在自己的核心竞争力的打造上就可以了,而这个核心竞争力,可以在任何一个层面上。无所谓高层,无所谓底层。

  80. 温景良(Jason)
    *.*.*.*
    链接

    温景良(Jason) 2009-06-01 23:53:00

    我喜欢这样讨论,老赵继续

  81. Ling Xu
    *.*.*.*
    链接

    Ling Xu 2009-06-01 23:57:00

    对于细节技术上的追究当然是有用的,然而透过这些技术细节看到其理论支持可能才是更加有意义的事情。

    IL和ASM本身出现的背景完全不同,把他们相提并论是不合适的,其背后的设计理念也完全不一样。

    毫无疑问的是现今IL的实现完全基于ASM,假设IL和ASM有完全一样的功能,那么还需要IL做什么?如果需要看到ASM所能表现的细节,那么就要去看ASM,而IL所要表现的细节则是另外的概念了。

    在IL中,类似于调用虚函数之类的事情,被认为是一个元操作,就类似于CPU也没有打算让你了解如何去执行一个加法操作一样。然而,相对于C#这类的高级语言来说,IL确实隐藏了不少细节。但即便MASM也支持函数和结构这样的概念(虽然不是非常强制性的),为什么IL就不能支持类和方法这样的概念呢?

    或许IL的价值正是在于其(高级)语言无关性和丰富的元数据,这个有助于在一个平台上统一各种语言,并且提供各种有用的功能。

  82. 老赵
    admin
    链接

    老赵 2009-06-01 23:58:00

    --引用--------------------------------------------------
    zheciniming : 那你觉得没有metaData, GC能够实现吗,!dumpheap能够实现吗?
    你能看到的, 不应该只是“运行中”, 还应该包括能够运行的能力
    IL不单单描述了执行步骤, 还描述了type和其他的一些东西, 比如[STAThread]
    但是汇编只能描述执行
    我的建议是把眼光放IL对于在整个CLR的重要性来理解
    --------------------------------------------------------
    明白你的意思了,谢谢,以后也可以多多交流。
    其实我从来没有说IL不重要,我想论述的其实是“学习IL”是否必要,这方面也希望可以多给我一些意见。:)

  83. feilng[未注册用户]
    *.*.*.*
    链接

    feilng[未注册用户] 2009-06-02 00:03:00

    IL可以理解为CLR虚拟机的汇编语言

  84. 幸存者[未注册用户]
    *.*.*.*
    链接

    幸存者[未注册用户] 2009-06-02 00:05:00

    --引用--------------------------------------------------
    zheciniming : 那你觉得没有metaData, GC能够实现吗,!dumpheap能够实现吗?
    你能看到的, 不应该只是“运行中”, 还应该包括能够运行的能力
    IL不单单描述了执行步骤, 还描述了type和其他的一些东西, 比如[STAThread]
    但是汇编只能描述执行
    我的建议是把眼光放IL对于在整个CLR的重要性来理解
    --------------------------------------------------------
    我觉得IL和metadata还是应该分开来看,IL和metadata是两个不同的概念。
    你说的GC,type,[STAThread]这些都属于metadata的能力,IL确实是只描述执行步骤的。如果有某种汇编能读取metadata,那也同样能实现上述功能。

  85. zheciniming [未注册用户]
    *.*.*.*
    链接

    zheciniming [未注册用户] 2009-06-02 00:22:00

    所以我先问清楚, 我们讨论的IL,是否归纳入metadata

    大家怎么理解无所谓, 我的意见是, 不能脱离metadata来讨论. 而metadata也不单单包含了IL的执行描述, 而是应该把眼光放在CLR本身

    学习IL/Metadata的说法本来就不好. IL/Metadata的意义应该站在计算机体系结构上来看. 这个跟compiler一样, 属于VM类体系的必不可少部分, 所以自然也就包含了jit/GC/Exception这些等等

    IL/Metadata的理解, 是研究计算机原理的自然而然的步骤. 如果不是做debugger, de-compiler等binary和VM技术相关的, 是没有必要专门研究的, 最多就知道用reflector就可以了

    而汇编却不一样了. 不仅仅是C/C++的编译结果, 而且对于C/C++的调试是必不可少的能力. 另外写C/C++的程序, 内联汇编, 处理不同模块的衔接, 进行代码移植等等, 汇编就是基本技能.

    回答
    “学习IL”是否必要

    我的答案:

    99%的情况都是没有必要,除非特殊应用.
    对IL/Metadata的深入理解,往往不是因为你"为了"学它, 然后学会了它. 而是在你对其他相关技术的研究过程中, 自然而然悟道了IL/Metadata的存在和必要性. 比如考虑为何CLR可以打出callstack, 为什么C++没有GC, 为什么C++没有sos.dll. 这里的关键在于理解metadata/IL的存在意义, 而不在于某一个指令是什么意义

    "学习汇编"是否必要
    我的答案:

    当你走到某一个阶段, 就一定是必要的. 而且我相信专著技术的工程师都应该走到这个阶段. 所以答案是必要.
    汇编解释了计算机中最核心的东西. 比如stack,体系结构,内存组织. 揭示了很多原理比如寄存器,内存和IO的速度. 解释了很多看起来高深的理论, 比如代码优化, catch命中, 多线程冲突. 不学习汇编, 这些都只能了解皮毛.
    另外汇编也有单独的应用, 比如跨平台的代码移植等

  86. 老赵
    admin
    链接

    老赵 2009-06-02 00:30:00

    重读文章内容,忽然意识到,我谈汇编最终把自己也给绕进去了。
    其实我下一篇文章是想谈论“CLR内部有太多太多IL看不到的东西,包括您平时必须了解的那些”,而不是“汇编可以看到IL太多看不到的东西”。
    犯这个错误实在不应该,说明写文章时思路还有些急躁,需要改正。

  87. zheciniming [未注册用户]
    *.*.*.*
    链接

    zheciniming [未注册用户] 2009-06-02 00:38:00

    就是
    不能拿汇编来和IL比
    不然真去学习这个指令啥意思,那个指令啥意思, 就sb了

  88. zheciniming [未注册用户]
    *.*.*.*
    链接

    zheciniming [未注册用户] 2009-06-02 00:44:00

    另外给老赵提醒下,别人我一般不说的
    没有x64的说法
    只有x86, x86-64, AMD64的说法
    具体参考:

    http://en.wikipedia.org/wiki/X86-64

    "The x86-64 specification was designed by Advanced Micro Devices (AMD), who have since renamed it AMD64"

    而且ms的release也是:
    x86fre
    x86chk
    ia64fre
    ia64chk
    amd64fre
    amd64chk

  89. 幸存者[未注册用户]
    *.*.*.*
    链接

    幸存者[未注册用户] 2009-06-02 00:49:00

    @zheciniming
    我觉得了解计算机体系结构、CPU、寄存器、stack、heap这些东西是很重要,这些都是计算机运行的基本原理,但是这些东西跟汇编无关,汇编只是用来控制计算机按照其基本原理运行的一组符号。
    不过我又想了想,似乎了解这些原理的一个基本手段就是通过汇编,这么说的话汇编的确有其重要性,但是必须说明的是,学习汇编只是手段,而不是目的。就好比说我只想学数学,根语文看似无关,但是如果不懂语文学起数学就会很困难,因为数学概念本身是很抽象的,需要通过具体的表述能力强的文字将其表达出来才能易于学习,也许这个例子不太恰当,不过只要能明白我的意思就行了。

  90. EricZhang(T2噬菌体)
    *.*.*.*
    链接

    EricZhang(T2噬菌体) 2009-06-02 00:55:00

    IL和汇编在本质上绝对是两码事

  91. 老赵
    admin
    链接

    老赵 2009-06-02 00:59:00

    @zheciniming
    谢谢提醒,已经改正,下次一定多考证一些再写入文章。:)

  92. hoodlum1980
    *.*.*.*
    链接

    hoodlum1980 2009-06-02 01:07:00

    和有些思想也真是没法解释的清楚。正好我前不久写了一个ZOJ上的题目,就属于模拟一个微型计算机的执行一段代码的过程的:

    《ZOJ - 1098 Simple Computer 解题报告 》
    http://www.cnblogs.com/hoodlum1980/archive/2009/03/11/1409205.html

    从累加器,存储单元,PC(程序计数器),到一个简单的指令集都有了。

    什么叫立即数,立即数就是嵌入到指令里的,是这条指令的一部分。也就是指令直接提供一个操作数。

  93. zheciniming [未注册用户]
    *.*.*.*
    链接

    zheciniming [未注册用户] 2009-06-02 01:12:00

    @幸存者
    不真正去读汇编, 所谓的理解只是皮毛

    比如就说两个thread操作同一个内存变量
    如果不懂
    MOV指令, 看不懂寄存器符号的话
    那我觉得这个所谓的理解了, 就要打个折扣了

    再比如Access Violation, 不懂汇编里面的[]地址操作符, 不知道EIP寄存器,不知道第一个exception filter保存的地方, 怎么理解异常如何发生如何派发

    还有stack overflow. 不知道EBP ESP的恢复, 分配stack变量的ESP EBP位移, RET指令的具体功能, 也没办法明白attach怎么出来的

    都到CPU寄存器了,汇编就那么10来个命令而已, 有什么借口不多走一步

  94. hoodlum1980
    *.*.*.*
    链接

    hoodlum1980 2009-06-02 01:14:00

    如果你开发过单片机你就知道了写汇编是怎么样的,先指定一个地址,然后就是接着一句一句的往下写。你将能够看到你的每条指令对应的一个地址。

  95. zheciniming [未注册用户]
    *.*.*.*
    链接

    zheciniming [未注册用户] 2009-06-02 01:26:00

    IL里面最珍贵的东西
    是方法上一个叫做
    [InternalCall]
    的属性
    看看谁能讨论下这个

  96. 躺着读书[未注册用户]
    *.*.*.*
    链接

    躺着读书[未注册用户] 2009-06-02 05:43:00

    搞不懂为什么.net里面就这么重视IL干什么。

    IL对应的是Java的bytecode(字节码)。看看Java社区的现状,国内几乎没有人关心bytecode。目前处理bytecode的有一个ASM的项目,在国内Java社区几乎无人问津。
    总的来,如果Java程序员关心到了Java的IL——字节码,通常就是里两个用途:
    1.重写字节码。目的是为了实现面向切片编程,或者是为了实现静态的代理,提高动态代理的性能。但是即使是重写字节码,也会直接根据目的选择现成的工具,如CGLib等。
    2.实现用perl等脚本语言批量生成字节码。或者基于jvm平台的其他语言的开发。这种开发人员才会真正的关心字节码。

    其实,与其关心Java字节码,倒不如关心下是apache的容器性能好,还是J2SE自带的容器性能好。是IBM的JVM的垃圾收集性能优异,还是SUN的垃圾处理性能好。以及多线程的并发/锁的开销。这些才是真正的性能瓶颈所在。

    我觉得一个语言就应该对应一个抽象层,关心得太多肯定不是好事。唉,什么时候Java也能有这么多的人关心下Java字节码啊~~~~

  97. Nick Wang (懒人王)
    *.*.*.*
    链接

    Nick Wang (懒人王) 2009-06-02 07:32:00

    讨论了半天的IL和ASM,弱弱的问一句:现在学校里是不是都不教汇编了?

  98. DiggingDeeply
    *.*.*.*
    链接

    DiggingDeeply 2009-06-02 07:43:00

    --引用--------------------------------------------------
    zheciniming : IL里面最珍贵的东西
    是方法上一个叫做
    [InternalCall]
    的属性
    看看谁能讨论下这个
    --------------------------------------------------------
    这个实际上是个内部的一个函数调用的映射,InternalCall的代码都是非托管的,详细的你可以参考rotor里clr\src\vm\ECall.cpp,所有的InternalCall都有映射。

  99. QQTest[未注册用户]
    *.*.*.*
    链接

    QQTest[未注册用户] 2009-06-02 08:14:00

    Good!

  100. zs851[未注册用户]
    *.*.*.*
    链接

    zs851[未注册用户] 2009-06-02 08:23:00

    --引用--------------------------------------------------
    Nick Wang (懒人王): 讨论了半天的IL和ASM,弱弱的问一句:现在学校里是不是都不教汇编了?
    --------------------------------------------------------
    当然教汇编了啊!不过都是基础的

  101. Windie Chai
    *.*.*.*
    链接

    Windie Chai 2009-06-02 08:33:00

    顶老赵,分析的不错,而且态度很中肯!

  102. 阿水
    *.*.*.*
    链接

    阿水 2009-06-02 08:46:00

    老赵老赵,别人已经开贴回复了,赶紧过去那边吧!
    开辟第二战场,诺曼底登陆!!!
    登陆地点
    http://www.cnblogs.com/Jax/archive/2009/06/02/1494167.html

  103. 翔诚
    *.*.*.*
    链接

    翔诚 2009-06-02 09:03:00

    会C#的有必要会IL吗?
    会IL有必要会汇编吗?
    会汇编有必要知道CPU是怎么设计的吗?
    会设计CPU有必要知道单晶硅是怎么提炼的吗?
    提炼单晶硅的有必要知道怎么淘沙子吗?
    ________________________________

    硬是要得

  104. Jester Zhu
    *.*.*.*
    链接

    Jester Zhu 2009-06-02 09:31:00

    你们都是园子里的名人,但是有一点我确实想说说,无论是谁,名人应该有你们上层阶级该遵守的条规,做人做事都要低调,因为你们太出名了,所以向我这样的菜鸟对你们的观点90%以上都是相信的,所以你们应该有严谨的治学态度,金无足赤,人无完人。真正为我们菜鸟阶级树立个榜样,只有这样才能在我们的领域里面,继续探索新发现,提出新观点。观点当然可以提,但是必须有实践做基础,毕竟实践是检验真理的唯一标准。

    所以希望名人本着高度负责的原则,真正为我们办好事办实事,因为你们每说的一句话都可能影响一些人甚至更多人!

  105. xjb
    *.*.*.*
    链接

    xjb 2009-06-02 09:37:00

    这样讨论对大家都有益

  106. jim.c[未注册用户]
    *.*.*.*
    链接

    jim.c[未注册用户] 2009-06-02 09:40:00

    似乎老赵早就说了,基础很重要,又把还给老师的复习了一下

  107. ♂风车车.Net
    *.*.*.*
    链接

    ♂风车车.Net 2009-06-02 09:46:00

    我觉得,大家也不要争来争去了.
    每个人的认识不一样,不一定非要把别人说死了才罢休.
    反正都是技术的交流,建议直接从具体的示例来说明问题.

  108. 韦恩卑鄙
    *.*.*.*
    链接

    韦恩卑鄙 2009-06-02 10:08:00

    恩 难道是 List JIT优化问题让老赵很郁闷

  109. zheciniming [未注册用户]
    *.*.*.*
    链接

    zheciniming [未注册用户] 2009-06-02 10:23:00

    @DiggingDeeply
    单独的一个影射表当然简单了
    问题在于, CLR里面的类型, 通过internall进去MSCORWKS的实现中, 怎么直接使用的呢?
    internallcall里面的内存分配, 要在托管堆中处理吗?

  110. xxxxxxxxxxxxxxxxx[未注册用户…
    *.*.*.*
    链接

    xxxxxxxxxxxxxxxxx[未注册用户] 2009-06-02 10:57:00

    呃。。不是很懂就出来乱说。。。建议重新读一读编译原理。。。

  111. 老赵
    admin
    链接

    老赵 2009-06-02 11:01:00

    --引用--------------------------------------------------
    韦恩卑鄙: 恩 难道是 List JIT优化问题让老赵很郁闷
    --------------------------------------------------------
    这个问题,接下来的文章里会观察一下的,作为示例,目前看来的确不是JIT优化的结果,是C#编译器干的。

  112. .。oоΟ○〇
    *.*.*.*
    链接

    .。oоΟ○〇 2009-06-02 11:30:00

    --引用--------------------------------------------------
    Nick Wang (懒人王): “什么时候应该学IL,该怎么学IL”
    很多人不想知道“什么时候”应该学,而是“应不应该”学。他们只想要一个现成的结论,而不是自己思考。

    又习惯性的跑题了 :p
    --------------------------------------------------------
    此君说出了很多人的想法(包括我)..>_<..

  113. cnbloger
    *.*.*.*
    链接

    cnbloger 2009-06-02 11:30:00

    framework安装后是不是自动安装了多个不同CPU架构下的JIT编译器?

  114. 老赵
    admin
    链接

    老赵 2009-06-02 11:36:00

    @cnbloger
    其实是,不同的平台下只能下载不同的.NET Framework来装。

  115. 韦恩卑鄙
    *.*.*.*
    链接

    韦恩卑鄙 2009-06-02 11:43:00

    都是些坏人 皑皑

  116. cnbloger
    *.*.*.*
    链接

    cnbloger 2009-06-02 11:44:00

    很想看到老赵对IL的理解。
    如果能把这些概念也加上"老赵的解释"那将是园之大幸,我之大幸!O(∩_∩)O~
    Framework、CLI(Common Language Infrastructure)、CIL(Common Intermediate Language)、CLR(Common Language Runtime)、CTS、JIT。
    另外特别希望看到老赵讲解IIS处理流程和ASP.NET Page LifeCycle。最好能与日常web开发的场景对应起来。
    一下子提了这么多“要求”,不好意思。


  117. 韦恩卑鄙
    *.*.*.*
    链接

    韦恩卑鄙 2009-06-02 11:47:00

    --引用--------------------------------------------------
    .。oоΟ○〇: --引用--------------------------------------------------
    Nick Wang (懒人王): “什么时候应该学IL,该怎么学IL”
    很多人不想知道“什么时候”应该学,而是“应不应该”学。他们只想要一个现成的结论,而不是自己思考。

    又习惯性的跑题了 :p
    --------------------------------------------------------
    此君说出了很多人的想法(包括我)..&gt;_&lt;..
    --------------------------------------------------------
    就好像 asp.net mvc 我一直觉得我不该马上学 结过公司需要我学 这不是在学么。。。

    不深入不代表不要了解一点周边的知识 我们可以去观察外围的东西 保证自己学习的时候不会完全没有头绪

    不赞成没有需求就去啃书 这样会缺少思考的空间。 但是没有需求的时候是可以记住包包有一本翻译好的好书的。对我个人来说这样是最好的

  118. cnbloger
    *.*.*.*
    链接

    cnbloger 2009-06-02 11:48:00

    @Jeffrey Zhao
    那是VS自带了多个不同版本的.NET Framework?
    安装VS的时候它总不能先根据本地CPU去下载Framework吧?

  119. 老赵
    admin
    链接

    老赵 2009-06-02 12:10:00

    @cnbloger
    不同平台使用的也是不同的VS,为x86编译的VS不能装在IA64上。其实软件都是这样的,因为大家的指令集,内存模型都不同,怎么能用一样的程序呢?
    // 这里的“程序”是指直接编译成本地代码的程序。

  120. 银河使者
    *.*.*.*
    链接

    银河使者 2009-06-02 12:39:00

    需要更正一下,不管是什么语言编译的目标文件,exe、dll等,都是静态的,当然,也不管它是汇编而成的,还是编译而成的。而动态的,是指程序在运行时所处理的数据。编译后的程序指令不会是动态的,不会编译完是add,运行后是sub了,那不就乱套了。
    实际上,我们使用的C/C++,在编译成exe之前,也是将将源代码进行汇编,再转换成机器码,只是这个过程大多数的时候都是不透明的。这和编译器的实现有关。
    再说说IL。这个东西是微软发明的一种二进制标准(类似于java的.class文件)。它也和汇编一样,有一些指令在汇编里add表示加,在IL里也有add,这两个实际上都是由一个指令码(整型数表示的),因此,我们在UltraEdit32在看到了就是这些指令码和指令码操作的数据。而使用ildasm.exe看到的实际上是将这些指令码和操作数据转换成了可读的形式,也就是象汇编的助记符一样。
    还有一点要说的,就是IL是大大的有用,当然了,这里的有用,都是高级的应用。我也不在这里说它有多高级。只举一个例子。也许地球人都知道,一个类必须至少有一个构造方法。而子类呢,必须要调用父类的某一个构造方法。这也就是在父类中尽量要有无参数的构造方法的原因。但我要实现一个功能,使在创建子类的对象时,不调用父类的构造方法,那么这如何做呢,显然使用C#或VB.net是无法办到的。而使用IL确可以很容易做到。C#和vb.net是通过编译器对IL的功能做了限制。而直接用IL的完全没有任何限制的。我以前做的一个AOP框架(基于C#2.0)就是直接使用Emit技术写IL。IL的确很强大。 关于emit,可以参考我的文章:http://www.cnblogs.com/nokiaguy/archive/2008/05/12/1193073.html

  121. ZelluX[未注册用户]
    *.*.*.*
    链接

    ZelluX[未注册用户] 2009-06-02 13:32:00

    @银河使者
    关于第一段,建议看看这个
    http://en.wikipedia.org/wiki/Self-modifying_code

  122. Steven Chen
    *.*.*.*
    链接

    Steven Chen 2009-06-02 13:41:00

    --引用--------------------------------------------------
    cnbloger:
    另外特别希望看到老赵讲解IIS处理流程和ASP.NET Page LifeCycle。最好能与日常web开发的场景对应起来。
    一下子提了这么多“要求”,不好意思。
    ------------------
    实际上这些东西园子有很多了,现在大家最想看到的是WCF的流程,这个绝对要比asp.net更加精彩,希望Artech或者是有人能够整理出来,本人最近开始学习DomainObject和Select,不再学习IL和windbg,感觉企业应用中设计的一些东西还是非常重要的。


    --引用--------------------------------------------------
    zheciniming : @幸存者
    --------------------------------------------------------
    刚开始还以为你是老包的马甲呢,后来发现应该不是,老包没这个水平。
    如果方便,加我MSN如何?拜一拜大师 StevenChennet@live.com



    To 老赵:
    您老人家苦口婆心的给别人指明灯,再看看园子里随着你和老包这个口水新开的那几个帖子,真让人心寒阿,在我看来他们都没有好好读你和老包的文章就发水文,IL ASM windbg......这情形和这两天讨论三层和架构的那些水文有何区别,幸好噬菌体写了一篇东西阐述了一下,虽然没怎么讲清楚。

  123. bbpnb[未注册用户]
    *.*.*.*
    链接

    bbpnb[未注册用户] 2009-06-02 14:34:00

    老赵就别再和包建强辩了,很多问题基本上不值一辩,呵呵,期待你的IL后文,也不必带太多主观色彩了。

  124. 老赵
    admin
    链接

    老赵 2009-06-02 18:43:00

    --引用--------------------------------------------------
    bbpnb: 老赵就别再和包建强辩了,很多问题基本上不值一辩,呵呵,期待你的IL后文,也不必带太多主观色彩了。
    --------------------------------------------------------
    明白了,下面只谈技术问题。

  125. MShijie
    *.*.*.*
    链接

    MShijie 2009-06-02 18:51:00

    @Colin Han
    第二个理由,我觉得还是用.Net Reflector反编译看来得直接明了

  126. kwanhong young
    *.*.*.*
    链接

    kwanhong young 2009-06-02 22:01:00

    从这篇文章可以看出老赵的计算机基础知识还是很扎实的,实际上我已经很久没有遇过做.net程序开发的人能搞清楚这些概念了。之前也是因为动态反编译和静态反编译的理解问题在一个论坛上跟人闹僵,后来发现大部分人都没时间去也不愿意去理解这些内容时才渐渐地不计较了

  127. kwanhong young
    *.*.*.*
    链接

    kwanhong young 2009-06-02 22:18:00

    还有一个建议,就是对“汇编”这个词的理解,你不可能指望所有人都是从数字逻辑、数字电路、组成原理、汇编、C语言……这样的顺序来学习的,所以有些人第一次接触“汇编”这个词的确是微软所说的“IL汇编”,可能微软本身也有些混淆视听的意思,或有有些教科书翻译混乱,所以导致一部分人都不知道有“助记符”汇编这么一个事物。所以建议文章中写着“助记符 汇编”会比直接写“汇编”会好区分些

  128. 老赵
    admin
    链接

    老赵 2009-06-02 22:18:00

    --引用--------------------------------------------------
    Frank Wang: 汇编语言写的程序,不是要通过汇编(动词)翻译成机器码(01代码),CPU才能识别码?什么时候CPU高级到能直接读懂汇编语言了?
    --------------------------------------------------------
    其实我的意思并不是这个,呵呵。
    你说的没错,是我没有说明白。
    文章最后已经有了注释,不知是否说清楚了。

  129. 老赵
    admin
    链接

    老赵 2009-06-02 22:21:00

    @kwanhong young
    你的建议很对,我现在正在写第2篇文章,在一开头已经“澄清”、“定义”了我对于“IL”和“汇编”在文章中的含义了,应该不会再有问题了。:)

  130. kwanhong young
    *.*.*.*
    链接

    kwanhong young 2009-06-02 22:22:00

    --引用--------------------------------------------------
    Jeffrey Zhao: --引用--------------------------------------------------
    Frank Wang: 汇编语言写的程序,不是要通过汇编(动词)翻译成机器码(01代码),CPU才能识别码?什么时候CPU高级到能直接读懂汇编语言了?
    --------------------------------------------------------
    其实我的意思并不是这个,呵呵。
    你说的没错,是我没有说明白。
    文章最后已经有了注释,不知是否说清楚了。
    --------------------------------------------------------

    老赵回复相当快,怀疑正在不断刷新评论 ^_^

    @Frank Wang: “汇编(动词)”应该是“编译(动词)”

  131. Frank Wang
    *.*.*.*
    链接

    Frank Wang 2009-06-02 22:28:00

    高手果然是高手,看急了.
    很喜欢你的文章.

  132. Colin Han
    *.*.*.*
    链接

    Colin Han 2009-06-03 11:39:00

    @MShijie
    呵呵,现在的Reflactor太强悍了,匿名方法都可以给你反编译出来了。
    其实,我也是那Reflactor看IL的,ILDasm很少用,只有第三条曾经用过。

  133. 试小邪
    *.*.*.*
    链接

    试小邪 2009-06-03 14:52:00

    IL转化为JIT再转化为机器码(可以用‘指令’汇编查看)!
    还是我们用平台JIT直接把IT转化为机器码?

  134. 老赵
    admin
    链接

    老赵 2009-06-03 14:59:00

    @试小邪
    JIT是编译器,把IL转为机器码。

  135. 试小邪
    *.*.*.*
    链接

    试小邪 2009-06-03 15:51:00

    我是小菜鸟!看了两篇文章和评论,让一个小菜鸟对整个IT编程结构有部分整体的了解!
    .Net(平台吗)(包括C#,VB.F#)在IL(属于CLR吗)上统一,然后通过JIT 编译成机器码!
    Java到JavaBytecode,到JVM再到(汇编转化机器码)/机器码(那个不是很清楚)
    C/C++到ASM 再到汇编

    到机器码跟CPU架构不同有关
    CLR(不一样的平台不一样)包括(很多,IT(metadata是执行描述), JIT,GC等等)跟JVM/ASM都是转化为CPU执行用的平台
    还有涉及到的很多东西就不是很清楚了!
    是否去看书了解上面的名称意思及关系!给自己构造一个体系,做到心里有底,然后去学习会提高很多的效率?

  136. 试小邪
    *.*.*.*
    链接

    试小邪 2009-06-03 15:52:00

    很有效果,了解了很多东西,引起我很多兴趣,会去了解疑惑!

  137. 老赵
    admin
    链接

    老赵 2009-06-03 16:06:00

    @试小邪
    asm就是指汇编。

    C# => IL => 机器码
    Java => Bytecode => 机器码
    C => 机器码

    当然中间肯定会是有多个步骤,tokenizer, linker, assembler等等,我说的只是几个“明显”的。

  138. 张荣华
    *.*.*.*
    链接

    张荣华 2009-06-03 23:24:00

    老赵刚才又去翻了翻《Essential .NET》、《CLR via C#》这《Customizing the .NET Common Language Runtime》这几本“偏底层”的书,
    中间是不是多了一个“这“呢?

    原理是明白,但是发现平常基本上没有关注过IL,对IL指令了解也有限。感觉做应用开发的话,IL帮助不是太大吧?

  139. ZelluX[未注册用户]
    *.*.*.*
    链接

    ZelluX[未注册用户] 2009-06-12 02:45:00

    不过我也不觉得区分bytecode和x86指令有多么重要,都不过是API的一层抽象而已。bytecode最后的确要转成x86指令才能执行,但是x86指令是cics的,现在常见的实现最后还是要进一步转成类似于cics的指令来执行的(比如movl会被拆成若干个更简单的指令),从这个角度来说bytecode和x86指令并没有很大的区别。无非是一个跑在CLR上,一个直接跑在CPU上。

  140. 老赵
    admin
    链接

    老赵 2009-06-12 09:10:00

    @ZelluX
    嗯,两者确有相似之处,但我还是认为这点相似之处不足以让两者可以等同对待起来。
    bytecode比x86指令高级的不是一点点。

  141. Damon King
    *.*.*.*
    链接

    Damon King 2009-06-12 16:55:00

    假如汇编是机器码的助记符,那么用0,1是可以直接编写出CPU可以运行的机器码了。我指的是用电话机恢复了Window95系统的那个故事.我所以说是恢复,因为用0,1不可能在那么短的时间内搞出带UI的东西。
    ----------------------------
    PS:老赵说的正确,我在看包子的文章,会有种迷茫感,但因为他讲的范围太广,水又很深,不是我能辩驳的了的。虽然讨论到深处,大家的观点都有相似的地方,但是用文字表述出来,确不是那么容易像老赵这样一针见血的。如此一来就容易误导人了。

  142. Damon King
    *.*.*.*
    链接

    Damon King 2009-06-12 16:57:00

    上面所说的假如,是本人个人推测那个故事中操作的可行性。
    本人认同汇编是机器码的助记符这个说法。

  143. 子曰
    *.*.*.*
    链接

    子曰 2009-06-13 13:48:00

    顺带问下。C语言代码编译成的是机器码,那么他是怎么实现可移植性呢?

  144. 老赵
    admin
    链接

    老赵 2009-06-13 14:27:00

    @子曰
    为不同平台各编译一次

  145. Strong Bird[未注册用户]
    *.*.*.*
    链接

    Strong Bird[未注册用户] 2009-06-15 15:38:00

    其实汇编还不是机器码,但是汇编可以和机器码对应起来。大学里学微机实验的时候做过直接对着一块板子写微指令,这些微指令就是真正的机器码。

  146. henryhuang[未注册用户]
    *.*.*.*
    链接

    henryhuang[未注册用户] 2009-07-01 14:02:00

    to老赵: 你的文章写得很好,道理阐述得非常清晰,初学者看了也不会觉得迷茫,这一点是非常值得赞赏的。但是令我不解的是,以你的修行,怎么会不理解包健强呢?初学者比理解倒是有情可原。这一点包同学确实应该向老赵学习。我想包同学将IL说成是一种汇编语言是一种非常形象而生动的,这显然是一种概念上的引伸。以包同学的修行决定不会区分不开“汇编语言”和IL的。我认为包同学的意思是:如果将CLR看做高级CPU,程序集便是能够在这个CPU上可执行代码,而IL就是这可执行代码的“汇编”。
    大家都知道虚拟机的概念吧,z/OS上有linux的虚拟机,linux的指令集是针对x86的,而z/OS则是IBM大机的指令集,虽然linux虚拟机上的可执行程序没有直接工作在IBM大机的CPU上,我们仍然把这个可执行程序的文字表现形式称为“汇编代码”。从这个意义上讲,{汇编是机器码的文字表现形式,提供了一些方便人们记忆的“助记符”}中的机器码不必是针对物理的CPU。如果我们对CLR有足够了解,就像我们对x86 cpu一样了解,也许x86汇编对我们没有太大价值。我们不得不承认跟踪CLR执行的汇编代码确实会让我们更了解CLR。也许有一天CLR会固化在真正的物理CPU上。CLR的实现途径可以不必“由IL”编译成“汇编”,这只不过是当前技术的限制而已。

    我不想看到有人在技术上相互拆台,钻牛角尖,同样是这篇文章,如果采用另外一种方式表达,也许将更和谐,也会让读者有更多的学习机会,包建强的文章也很不错。

    希望你的这篇文章没有误导读者,当然我指的不是技术。我很赞赏你的表述能力。但是请停止攻击,团结起来,互相补台。这样,我们这些读者就可以看到更多优秀的文章,而是不是无聊的口水

  147. 老赵
    admin
    链接

    老赵 2009-07-01 14:39:00

    @henryhuang
    呵呵,如果是以前,我会好好说。但是经过了一些事情以后,我发现最适合的还是不留情面地开唰。有些人有些东西,不是能够“补台”的了的。
    你说“包建强”的文章好,我想这应该是套话,我真看不出来。当然,我也希望您可以详细谈谈您的看法。他写了什么?发表了一堆翻译地歪七歪八的文字,或者随便贴了一点代码而已。
    一个扯蛋的说一句“鱼在天上飞”和一个真正的思想家说出来,含义是不一样的。
    你去看一下我指出他文章的上下文就知道他究竟是比喻还是真分不清了。或者看看他新写的文章,会找到“偷换概念”的实例。
    所以,除非他有改观,否则我见到他扯一次蛋,我还是会狠狠批驳一番的。您认为他是高手,我觉得他其实是在伪装到现在——看看他写了多少天花乱坠的东西,写了多少自己真正的感想就知道了。
    博客园好文章和踏实搞技术的人很多。说他的文章好,真的太糟塌博客园和其他认真写文章的兄弟们了。
    这就是我要反对的:如果社区把一个扯蛋的还当作高手,前途何在?分辨事物的基本能力啊。

  148. 老赵
    admin
    链接

    老赵 2009-07-01 14:48:00

    @henryhuang
    对了,我批包建强的感想,其实和有一段时间javaeye上众人批李刚的感觉是差不多的。在google上搜索一下“javaeye 李刚”可以知道前因后果。
    有些东西,真是“团结”不得的。

  149. Ben
    *.*.*.*
    链接

    Ben 2009-07-09 18:34:00

    这个页面也太霸道了吧。
    怎么有这样一段JS


    <script language="javascript" type="text/javascript">
    if ($.browser.msie && $.browser.version < 7) {
    eval("ale" + "rt('IE 6? Please use IE 8 instead!')");
    window.location = "http://www.microsoft.com/windows/internet-explorer/";
    }
    </script>

    不用IE8,就强制给你弹到IE8下载页面。

    很不好

  150. 老赵
    admin
    链接

    老赵 2009-07-09 18:36:00

    @Ben
    错了,是如果你用了IE6或更低版本IE,就会让你去用IE8。
    IE7是可以的。

  151. Ben
    *.*.*.*
    链接

    Ben 2009-07-09 19:08:00

    老赵,那段JS还是不对,
    我用的是Vista + IE8,一样提示。

    其实提示还是无所谓,但是强制指向IE8的下载页面也太死了

  152. 老赵
    admin
    链接

    老赵 2009-07-09 19:30:00

    @Ben
    if ($.browser.msie && $.browser.version < 7)
    这个判断没有问题啊,我用Vista + IE 8就没有问题的。

    直接跳转最为方便嘛,有人的做法是用个遮罩,然后显示一些信息,这样就组织用户操作了。
    等我有兴趣了,再慢慢搞一下。:)

  153. 老赵
    admin
    链接

    老赵 2009-07-09 19:59:00

    @Ben
    你可不可以在IE8的浏览器地址栏里运行如下代码,然后把结果贴给我看一下呢?
    javascript:document.write(navigator.userAgent);
    比如我在IE8里获得的结果是:
    Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.0; Trident/4.0; SLCC1; .NET CLR 2.0.50727; .NET CLR 3.5.21022; InfoPath.2; MS-RTC LM 8; OfficeLiveConnector.1.3; OfficeLivePatch.0.0; .NET CLR 3.5.30729; .NET CLR 3.0.30729)

  154. Ben
    *.*.*.*
    链接

    Ben 2009-07-09 20:34:00

    运行结果如下


    Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.0; Trident/4.0; Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1) ; SLCC1; .NET CLR 2.0.50727; Media Center PC 5.0; .NET CLR 3.5.30729; InfoPath.2; .NET CLR 3.0.30729; OfficeLiveConnector.1.4; OfficeLivePatch.1.3)

    比较奇怪了,早就安装了IE8。还是看到是7.0


    怀疑机器被什么修改了useragent

  155. 老赵
    admin
    链接

    老赵 2009-07-09 21:45:00

    @Ben
    真奇怪,按理说我的代码也没有写错啊。一会儿我做个试验看看。
    谢谢提醒!

  156. wu0527[未注册用户]
    *.*.*.*
    链接

    wu0527[未注册用户] 2009-07-10 16:27:00

    老赵你为何不让ie6浏览啊

  157. 老赵
    admin
    链接

    老赵 2009-07-10 16:31:00

    @wu0527
    因为IE6应该被时代淘汰了,各方面都远远落后于现代浏览器。

  158. jivi
    *.*.*.*
    链接

    jivi 2009-07-30 16:36:00

    CPU 是不认识汇编代码的。他只认识指令。同一条汇编语句,因为操作数的类型不一样。WORD或者DWORD对应的指令是不一样的。汇编也有很多种。但任何一种汇编只不仅仅是 普通理解 的那种“只是一种指令的助记符”而已

  159. jivi
    *.*.*.*
    链接

    jivi 2009-07-30 16:39:00

    Ben:
    这个页面也太霸道了吧。
    怎么有这样一段JS


    <script language="javascript" type="text/javascript">
    if ($.browser.msie && $.browser.version < 7) {
    eval("ale" + "rt('IE 6? Please use IE 8 instead!')");
    window.location = "http://www.microsoft.com/windows/internet-explorer/";
    }
    </script>

    不用IE8,就强制给你弹到IE8下载页面。

    很不好


    同意。老赵的很多文章还是不错的。但这点还是很霸道的。我用IE6打开他。被无缘无故的骂了一顿。很郁闷。用Opera也打不开。只好使用FireFox了。但FireFox在我的机子上光打开得半分钟

  160. 老赵
    admin
    链接

    老赵 2009-07-30 16:43:00

    @jivi
    1、我写过任何一句骂人的话吗?
    2、Opera我试过,可以打开。

  161. 老赵
    admin
    链接

    老赵 2009-07-30 16:44:00

    jivi:CPU 是不认识汇编代码的。他只认识指令。同一条汇编语句,因为操作数的类型不一样。WORD或者DWORD对应的指令是不一样的。汇编也有很多种。但任何一种汇编只不仅仅是 普通理解 的那种“只是一种指令的助记符”而已


    你一定没有看清我写的文章,你说的就是我说的,你不同意的我也补充了。

  162. jivi
    *.*.*.*
    链接

    jivi 2009-07-31 11:05:00

    @Jeffrey Zhao
    可能表达的有问题。
    其实你说的不算是骂人的话,但对于使用IE6的人来说。看起来总是有点难受的哈。

  163. 徐培华
    *.*.*.*
    链接

    徐培华 2009-09-21 00:33:00

    小菜鸟过来观望一下。
    不知道楼主所说的包同学有没有在。
    不过我最近在看他的那篇翻译IL的文章,
    觉得IL代码还是挺重要的,
    对于学.net的同学来说。

  164. 老赵
    admin
    链接

    老赵 2009-09-21 00:37:00

    @徐培华
    把原因说明白很重要,如果说只是“感觉是这样,但说不清楚”,其实往往是还没有想明白。

  165. 徐培华
    *.*.*.*
    链接

    徐培华 2009-09-21 12:01:00

    呵呵,
    楼主说的话挺抽象的。
    其实搞.net的。
    能去了解它底层怎样动作,对于理解程序比较好
    所以就想学下il语言。
    但是网上找了很多却没有一些比较详细的文章,
    找来找去就找了那位包同学的,
    要是老赵你能写一系列这样的文章,我会选择看你的,呵呵 。

  166. 老赵
    admin
    链接

    老赵 2009-09-21 12:13:00

    @徐培华
    我认为对于9成.NET技术人员来说,学IL只是在浪费时间,所以我只会写为什么我不推荐学IL。
    IL不是底层,它只是C#语言下方的抽象,在我看来对于写程序的帮助非常有限。
    我这几篇文章就是通过各种方式来证明“IL无用论”的,呵呵。

  167. 徐培华
    *.*.*.*
    链接

    徐培华 2009-09-21 19:07:00

    呵呵,我可不想加入你们的什么无用论,有用论的,

  168. 徐培华
    *.*.*.*
    链接

    徐培华 2009-09-21 19:08:00

    只要对自己有些用处的,都应该去看看。
    在网上这样争来争去也没什么意思

  169. 老赵
    admin
    链接

    老赵 2009-09-21 19:11:00

    @徐培华
    好吧,那么我说具体一点,“看看”自然没关系,但是不用特地去学。
    不过这总归是个人相关的,如果你觉得学IL投入产出比很高,自然应该学。

    至于争论有没有意思……前几天我正好写了篇文章,这里转来瞧瞧:
    http://www.cnblogs.com/JeffreyZhao/archive/2009/09/18/aspnet-php-benchmark-and-more.html

  170. willvvv[未注册用户]
    *.*.*.*
    链接

    willvvv[未注册用户] 2009-09-28 16:39:00

    Compile Once,Run Everywhere??
    好像是write Once,Run Everywhere
    还是有区别的,挑个小刺。。

  171. 老赵
    admin
    链接

    老赵 2009-09-28 16:46:00

    @willvvv
    不过Java和.NET都是Compile once的吧,就是编译后的dll/jar是通用的。

  172. bug yang
    *.*.*.*
    链接

    bug yang 2009-12-25 13:33:00

    呵呵,高手云集,不错

  173. minvt
    *.*.*.*
    链接

    minvt 2009-12-29 18:27:00

    赵哥大概的意思是说,是为了让人可以更认清什么才是IL,假如要学的话,自己究竟学的是啥,为了啥学,这样才真正是正道.而不是很功利性的,为了学而学,不学的的话,心有戚戚然,总是不放心,就像放着宝箱不去拿,或者总是为了NB或者心比天高乱学等等.要讲究理性,考究技术,追究需要.不是简单的该不该学的问题,是这样不?毕竟"底层"等等词汇太耀眼,越是俺这种菜鸟越容易失去理智,事倍功半.T_T

    看了文章终于理清楚了些问题,我们学校的老师经常忽悠人,很多观点竟然是荒谬的.终于知道"第一次运行慢一些,以后就快了"是咋回事儿了,终于搞清了偶的老师总是回避的一些问题--

    弱弱地问一下,一个.net程序在装有CLR的环境上第一次运行时,会生成机器代码是吧?那么这些机器码是存放在什么地方的呢?另外是程序运行到需要的地方才会产生机器码是吧?不需要的暂时不产生?这就是说的"多运行几次才会最好,vista的启动几次越用越流畅"也部分与之有关不?产生的机器代码会一直保存不会变动么?

    最后多问一句无关的,汇编代码也是通过特定的编译器转成机器码才能执行的吧?

  174. 老赵
    admin
    链接

    老赵 2009-12-29 19:05:00

    @minvt

    赵哥大概的意思是说,是为了让人可以更认清什么才是IL,假如要学的话,自己究竟学的是啥,为了啥学,这样才真正是正道.而不是很功利性的,为了学而学,不学的的话,心有戚戚然,总是不放心,就像放着宝箱不去拿,或者总是为了NB或者心比天高乱学等等.要讲究理性,考究技术,追究需要.不是简单的该不该学的问题,是这样不?毕竟"底层"等等词汇太耀眼,越是俺这种菜鸟越容易失去理智,事倍功半.T_T


    是的

    弱弱地问一下,一个.net程序在装有CLR的环境上第一次运行时,会生成机器代码是吧?那么这些机器码是存放在什么地方的呢?另外是程序运行到需要的地方才会产生机器码是吧?不需要的暂时不产生?这就是说的"多运行几次才会最好,vista的启动几次越用越流畅"也部分与之有关不?产生的机器代码会一直保存不会变动么?


    机器码放在内存里,多运行几次不会有效果,因为程序关了之后以前生成的机器码就释放了。

    最后多问一句无关的,汇编代码也是通过特定的编译器转成机器码才能执行的吧?


    这篇文章里已经写了。

  175. minvt
    *.*.*.*
    链接

    minvt 2009-12-30 11:04:00

    @Jeffrey Zhao
    谢谢赵哥
    原来CLR起到翻译解释作用 这样看来真的像是虚拟机呢
    那就是没有所谓".net"程序第一次用慢一些,以后用就快了"这种说法了吧?

  176. 老赵
    admin
    链接

    老赵 2009-12-30 11:05:00

    @minvt
    CLR本来就是虚拟机,不过是编译,不是翻译解释。
    .net程序不会第一次用慢,以后就快的。

  177. minvt
    *.*.*.*
    链接

    minvt 2009-12-30 11:44:00

    Jeffrey Zhao:
    @minvt
    这篇文章里已经写了。


    不好意思 因为不少东西第一次深入理解 大脑没处理过来 今天又看了一次

    貌似不同的cpu会有自己特定的指令集 不过这个指令集是以机器代码的形式存在 指令集的解释已经内置在cpu中了 而通常会说的汇编代码就是和机器代码一一对应的 便于理解的一种代码 是一种显示形式 用来控制指令集操作的 这样理解对不?

    就是说编译过程没有编译成汇编这一过程 而一些工具查看机器码 但是机器码用人脑解读有些不现实 所以用汇编来显示
    而有的用汇编来编辑的软件 就是在下面进行机器码的操作
    这样理解有问题没?

    这些是困扰俺N久的问题呢 貌似今天可以看到一点亮儿了 T_T

  178. minvt
    *.*.*.*
    链接

    minvt 2009-12-30 11:52:00

    貌似我176的描述很有问题 --

    之前看到有书称CLR中的编译器为一种JIT,读完赵哥的文章发现这种表述是很不对的了

  179. minvt
    *.*.*.*
    链接

    minvt 2009-12-30 11:53:00

    @Jeffrey Zhao

    .net程序不会第一次用慢,以后就快的。



    汗 当年偶的老师经常灌输这种观念 残念.....嫩牛满面

  180. 老赵
    admin
    链接

    老赵 2009-12-30 11:54:00

    minvt:
    貌似我176的描述很有问题 --

    之前看到有书称CLR中的编译器为一种JIT,读完赵哥的文章发现这种表述是很不对的了


    JIT没错啊,Just in Time Compiler

  181. minvt
    *.*.*.*
    链接

    minvt 2009-12-30 11:58:00

    建议赵哥配个clr .net framework等层次的.net结构详图

  182. minvt
    *.*.*.*
    链接

    minvt 2009-12-30 12:00:00

    @Jeffrey Zhao
    那个书中是把c#->IL的编译器成为JIT 这个不对吧 ?

  183. 老赵
    admin
    链接

    老赵 2009-12-30 12:03:00

    minvt:
    @Jeffrey Zhao
    那个书中是把c#->IL的编译器成为JIT 这个不对吧 ?


    这自然是错的。

  184. minvt
    *.*.*.*
    链接

    minvt 2009-12-30 14:28:00

    又把一些资料翻出来参考 结合赵哥的文章 好好又想了想 对于.net的理解有了新的认识 不敢说正确 但是应该比以前更接近真相了 感谢赵哥 感觉以前一年多的c#真差不多白学了

  185. apoclast
    114.94.204.*
    链接

    apoclast 2010-12-13 23:12:09

    这篇文章一直都围绕着机器的"汇编", 和.NET的MSIL 一直以来我都是这样理解的, .NET自己是一个操作系统, 也是一台理想状态的虚构计算机, 而MSIL在这台机器上的作用, 相当于传统计算机的作用. 在真实场景下, JIT是这两者的一座桥梁.

    一直在期望是否有一天能制造出".NET计算器", 没有仔细研究过, 不过我在猜想WP7是否就是这样的一个玩意. 另外, 老赵研究过Singularity吗? 它是否是一个.NET的真实实现

  186. apoclast
    114.94.204.*
    链接

    apoclast 2010-12-13 23:14:11

    前面一句话打错了"相当于传统计算机的作用" 应为 "相当于传统计算机中汇编的作用"

  187. woxf
    221.12.174.*
    链接

    woxf 2011-04-01 20:12:30

    关于IL我有个疑问,那就是CLR VIA C# 第三版里这样写,IL源代码经过汇编编译器编译成托管模块,那托管模块中的IL代码和上面的IL源代码又有什么区别呢? 求解答!

  188. 老赵
    admin
    链接

    老赵 2011-04-01 22:57:13

    @woxf

    看错了吧,什么叫做“汇编编译器”?IL源代码再编译一下就成本地代码了。

  189. woxf
    221.12.174.*
    链接

    woxf 2011-04-02 19:28:42

    难道我看的第三版是盗版?第三版第一章图1—1里,确实是有IL Source code files——》IL Assemblier——》Managed module(IL and metadata),我也纳闷,那个 IL Source code files到底是什么,这个IL和Managed module(IL and metadata)里的IL又有什么区别呢?

  190. 老赵
    admin
    链接

    老赵 2011-04-03 13:27:49

    @woxf

    手边没书,到时候帮你看看。

  191. woxf
    221.12.174.*
    链接

    woxf 2011-04-03 15:09:23

    先谢过。看了你写的IL系列,再对照CLR via C#,确实对IL清楚多了。

  192. Joey
    36.110.119.*
    链接

    Joey 2016-08-22 09:07:44

    姐夫你出来更新博客吧,怀念。

发表回复

登录 / 登录并记住我 ,登陆后便可删除或修改已发表的评论 (请注意保留评论内容)

昵称:(必填)

邮箱:(必填,仅用于Gavatar

主页:(可选)

评论内容(大于5个字符):

  1. Your Name yyyy-MM-dd HH:mm:ss

使用Live Messenger联系我