当前位置: 首页 > 编程语言 > C#

Problemswithhand-codedILbasedondisassemblingsimpleC#codeShare

时间:2023-04-10 17:55:30 C#

Problemswithhand-codingILbasedondisassemblingsimpleC#code)从编译器的输出中删除冗余代码的任何意外副作用。关于结果的几个问题:原操作中nop操作的目的是什么?原始方法末尾的br.s的目的是什么?重写的版本在任何方面都不正确吗?原始C#代码:classProgram{publicstaticintMain(){returnAdd(1,2);}publicstaticintAdd(inta,intb){returna+b;}}用csc.exe编译,用ildasm编译。exe(原版)反汇编:.methodpublichidebysigstaticint32Main()cilmanaged{.entrypoint.maxstack2.localsinit(int32V_0)IL_0000:nopIL_0001:ldc.i4.1IL_0002:ldc.i4.2IL_0003:调用int32Program::Add(int32,int32)IL_0008:stloc.0IL_0009:br.sIL_000bIL_000b:ldloc.0IL_000c:ret}.methodpublichidebysigstaticint32添加(int32a,int32bd)cilmanage.maxstack2.localsinit(int32V_0)IL_0000:nopIL_0001:ldarg.0IL_0002:ldarg.1IL_0003:addIL_0004:stloc.0IL_0005:br.sIL_0007IL_0007:ldloc。0IL_0008:重写}重写(相同输出):.methodpublichidebysigstaticint32Main()cilmanaged{.entrypoint.maxstack2ldc.i4.1ldc.i4.2callint32Program::Add(int32,int32)ret}.methodpublichidebysigstaticint32添加(int32a,int32b)cilmanaged{.maxstack2ldarg.0ldarg.1addret}您看到的所有“冗余”代码都是特定于调试版本(通常针对发布版本进行了优化)并允许您执行通常是什么在版本调试中不可能构建代码,以便在调试会话期间设置断点和更改/检查堆栈值时允许最大的独立性。此外,IL代码应尽可能模仿更高级别的代码,以便每个“原因”和“结果”都可以映射到更高级别的代码行。现在具体针对你的问题:原操作中nop操作的目的是什么?NOP允许您在不执行它们的地方设置断点。例如,方法、循环或if语句的左括号。在这些不可执行的指令中,左大括号允许您在块开始之前修改/检查堆栈(尽管您可以通过在块的第一行而不是左大括号执行来非常容易地做到这一点,但它仍然允许您中断独立于开括号)原始方法末尾的br.s的目的是什么?查看原始代码,您可能会发现“跳”到下一行没有任何意义,而不是让代码自然地“下降”到下一行。但是读成:“在调试构建中,每当方法需要返回时,跳转到方法的末尾,从栈中读取返回值,返回值”那么它为调试提供了什么优势呢?如果代码中有多个return语句,在从栈中读取返回值之前,它们都会“跳转”到代码末尾。这允许您只有一个地方(方法的右括号)可以放置断点并在实际返回到调用方法之前修改返回值。很有帮助不是吗?重写的版本在任何方面都不正确吗?您的代码没有任何不当之处。事实上,如果您在发布模式下构建原型并检查生成的CIL,您会发现它与您的大致相同。免责声明:我无论如何都不是IL专家。nop操作的目的是什么?前段时间在programmers.stackexchange.com上有很多关于x86ASM的讨论,请参见此处:PurposeoftheNOPinstructionandthealignstatementinx86assembly。基本上是一样的。原始方法末尾的br.s的目的是什么?这只是方法结束的一个分支。如果您在此函数中有多个返回路径,那么查看它会更有意义。就目前而言,编译器已经包含它而不是优化它(可能编译器开关会优化它)。重写的版本在任何方面都不正确吗?不是我能看到的。您刚刚剥离了编译器的大部分工作,这对于这样一个简单的应用程序来说并不是真正必要的。如果要对此代码进行任何进一步的添加,则需要额外的IL才能完成其任务。以上就是《C#学习教程:基于反汇编简单C#代码手写IL》的全部内容。不代表立场,如涉及侵权,请点击右侧联系管理员删除。如需转载请注明出处: