.Net8的顶级技术JIT机器码生成

前言

机器码生成了,这部分代码才是.Net程序真正运行的部分。本篇来通过一个简单的例子简要看下机器码的生成。.

概括

1.前例
以Helloworld为例:

static void Main(){  Console.WriteLine("hello world");}

机器码生成的时候,会事先初始化一个函数头地址,也就是上面例子里面的Main函数最开始运行的那个地址。

此后JIT会对MSIL代码继续各种复杂的解析,以便于生成机器码。这里主要看下从LIR到MC的过程。

2.循环
LIR(一个封装BasicBlock的结构体)会循环被封装的BasicBlock(分割IL代码的结构体),然后赋值给GenTree(把分割的IL代码封装后赋给这棵树),对BasicBlock进行一个解析。最后会生成一个insGroup类型的emitIGlist庞大的结构体,它的实例叫ig。此后的操作都在这个结构体里面进行。ig有前LIR和后LIR,相当于一连串的链表形式。每一个ig里面包含了需要生成的机器码的个数。

以上面的helloworld为例,它把IL代码分为四段。每一段的代码LIR和机器码如下对应:

一段:总共有四个LIR和四个Machine Code

INS_push REG_RBPINS_push REG_RDIINS_sub REG_RSP, 0INS_lea一一对应的机器码是push        rbppush        rdisub         rsp,28hlea         rbp,[rsp+30h]

二段:两个L和M

INS_cmpINS_je对应:cmp  dword ptr [2878031C100h],0 je   00000287801399E1  //很明显这个地方是调试信息

三段:一个L和M

INS_call对应:call  00000287DEAD7068

四段:五个L和M

INS_nopINS_mov REG_RCX, 1INS_callINS_nopINS_nop对应:nopmov rcx,28780209C88hcall qword ptr [287807C53F8h] //这里就是调用Console.WriteLinenopnop

3.注意点

它这个M生成的最后是没有ret指令的,这个是为啥呢?目前还没研究出结果。后面再看看