I am trying to understand the difference between the way parameters passed by reference and value are treated at IL level.
Here are the two methods in C#
public static void TestRef(ref int x)
{
x++;
}
public static void Test(int x)
{
x++;
}
The IL for pass by value is below, I understand that it loads the arg, then the int constant 1 and adds it and stuffs it back on the stack.
IL_0000: nop
IL_0001: ldarg.0
IL_0002: ldc.i4.1
IL_0003: add
IL_0004: starg.s x
IL_0006: ret
The IL for the method which passes by reference:
IL_0000: nop
IL_0001: ldarg.0
IL_0002: ldarg.0
IL_0003: ldind.i4
IL_0004: ldc.i4.1
IL_0005: add
IL_0006: stind.i4
IL_0007: ret
I don't understand why the two ldarg.0 statements are there. I assume the IL_0002/3 are just loading the argument address and then the argument value for that address.
But then what about IL_0001? Is it something to do with the left hand side of x =x+1?
The address loaded at IL_0001: ldarg.0 will be consumed by the storing operation at IL_0006: stind.i4.
The msdn tells us about the stind.i4 opcode:
The stack transitional behavior, in sequential order, is:
An address is pushed onto the stack.
A value is pushed onto the stack.
The value and the address are popped from the stack; the value is stored at the address.
https://learn.microsoft.com/de-de/dotnet/api/system.reflection.emit.opcodes.stind_i4?view=netframework-4.8
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With