关于基于反汇编的简单 C# 代码的手工编码 IL 的问题

2023-12-29

我刚刚开始研究一下 IL,我很好奇我从编译器输出中删除多余代码的尝试(如下所示)是否会产生任何意想不到的副作用。

关于结果的几个问题:

  1. 原文中nop操作的目的是什么?
  2. 原始方法末尾的 br.s 的目的是什么?
  3. 重写的版本有什么不合适的地方吗?

原始C#代码:

class Program {
    public static int Main() {
        return Add(1, 2);
    }
    public static int Add(int a, int b) {
        return a + b;
    }
}

编译为csc.exe并将其拆解为ildasm.exe(原来的):

  .method public hidebysig static int32  Main() cil managed
  {
    .entrypoint
    .maxstack  2
    .locals init (int32 V_0)
    IL_0000:  nop
    IL_0001:  ldc.i4.1
    IL_0002:  ldc.i4.2
    IL_0003:  call       int32 Program::Add(int32, int32)
    IL_0008:  stloc.0
    IL_0009:  br.s       IL_000b
    IL_000b:  ldloc.0
    IL_000c:  ret
  } 
  .method public hidebysig static int32  Add(int32 a,
                                             int32 b) cil managed
  {
    .maxstack  2
    .locals init (int32 V_0)
    IL_0000:  nop
    IL_0001:  ldarg.0
    IL_0002:  ldarg.1
    IL_0003:  add
    IL_0004:  stloc.0
    IL_0005:  br.s       IL_0007
    IL_0007:  ldloc.0
    IL_0008:  ret
  }

重写(产生相同的输出):

  .method public hidebysig static int32  Main() cil managed
  {
    .entrypoint
        .maxstack  2
    ldc.i4.1
    ldc.i4.2
    call int32 Program::Add(int32, int32)
    ret
  }

  .method public hidebysig static int32  Add(int32 a, int32 b) cil managed
  {
    .maxstack  2
      ldarg.0
      ldarg.1
    add
    ret
  }

您看到的所有“多余”代码都是特定于调试版本的(通常会针对发布版本进行优化),并允许您执行在发布版本中通常无法执行的操作。

调试构建代码允许在调试会话期间设置断点和更改/检查堆栈值方面具有最大的独立性。此外,IL 代码应尽可能模仿更高级别的代码,以便每个“原因”和“结果”都可以映射到更高级别的代码行。

现在具体回答您的问题:

原文中nop操作的目的是什么?

NOP 允许您在未“执行”的地方设置断点。例如方法、循环或 if 语句的左大括号。在这些不可执行的指令中,在左大括号处中断允许您在块开始之前修改/检查堆栈(尽管不可否认,您可以通过在块的第一行执行处中断而不是左大括号来轻松实现这一点,但它仍然允许您独立地在左大括号处断开)

原始方法末尾的 br.s 的目的是什么?

查看原始代码,您可能会发现“跳”到下一行而不是让代码自然“落”到下一行是荒谬的。但读作:

“在调试版本中,每当一个方法需要返回时,跳转到该方法的末尾,从堆栈中读取返回值,然后返回该值”

那么它对调试有什么好处呢?

如果代码中有多个 return 语句,则在从堆栈读取返回值之前,它们都会“跳转”到代码末尾。这允许您在一个地方(方法的右大括号)放置断点并在返回值实际返回到调用方法之前修改它。很有帮助不是吗?

重写的版本有什么不合适的地方吗?

您的代码中没有任何不正确的地方。事实上,如果您在发布模式下构建原始版本并检查生成的 CIL,您会发现它与您的大部分相同。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

关于基于反汇编的简单 C# 代码的手工编码 IL 的问题 的相关文章

