JIT概念就不说了

通过这个教程了解jit,https://solarianprogrammer.com/2018/01/12/writing-minimal-x86-64-jit-compiler-cpp-part-2/

代码在这里 https://github.com/sol-prog/x86-64-minimal-JIT-compiler-Cpp/blob/master/part_2/funcall.cpp

一个调用的汇编是这样的

func():
    push rbp
    mov rbp, rsp
    call test()
    pop rbp
    ret

call这个动作要通过代码来实现

func():
    push rbp
    mov rbp, rsp
    movabs rax, 0x0		# replace with the address of the called function
    call rax
    pop rbp
    ret

抄到机器码

0:	55                   	push   rbp
1:	48 89 e5             	mov    rbp,rsp

4:	48 b8 00 00 00 00 00 	movabs rax,0x0
b:	00 00 00
e:	ff d0                	call   rax

10:	5d                   	pop    rbp
11:	c3                   	ret

注意48 b8 ff d0

封装成函数来保存入站出站

namespace AssemblyChunks {
     std::vector<uint8_t>function_prologue {
         0x55,               // push rbp
         0x48, 0x89, 0xe5,   // mov	rbp, rsp
     };
 
     std::vector<uint8_t>function_epilogue {
         0x5d,   // pop	rbp
         0xc3    // ret
     };
 }

最终运行时变成这样

    MemoryPages mp;

    // Push prologue
    mp.push(AssemblyChunks::function_prologue);

    // Push the call to the C++ function test (actually we push the address of the test function)
    mp.push(0x48); mp.push(0xb8); mp.push(test);    // movabs rax, <function_address>
    mp.push(0xff); mp.push(0xd0);                   // call rax

    // Push epilogue and print the generated code
    mp.push(AssemblyChunks::function_epilogue);
    mp.show_memory();

能调用内部,也就能调用写好的函数,更进一步,调用外部输入函数

以及通过下面这些链接学一下,争取抄一个

https://www.clarkok.com/blog/2016/06/13/%E4%BD%BF%E7%94%A8-Xbyak-%E8%BF%9B%E8%A1%8C-JIT/

https://github.com/clarkok/cyan/blob/master/lib/codegen_x64.cpp

https://www.clarkok.com/blog/2016/04/20/Cript%E4%B8%80%E9%97%A8%E8%84%9A%E6%9C%AC%E8%AF%AD%E8%A8%80/

https://github.com/taocpp/PEGTL/blob/66e982bc2baef027fa463e6d633b5a8bcaae9f00/examples/calculator.cc

拓展阅读

  • https://zhuanlan.zhihu.com/p/162111478
  • 有个llvm-clang-jit实现,非常变态 ppt 代码 论文