asmjit是一個開源項目,使用它可以將代碼即時的編譯成機器碼,也就是所謂的jit技術。
初次接觸這個項目,編寫了一個demo,學習它的使用方法。
現將編寫的demo以及調試jit生成的機器碼的過程總結出來,分享給大家
asmjit調用自定義方法的demo
代碼如下
#include "asmjit.h" // [Dependencies - C] #include <stdio.h> #include <stdlib.h> #include <string.h> using namespace AsmJit; #include <string> #include <iostream> using namespace std; int add(int value1, int value2) { cout << "arg1: " << value1 << " arg2: " << value2 << endl; return value1 + value2; } int main(int argc, char* argv[]) { X86Compiler c; //記錄日志,將編譯細節輸出到控制台 FileLogger Logger(stdout); c.setLogger(&Logger); //新建一個無參數、無返回值的方法 c.newFunc(kX86FuncConvDefault, FuncBuilder0<void>()); //定義一個臨時變量 GpVar result(c.newGpVar()); //給add方法傳入參數 c.push(Imm(9)); c.push(Imm(10)); //調用自定義的add方法 c.call((void*)add); //方法結束 c.endFunc(); typedef void (*myfun)(void); //生成方法的機器碼--真正的機器碼 myfun fun = asmjit_cast<myfun>(c.make()); //調用剛剛生成的方法 fun(); //獲取add方法的返回值 __asm{ mov value3, eax } cout << value3 << endl; //程序結束釋放生成的方法占用的內存 MemoryManager::getGlobal()->free(fun); return 0; }
VS調試
用VS調試生成的fun方法,首先通過調試菜單,打開反匯編窗口,如下圖
通過F11單步調試進生成的fun方法,看到如下的反匯編代碼
由於顯示一堆的??,無法知道生成的是什么指令,所以無法調試。
針對此問題在asmjit的google groups進行了提問
下面是比較有用的回答
根據Palo Marton的回答,這應該是VS的BUG。
windbg調試asmjit生成的方法
既然VS2012有BUG,那么就用windbg來調試吧
啟動后通過 lm 指令查看當前加載的模塊
上圖看到,asmjit的符號文件還未加載。
對main方法設置斷點 bp asmjit!main + 10,然后通過bl查看當前斷點
查看當前模塊及其符號文件
可以看到,這時asmjit的符號文件已經加載了。
通過g命令直接運行。
此時由於符號文件已經加載,windbg會根據符號文件加載對應的源文件
這時斷在了剛才下的斷點處,Alt+7打開反匯編窗口
通過p命令進行單步調試(相當於VS中的F10),t命令進行步入調試(相當於VS中的F11)。
執行到fun方法時,通過t命令進入方法內就可以看到生成的fun方法的反匯編代碼了
調試過程中使用到的windbg命令介紹
lm:List Loaded Modules,lm 命令顯示已經加載的模塊,輸出信息包括模塊的狀態和路徑。
bp:bp命令設置程序斷點。
bl:BreakPoint List ,bl命令列出當前存在的斷點信息列表。
p:Step,p命令執行一條指令或者一句源代碼,然后展示所有寄存器的結果,相當於VS調試中的F10。
g:Go,g命令開始執行當前進程或線程,相當於VS中的F5。
t:Trace,t命令相當於VS中的F11。
gu:Go Up,gu命令會使程序一直執行,知道當前的方法執行結束。相當於VS中的Shift+F11。