C # intermediate code and inline assembly,
Intermediate code (IL) is an internal representation of the source program. For example, if C language is used to compile a program, the C language compiler will translate all the code into machine commands that can be recognized by machines. Similarly, C # compiler is the same, but it is by C # (CSC) compiled into commands that can be recognized by CLR. This command is called intermediate code. C # It can be embedded in the Assembly, but it needs to be embedded through Emit. Another method is to use Mono, but usually Microsoft Emit. IL Add:
static void Main(string[] args) { DynamicMethod add = new DynamicMethod("add", typeof(int), new Type[] { typeof(int), typeof(int) }); ILGenerator il = add.GetILGenerator(); il.Emit(OpCodes.Ldarg_0); // ldarg.0 il.Emit(OpCodes.Ldarg_1); // ldarg.1 il.Emit(OpCodes.Add); // add il.Emit(OpCodes.Ret); // ret int num = (int)add.Invoke(add, new object[] { 1, 2 }); }
Ldarg.0 press the parameter 0 to the calculation stack ldarg.1 press the parameter 1 to the calculation stack add two numbers add ret return
ASM Add:
<span style="font-size:12px;">int Add(int x, int y){int ret;_asm{mov eax, dword ptr[x]add eax, dword ptr[y]mov dword ptr[ret], eax}return ret;}</span>
Mov source operand transmitted to target operand add two add eax 32-bit register dword ptr four-byte address
IL While:
static void Main(string[] args) { DynamicMethod _while = new DynamicMethod("while", typeof(int), null); ILGenerator il = _while.GetILGenerator(); il.DeclareLocal(typeof(int)); // int i Label IL_0004 = il.DefineLabel(); // IL_0004 Label IL_0008 = il.DefineLabel(); // IL_0008 il.Emit(OpCodes.Ldc_I4_0); // ldc.i4.0 il.Emit(OpCodes.Stloc_0); // stloc.0 il.Emit(OpCodes.Br_S, IL_0008); // br.s IL_0008 il.MarkLabel(IL_0004); il.Emit(OpCodes.Ldloc_0); // ldloc.0 il.Emit(OpCodes.Ldc_I4_1); // ldc.i4.1 il.Emit(OpCodes.Add); // add il.Emit(OpCodes.Stloc_0); // stloc.0 il.MarkLabel(IL_0008); il.Emit(OpCodes.Ldloc_0); // ldloc.0 il.Emit(OpCodes.Ldc_I4_S, 100); // ldc.i4.s 100 il.Emit(OpCodes.Blt_S, IL_0004); // blt.s IL_0004 il.Emit(OpCodes.Ldloc_0); // ldloc.0 il.Emit(OpCodes.Ret); // ret int num = (int)_while.Invoke(_while, null); }
Ldc. i4.0 press _ int32 0 to calculate the stack stloc.0 from the calculation stack pop-up value to the local variable 0br. s unconditionally transfers ldloc.0 to push the local variable 0 to the computing stack ldc. i4.1 press _ int32 1 to the computing Stack
Add two numbers to add ldc. i4.s press _ int8, but as _ int32 to the computing stack blt. if the value of s is smaller than the value of ret, the returned value (if any) is transferred to the computing stack of the caller (Win32-> eax)
ASM While:
void main(int argc, char* argv[]){ __int32 i;_asm{mov dword ptr [i],0 _loop_beige:cmp dword ptr [i],64hjge _loop_endmov eax,dword ptr [i] add eax,1 mov dword ptr [i],eax jmp _loop_beige _loop_end:}}
Transfer when jge is greater than or equal
Jmp unconditional transfer
The code of the two is not very difficult to understand, but it will be very painful for you to write the program, but IL is an exception. It is very powerful to bypass the compiler to check and obtain the member IL in the hidden object. It will be very easy for AOP in C. # It is implemented using Emit. Sometimes we need to optimize the code from the intermediate code. It's just that there is something wrong with all instruction languages. A small loop involves a large number of commands, which can be annoying. However, if the intermediate code is relatively compiled, it is much better. Check whether the two different compilations above make MDIL much easier. At least I think so.