C# 中间代码与内联汇编

中间代码(IL)是源程序的一种内部表示 举个例子C语言编译一个程序 那么C语言编

译器会把代码全部翻译为可以被机器识别的机器指令 同理C#编译器也是一样的 不

过它是被C#(CSC)编译为可以被CLR识别的指令 该指令称为中间代码。

C#可以内嵌汇编但需要通过Emit还有一种则通过Mono 但通常是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 压入参数0到计算堆栈

ldarg.1 压入参数1到计算堆栈

add 两数相加

ret 返回

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 源操作数传送到目标操作数

add 两数相加

eax 32位寄存器

dword ptr 四字节地址

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 压入__int32 0到计算堆栈

stloc.0 从计算堆栈弹出值到局部变量0

br.s 无条件转移

ldloc.0 压入局部变量0到计算堆栈

ldc.i4.1 压入__int32 1到计算堆栈

add 两数相加

ldc.i4.s 压入__int8但作为__int32到计算堆栈

blt.s 如果小于则转移

ret 返回返回值(如果存在)压入到调用方的计算堆栈(Win32 -> eax)

ASM While:

void main(int argc, char* argv[])
{
        __int32 i;
	_asm
	{
		mov         dword ptr [i],0
_loop_beige:
		cmp         dword ptr [i],64h
		jge         _loop_end
		mov         eax,dword ptr [i]
		add         eax,1
		mov         dword ptr [i],eax
		jmp         _loop_beige
_loop_end:
	}
}

jge 大于等于时转移

jmp 无条件转移

两者的代码并不是很难理解 不过你要它写程序会异常痛苦 不过IL是一个例外

它很强大 绕过编译器检查获取隐藏对象中的成员IL会很轻松AOP在C#中则是

利用Emit实现的有的时候我们需要去优化代码 从中间代码是一个很好的办法。

只是乎所有指令语言都有个毛病 做一个小小的循环会涉及到大量指令会让人

感到厌烦不过中间代码相对汇编的话是好太多了。看看上面两种不同的汇编

你是不是还是感到MDIL要轻松的多至少我如此的认为。

时间: 2024-11-26 13:37:59

C# 中间代码与内联汇编的相关文章

Linux C中内联汇编的语法格式及使用方法(Inline Assembly in Linux C)

在阅读Linux内核源码或对代码做性能优化时,经常会有在C语言中嵌入一段汇编代码的需求,这种嵌入汇编在CS术语上叫做inline assembly.本文的笔记试图说明Inline Assembly的基本语法规则和用法(建议英文阅读能力较强的同学直接阅读本文参考资料中推荐的技术文章 ^_^). 注意:由于gcc采用AT&T风格的汇编语法(与Intel Syntax相对应,二者的区别参见这里),因此,本文涉及到的汇编代码均以AT&T Syntax为准. 1. 基本语法规则 内联汇编(或称嵌入汇

linux平台学x86汇编(十八):内联汇编

[版权声明:尊重原创,转载请保留出处:blog.csdn.net/shallnet,文章仅供学习交流,请勿用于商业用途] 使用汇编语言笔编程最常见的方式是在高级语言(C和C++)程序内编写汇编函数,这种吧汇编语言直接写到C和C++语言程序内的技术称为内联汇编. GNU的C编译器使用asm关键字指出使用汇编语言编写的源代码段落.asm段的基本格式如下: asm("as code"): 括号中的汇编指令必须在括号,指令超过一条的话必须使用新的行分隔汇编语言代码每一行,因为编译器逐字地取得a

64位内联汇编

#define  Base_Pople 0x9cd654int Call_DaZuo=0x0044e000; //打坐 void DaZuo() { _asm { mov ecx,[Base_Pople] mov ecx,[ecx] mov ecx,[ecx+0x70] mov ecx,[ecx+0x1ec] mov ecx,[ecx+0x8] mov ecx,[ecx+0x200] call Call_DaZuo } } 内联汇编中不能直接用常量

C语言中递归什么时候可以省略return引发的思考:通过内联汇编解读C语言函数return的本质

事情的经过是这样的,博主在用C写一个简单的业务时使用递归,由于粗心而忘了写return.结果发现返回的结果依然是正确的.经过半小时的反汇编调试,证明了我的猜想,现在在博客里分享.也是对C语言编译原理的一次加深理解. 引子: 首先我想以一道题目引例,比较能体现出问题. 例1: #include <stdio.h> /** 函数功能:用递归实现位运算加法 */ int Add_Recursion(int a,int b) { int carry_num = 0, add_num = 0; if (

内联汇编

原文链接:http://www.orlion.ga/776/ 用C写的程序效率可能不如汇编,而且有些平台相关的指令必须手写,例如x86是端口I/O,而c语言就没有这个概念,所以in/out指令必须用汇编来写. gcc提供了一种扩展写法可以在C代码中试用内联汇编,最简单的格式是__asm__("assembly  code"); , 例如__asm__("nop");,nop这条指令让CPU空转一个周期,如果需要执行多条指令则用\n\t将各条指令隔开,例如: __as

最牛X的GCC 内联汇编

导读 正如大家知道的,在C语言中插入汇编语言,其是Linux中使用的基本汇编程序语法.本文将讲解 GCC 提供的内联汇编特性的用途和用法.对于阅读这篇文章,这里只有两个前提要求,很明显,就是 x86 汇编语言和 C 语言的基本认识. 1. 简介 1.1 版权许可 Copyright (C) 2003 Sandeep S. 本文档自由共享:你可以重新发布它,并且/或者在遵循自由软件基金会发布的 GNU 通用公共许可证下修改它:也可以是该许可证的版本 2 或者(按照你的需求)更晚的版本. 发布这篇文

操作系统学习之GCC内联汇编

GCC内联汇编(INLINE ASSEMBLY) 什么是内联汇编(Inline assembly)? 1.这是GCC对C语言的扩张,就是在C代码里面去写汇编代码 2.可以直接在C的语句中插入汇编指令 有何用处? 1.C语言不足以完成所有CPU的指令, 特别是有一些特权指令,比如加载gdt表(Global Descriptor Table 全局描述符表),从而使用汇编代码来完成 2.用汇编在C语言中手动优化,特别是在操作系统当中,使用汇编对操作系统的掌控更为精准,更加准确. 如何工作? 1.用给定

32位汇编第七讲,混合编程,内联汇编

32位汇编第七讲,混合编程 博客园IBinary原创 QQ:2510908331  博客连接:http://www.cnblogs.com/iBinary/ 转载请注明出处,谢谢 混合编程的概念,有时候我们会想,C语言可不可以调用汇编的函数,或者反过来调用 或者说C语言里面内部直接内联汇编去编写. 可以实现,静看怎么实现 一丶C语言调用汇编语言的函数 1.创建工程和代码 ①创建VC++控制台程序 FILE(文件) - NEW (新建) 然后我们打开源文件,一级一级展开,找到我们的main函数 那

Android漫游记(5)---ARM GCC 内联汇编烹饪书(附实例分析)

原文链接(点击打开链接) 关于本文档 GNU C编译器针对ARM RISC处理器,提供了内联汇编支持.利用这一非常酷炫的特性,我们可以用来优化软件代码中的关键部分,或者可以使用针对特定处理的汇编处理指令. 本文假定,你已经熟悉ARM汇编语言.本文不是一篇ARM汇编教程,也不是C语言教程. GCC汇编声明 让我们从一个简单的例子开始.下面的一条ARM汇编指令,你可以添加到C源码中. /* NOP example-空操作 */ asm("mov r0,r0"); 上面的指令,讲r0寄存器的