- Java虛擬機字節碼:從入門到實戰
- 吳就業
- 1165字
- 2021-01-08 19:08:23
基于棧的指令集架構
在匯編語言中,除直接內存操作的指令外,其它指令的執行都依賴寄存器,如跳轉指令、循環指令、加減法指令等。匯編指令集是由硬件直接支持的,不同架構的CPU提供的匯編指令集也會不一樣[1]。
以一個經典的++i面試題為例,使用c語言編寫的實現如下。
int m = ++i;
反匯編后對應的32位x86 CPU的匯編指令如下。
inc dword ptr [ebp-44h] mov eax,dword prt [ebp-44h] mov dword ptr [ebp-4ch],eax
這三條指令的意思是,先將[ebp-44h]指向的內存塊的值加1,dword ptr相當于c語言中的類型聲明。接著將自增后[ebp-44h]指向的內存塊的值放入eax寄存器,最后將eax寄存器的值放到[ebp-4ch]指向的內存塊,也就是賦值給變量m。由于i和m是在棧上分配的內存,因此[ebp-44h]對應i的內存地址,[ebp-4ch]對應m的內存地址。
匯編指令不能直接操作將一塊內存的值賦值給另一塊內存,必須要通過寄存器。32位x86 CPU包括8個通用寄存器,EAX、EBX、ECX、EDX、ESP、EBP、ESI、EDI,其中EBP、ESP用做指針寄存器,存放堆棧內存儲單元的偏移量[2]。這些看不懂沒關系,這也不是本書的重點。
上述++i的例子使用java代碼實現如下。
public static void main(String[] args) { int a = 10; int result = ++a; System.out.println(result); }
使用javap命令輸出這段代碼的字節碼如下。
public static void main(java.lang.String[]); Code: 0: bipush 10 2: istore_1 3: iinc 1, 1 6: iload_1 7: istore_2 8: getstatic #2 // Field java/lang/System.out:Ljava/io/PrintStream; 11: iload_2 12: invokevirtual #3 // Method java/io/PrintStream.println:(I)V 15: return
字節碼指令前面的編號我們暫時理解為行號。在本例中,行號0到7的字節碼指令完成的工作是將變量a自增后的值賦值給result變量。下面將詳細分析這幾條指令的執行過程。
1. bipush指令是將立即數10放入到操作數棧頂,如圖1.10所示。

圖1.10 bipush指令執行過程
2. istore_1指令是將操作數棧頂的元素從操作數棧出彈出,并存放到局部變量表中索引為1的Slot,也就是賦值給變量a。如圖1.11所示。

圖1.11 istore指令執行過程
3. iinc這條字節碼指令比較特別,它可以直接操作局部變量表的變量,而不需要經過操作數棧。該指令是將局部變量表中索引為1的Slot所存儲的整數值自增1,也就是將局部變量a自增1。如圖1.12所示。

圖1.12 iinc指令執行過程
4. iload_1指令是將自增后的變量a放入操作數棧的棧頂,如圖1.13所示。

圖1.13 iload_1指令執行過程
5. 最后,istore_2指令是將當前操作數棧頂的元素從操作數棧彈出,并存放到局部變量表中索引為2的Slot,也就是給result變量賦值。如圖1.14所示。

圖1.14 istore_2指令執行過程
從++i的例子中,我們可以看出,字節碼是依賴操作數棧工作的。在虛擬機上執行的字節碼指令雖然最終也是編譯為機器碼執行,但編寫字節碼指令時并不需要我們考慮使用哪些寄存器的問題,這些交由JVM去實現。
使用匯編指令編寫代碼,我們需要考慮CPU的架構,有多少個寄存器可選,了解硬件,需要關心每條指令操作多少個字節,在使用寄存器之前需要考慮是否要備份寄存器的當前值,指令執行完之后是否需要恢復寄存器的值。而使用依賴棧工作的字節碼指令編寫代碼,我們只需要關心每條字節碼指令需要多少個參數,按順序將參數push到操作數棧頂。如果指令執行完有返回值,操作數棧頂就是返回值。
注釋:
[1] cpu架構是cpu廠商給屬于同一系列的cpu產品定的一個規范
[2] 王爽.《匯編語言》
- Apache ZooKeeper Essentials
- C# Programming Cookbook
- 區塊鏈架構與實現:Cosmos詳解
- 實戰低代碼
- C語言從入門到精通(第4版)
- MySQL數據庫管理與開發(慕課版)
- 實戰Java高并發程序設計(第3版)
- Python算法從菜鳥到達人
- BeagleBone Black Cookbook
- 低代碼平臺開發實踐:基于React
- NGINX Cookbook
- Procedural Content Generation for C++ Game Development
- Maker基地嘉年華:玩轉樂動魔盒學Scratch
- QlikView Unlocked
- Python編程快速上手2