随机推荐

  • scipy.io:无法写入 wavfile

    我在将 2d numpy 数组写入波形文件 音频 时遇到问题 根据文档我应该写一个 2d int16 numpy 数组 https docs scipy org doc scipy 0 18 1 reference generated sc
  • 使用 PHP 进行树形图可视化?

    除了 PHP 之外 几乎所有语言似乎都有 TreeMap 的示例 有人有一些基本代码的链接吗 http www neurofuzzy net 2006 04 28 treemap php source code http www neuro
  • 向 DOM Element 对象添加属性有什么问题?

    我一直在寻找一个直接的答案 我可以想到很多可能性 但我想知道真正的原因 jQuery 提供了 data 方法来将数据与 DOM Element 对象关联起来 是什么使得这有必要 直接向 DOM 元素对象添加属性 或方法 是否存在问题 它是什
  • 使用 CUDA 并行实现多个 SVD

    我是使用 GPU 并行编程的新手 因此如果问题广泛或模糊 我深表歉意 我知道 CULA 库中有一些并行 SVD 函数 但是如果我有大量相对较小的矩阵需要分解 应该采取什么策略 例如我有n有维数的矩阵d n很大并且d是小 如何并行化这个过程
  • Python pandas 无法读取带有一些奇怪编码和分割窗格的旧 Excel 文件

    我正在尝试将旧的 Excel 文件导入 pandas 该文件是由 CropSyst 软件使用旧格式 我不知道 生成的 并且默认情况下具有分割窗格 这是快照 一个解决方案可能是用excel打开文件并将其保存在xlsx中 这样pandas可以毫
  • 将 div 的高度设置为较大的值

    我的身高限制有问题 div div 在某些网络浏览器中 例如 Firefox 我有这样的 JavaScript 代码 MyDiv css height 20000000px 20 000 000 pixel height 但我看到heigh
  • python 脚本的管道输出

    我在跑 sample py url http blah com没有错误 但如果我运行 sample py url http blah com wc l或类似的我收到错误 UnicodeEncodeError ascii codec can
  • TypeScript 的 Angular 框架错误 - “没有将 exportAs 设置为 ngForm 的指令”

    我在使用 TypeScript 的 Angular2 forms 框架时不断收到此错误 没有directive将 exportAs 设置为 ngForm 这是我的代码 项目依赖 dependencies angular common 2 0
  • 将 grid.arrange 中的两个 ggplot 保存为 eps 文件格式

    我在 RStudio 工作 有两个 ggplot 称它们为plot1 和plot2 我想将它们排列在另一个之上并保存为 eps 格式 我已阅读以下有关该主题的帖子 使用 R 将图形导出到 eps 文件 https stackoverflow
  • React Native 动画 - 如何用动画将文本从中心移动到左侧?

    我需要用动画将文本从中心移动到左侧 我不能使用 screenWidth 2 和 marginLeft 来做到这一点 因为这样我需要了解文本长度和其他内容才能将其放在中心 也许有一种方法可以将 Interpolate 与 justifyCon
  • 使用 RMagick 从 https 读取 pdf 会出现未经授权的错误

    我正在尝试阅读 pdf 并将第一页保存为图像 此方法适用于http 但不适用于https require RMagick url http www ke tu darmstadt de publications reports tud ke
  • 如何构建 C# WinForms 模型-视图-呈现器(被动视图)程序?

    我正在设计一个具有以下基本思想的 GUI 类似于 Visual Studio 的基本外观和感觉 文件导航 控制选择器 用于选择编辑器组件中显示的内容 Editor 记录器 错误 警告 确认等 现在 我将使用 TreeView 进行文件导航
  • 从 Java bean 获取数据以显示在 JSP 页面上 [重复]

    这个问题在这里已经有答案了 我有一个论坛 用户可以在其中注册详细信息 并将其发送到 Servlet 然后发送到 Java bean 我遇到的问题是 当请求 Java bean 时 我无法将数据显示在另一个 JSP 页面上 所以CreateA
  • C 反转无符号整数中的位

    我正在使用按位运算符将无符号整数转换为二进制 当前执行整数 1 来检查位是 1 还是 0 并输出 然后右移 1 以除以 2 但是 这些位以错误的顺序返回 相反 所以我想在开始之前反转整数中的位顺序 有没有一种简单的方法可以做到这一点 例子
  • 如何在扩展弹出窗口中加载外部 JavaScript

    我正在尝试构建一个页面操作扩展 并且需要从弹出窗口加载外部 JavaScript 库 它需要来自外部域 以便发送正确的 cookie 但是我收到此错误消息 拒绝加载脚本 http api flattr com js 0 6 load js
  • UITabBarItem.title 与 UINavigationController.title

    我分配了一个带有标题 initWithTitle 的 UITabBarItem 并将其连接到 UINavigationController 我发现如果导航控制器的根视图控制器有自己的标题 那么该标题将永久替换选项卡栏项目上指定的标题 例如
  • 为什么 Hashmap.values().parallelStream() 不能并行运行,而将它们包装在 ArrayList 中可以工作?

    hashmap有两个键值对 它们不是由不同的线程并行处理的 import java util stream Stream import java util Map import java util HashMap class Ideone
  • Haskell 有变量吗?

    我经常听到有人声称 Haskell 没有变量 尤其 这个答案 https stackoverflow com questions 333185 what type of scope does haskell use 333219 33321
  • 将计算机添加到安全组 - Powershell GUI?

    本周我的任务是解决问题 如何使用包含各种计算机名称输入方法的功能正常的 Powershell GUI 界面将计算机添加到 OU 内的安全组 本地主机 手动输入主机名 从文件加载计算机列表 由于我在网上找不到类似的内容 所以我想我应该在这里发
  • 关于基于反汇编的简单 C# 代码的手工编码 IL 的问题

    我刚刚开始研究一下 IL 我很好奇我从编译器输出中删除多余代码的尝试 如下所示 是否会产生任何意想不到的副作用 关于结果的几个问题 原文中nop操作的目的是什么 原始方法末尾的 br s 的目的是什么 重写的版本有什么不合适的地方吗 原始C