无法在 CIL 中调用 2 个函数

Not able to call 2 functions in CIL

我今天开始学习 CIL,并且一直在使用多个教程来获得基本的理解。

目前我有 2 个函数,其中 1 个函数将作为参数给出的整数加 10 并打印答案。第二个函数接受 2 个整数,将它们都加 5,然后将答案相乘。然后返回。

当只调用其中一个函数时,这两个函数都有效,但是当两个函数都被调用时,我得到以下错误:

Unhandled Exception: System.InvalidProgramException: Common Language Runtime detected an invalid program.

at Bewerkingen.Program.Main(String[] args)

我不知道如何让这两个函数在相互调用时起作用。这是我的代码:

.assembly extern mscorlib {} 
.assembly Bewerkingen {} 
.module Bewerkingen.exe

.class public Functions
extends [mscorlib]System.Object
{
 .method public specialname void .ctor()
 {
  ret
 }
 .method public void Add(int32)
 {
  ldarg.1
  ldc.i4 10
  add
  call void [mscorlib]System.Console::WriteLine(int32)
  ret
 }
 .method public int32 add5mul(int32,int32)
 {
  ldarg.1
  ldc.i4 5
  add
  ldarg.2
  ldc.i4 5
  add
  mul
  ret
 }
}

.class Bewerkingen.Program
extends [mscorlib]System.Object
{
 .method static void Main(string[] args)
 cil managed
 {
  .entrypoint
  newobj instance void Functions::.ctor()
  ldc.i4 3
  call instance void Functions::Add(int32)
  ldc.i4 5
  ldc.i4 3
  call instance int32 Functions::add5mul(int32,int32)
  call void [mscorlib]System.Console::WriteLine(int32)
  ret
 }
}

您的第一个函数调用消耗了调用非静态函数所需的对象引用。将 newobj 操作后的对象引用保存到局部变量并为每个函数调用加载该引用。

来自msdn:

Calls to an instance (or virtual) method must push that instance reference before any of the user-visible arguments. The instance reference must not be a null reference. The signature carried in the metadata does not contain an entry in the parameter list for the this pointer; instead, it uses a bit to indicate whether the method requires passing the this pointer. https://docs.microsoft.com/en-us/dotnet/api/system.reflection.emit.opcodes.call?view=netframework-4.8

您遇到了一个小问题,您的 .ctor 需要调用基础对象的构造函数(ldarg.0call instance void [System.Private.CoreLib]System.Object::.ctor()ref)。对于程序和函数

然而,主要问题是您尝试调用 add5mul...什么都没有。堆栈上没有 Functions 对象可以调用它。

// Push Functions instance onto stack
// Stack: [functions]
  newobj instance void Functions::.ctor()

// Push 3 onto stack
// Stack: [3, functions]
  ldc.i4 3

// Pop 3 and functions off the stack
// Stack: []
  call instance void Functions::Add(int32)

// Push 5 and 3 onto stack
// Stack: [3, 5]
  ldc.i4 5
  ldc.i4 3

// Pop 5, 3, and... nothing. We're missing the Functions instance to call it on.
  call instance int32 Functions::add5mul(int32,int32)

您可以通过在首次使用 Functions 实例之前复制它来解决此问题:

  newobj instance void Functions::.ctor()
  dup                                                     <-- Here
  ldc.i4 3
  call instance void Functions::Add(int32)
  ldc.i4 5
  ldc.i4 3
  call instance int32 Functions::add5mul(int32,int32)
  call void [mscorlib]System.Console::WriteLine(int32)
  ret

您还可以将该 Functions 实例存储在本地槽中:

.method static void Main(string[] args)
 cil managed
 {
  .locals init (
    [0] class Functions
  )
  .entrypoint
  newobj instance void Functions::.ctor()
  stloc.0
  ldloc.0
  ldc.i4 3
  call instance void Functions::Add(int32)
  ldloc.0
  ldc.i4 5
  ldc.i4 3
  call instance int32 Functions::add5mul(int32,int32)
  call void [mscorlib]System.Console::WriteLine(int32)
  ret
 }


SharpLab.io is a great resource for learning IL. Here's your code, translated to C# then decompiled into IL.