IL has some opcodes for operating with arguments, such as Ldarg.0
, Ldarg.1
and so on.
I know that those arguments are pushed onto the stack before a call
opcode is executed, in some cases Ldarg.0
is used to get a reference to this
(for instance members)
My question is: where are those arguments stored when a call is initiated? Is a copy of the caller's stack accessible from the executed call?
Where can I find more information about that subject?
Update
I know that the virtual machine is abstract, and that JIT compiler takes care of those problems but let's imagine if the IL was interpreted, like it is on .NET Micro Framework
MSIL works with a specification of a virtual machine. The mental model for the arguments passed to a method is of them being present in an array. Where Ldarg picks an element from that array to access the method argument and pushes it onto the evaluation stack. Opcodes.Ldarg_0 is an abbreviated version of the more general Opcodes.Ldarg IL instruction, it saves two bytes by always picking element 0. Same idea for Opcodes.Ldarg_1 for the 2nd argument. Very common of course, Ldarg only gets "expensive" when the method has more than 4 arguments. Emphasis on the double quotes, this is not the kind of expense you ever worry about.
The actual storage of arguments at runtime is very different. It depends on the jitter you use, different architectures use different ways to pass arguments. In general, the first few arguments are passed through cpu registers, the rest through the cpu stack. Processors like x64 or ARM have a lot of registers so pass more of the arguments using a register than x86. Governed by the rules of the __clrcall calling convention for that architecture.
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