JIT编译如何在运行时真正执行机器代码? [英] How does JIT compilation actually execute the machine code at runtime?

查看:294
本文介绍了JIT编译如何在运行时真正执行机器代码?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我了解JIT编译的工作原理(在阅读了此SO问题)。但是,我仍然想知道它在运行时如何实际执行机器码。

I understand the gist of how JIT compilation works (after reading such resources as this SO question). However, I am still wondering how does it actually execute the machine code at runtime?

我没有深入的操作系统背景或编译器优化,并且没有直接使用机器代码,但是我开始探索它。我已经开始在汇编中玩了,看看像NASM这样的东西可以把你的汇编代码和编译到机器代码(可执行文件),然后你可以从命令行调用,如。 / my-executable

I don't have a deep background in operating systems or compiler optimizations, and haven't done anything with machine code directly, but am starting to explore it. I have started playing around in assembly, and see how something like NASM can take your assembly code and compile it to machine code (the executable), and then you can "invoke" it from the command line like ./my-executable.

但是JIT编译器在运行时如何做呢?它是像流机器代码到stdin或什么,或者它是如何工作的?如果你可以提供一个例子或一些伪代码如何一些程序集(或沿着那些线,而不是像C一样高的水平)可能看起来证明基本的流程,这将是惊人的。

But how is a JIT compiler actually doing that at runtime? Is it like streaming machine code into stdin or something, or how does it work? If you could provide an example or some pseudocode of how some assembly (or something along those lines, not as high level as C though) might look to demonstrate the basic flow, that would be amazing too.

推荐答案

你提到你在装配中玩耍,所以你有一些想法如何工作,好。假设您编写分配缓冲区的代码(例如:地址0x75612d39)。然后你的代码将汇编操作保存到该缓冲区,从堆栈中弹出一个数字,汇编程序调用一个打印函数打印该数字,然后汇编到返回。然后将数字3推入堆栈,并调用/跳转到地址0x75612d39。处理器将遵守打印数字的说明,然后再次返回到代码,并继续。

You mentioned that you played around with assembly so you have some idea how that works, good. Imagine that you write code that allocates a buffer (ex: at address 0x75612d39). Then your code saves the assembly ops to that buffer to pop a number from the stack, the assembly to call a print function to print that number, then the assembly to "return". Then you push the number 3 onto the stack, and call/jump to address 0x75612d39. The processor will obey the instructions to print your numbers, then return to your code again, and continue. At the assembly level it's actually pretty straightforward.

我不知道任何真正的汇编语言,但这里是一个从我知道的字节码拼凑在一起的样本。此机器有2个字节指针,字符串%s 位于 6a ,函数 printf 位于地址 1388

I don't know any "real" assembly languages, but here's a "sample" cobbled together from a bytecode I know. This machine has 2 byte pointers, the string %s is located at address 6a, and the function printf is located at address 1388.

void myfunc(int a) {
    printf("%s", a);
}

此函数的程序集如下所示:

The assembly for this function would look like this:

OP Params OpName     Description
13 82 6a  PushString 82 means string, 6a is the address of "%s"
                     So this function pushes a pointer to "%s" on the stack.
13 83 00  PushInt    83 means integer, 00 means the one on the top of the stack.
                     So this function gets the integer at the top of the stack,
                     And pushes it on the stack again
17 13 88 Call        1388 is printf, so this calls the printf function
03 02    Pop         This pops the two things we pushed back off the stack
02       Return      This returns to the calling code.

所以当你的JITTER读取 void myfunc(int a){printf (%s,a);} ,它为这个函数分配内存(例如:在地址0x75612d39),并将这些字节存储在那个内存中: 13 82 6a 13 83 00 17 13 88 03 02 02 。然后,要调用该函数,只需跳转/调用地址为0x75612d39的函数。

So when your JITTER reads in the void myfunc(int a) {printf("%s", a);}, it allocate memory for this function (ex: at address 0x75612d39), and store these bytes in that memory: 13 82 6a 13 83 00 17 13 88 03 02 02. Then, to call that function, it simply jumps/calls the function at address 0x75612d39.

这篇关于JIT编译如何在运行时真正执行机器代码?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