无法在 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.0
、call 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.
我今天开始学习 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.0
、call 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.