我了解 JIT 编译的工作原理(在阅读了 this SO question 等资源后)。但是,我仍然想知道它是如何在运行时实际执行机器代码的?
我在操作系统或编译器优化方面没有深厚的背景,也没有直接对机器代码做过任何事情,但我开始探索它。我已经开始玩汇编,看看像 NASM 这样的东西如何获取你的汇编代码并将其编译为机器代码(可执行文件),然后你可以从命令行“调用”它,如 ./my-executable
.
但是 JIT 编译器实际上是如何在运行时做到这一点的呢?它是像将机器代码流式传输到 stdin 之类的,还是它是如何工作的?如果您可以提供一个示例或一些伪代码,说明某些程序集(或类似的东西,虽然不像 C 那样高级)可能看起来如何演示基本流程,那也太棒了。
最佳答案
你提到你玩过汇编,所以你知道它是如何工作的,很好。想象一下,您编写了分配缓冲区的代码(例如:在地址 0x75612d39 处)。然后您的代码将程序集操作保存到该缓冲区以从堆栈中弹出一个数字,程序集调用打印函数来打印该数字,然后程序集“返回”。然后将数字 3 压入堆栈,并调用/跳转到地址 0x75612d39。处理器将按照说明打印您的数字,然后再次返回您的代码,并继续。在组装级别,它实际上非常简单。
我不知道任何“真正的”汇编语言,但这里有一个由我知道的字节码拼凑而成的“样本”。这台机器有 2 个字节的指针,字符串 %s
位于地址 6a
,以及函数 printf
位于地址 1388
.
void myfunc(int a) {
printf("%s", a);
}
此函数的程序集如下所示:
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 处的函数。
关于compiler-construction - JIT 编译是如何在运行时实际执行机器码的?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27627234/