不同的CPU都能夠解釋的機器語言的體系稱為指令集架構(ISA,Instruction Set Architecture),也可以稱為指令集(instruction set)。Intel將x86系列CPU之中的32位CPU指令集架構稱為IA-32,IA是“Intel Architecture”的簡稱,也可以稱為i386、x86-32。AMD等於Intell提出了x86系列的64位擴充套件,所以由AMD設計的x86系列的64位指令集架構稱為AMD64。後來Intel在自己的CPU中加入和AMD64幾乎相同的指令集,稱為Intel 64的指令集。AMD64和Intel 64可以統稱為x86-64。

x86-64的所有暫存器都是與機器字長(資料匯流排位寬)相同,即64位的,x86-64將x86的8個32位通用暫存器擴充套件為64位(eax、ebx、ecx、edx、eci、edi、ebp、esp),並且增加了8個新的64位暫存器(r8-r15),在命名方式上,也從”exx”變為”rxx”,但仍保留”exx”進行32位操作,下表描述了各暫存器的命名和作用。

描述

32位

64位

通用暫存器組

eax

rax

ecx

rcx

edx

rdx

ebx

rbx

esp

rsp

ebp

rbp

esi

rsi

edi

rdi

-

r8~r15

浮點暫存器組

st0~st7

st0~st7

XMM暫存器組

XMM0~XMM7

XMM0~XMM15

其中的%esp與%ebp有特殊用途,用來儲存指向程式棧中特定位置的指標。

另外還有eflags暫存器,通過位來表示特定的含義,如下圖所示。

在HotSpot VM中,表示暫存器的類都繼承自AbstractRegisterImpl類,這個類的定義如下:

原始碼位置:hotspot/src/share/vm/asm/register.hpp

class AbstractRegisterImpl;
typedef AbstractRegisterImpl* AbstractRegister; class AbstractRegisterImpl {
protected:
int value() const { return (int)(intx)this; }
}; 

AbstractRegisterImpl類的繼承體系如下圖所示。

另外還有個ConcreteRegisterImpl類也繼承了AbstractRegisterImpl,這個灰與C2編譯器的實現有關,這裡不做過多講解。

1、RegisterImpl類

RegisterImpl類用來表示通用暫存器,類的定義如下:

原始碼位置:cpu/x86/vm/register_x86.hpp

// 使用Register做為RegisterImpl的簡稱
class RegisterImpl;
typedef RegisterImpl* Register; class RegisterImpl: public AbstractRegisterImpl {
public:
enum {
number_of_registers = 16,
number_of_byte_registers = 16
};
// ...
};

對於64位來說,通用暫存器的位寬為64位,也可以將eax、ebx、ecx和edx的一部分當作8位暫存器來使用,所以可以儲存位元組的暫存器數量為4。

在HotSpot VM中定義暫存器,如下:

原始碼位置:hotspot/src/cpu/x86/vm/register_x86.hpp

CONSTANT_REGISTER_DECLARATION(Register, noreg, (-1)); // noreg_RegisterEnumValue = ((-1))
CONSTANT_REGISTER_DECLARATION(Register, rax, (0)); // rax_RegisterEnumValue = ((0))
CONSTANT_REGISTER_DECLARATION(Register, rcx, (1)); // rcx_RegisterEnumValue = ((1))
CONSTANT_REGISTER_DECLARATION(Register, rdx, (2)); // rdx_RegisterEnumValue = ((2))
CONSTANT_REGISTER_DECLARATION(Register, rbx, (3)); // rbx_RegisterEnumValue = ((3))
CONSTANT_REGISTER_DECLARATION(Register, rsp, (4)); // rsp_RegisterEnumValue = ((4))
CONSTANT_REGISTER_DECLARATION(Register, rbp, (5)); // rbp_RegisterEnumValue = ((5))
CONSTANT_REGISTER_DECLARATION(Register, rsi, (6)); // rsi_RegisterEnumValue = ((6))
CONSTANT_REGISTER_DECLARATION(Register, rdi, (7)); // rdi_RegisterEnumValue = ((7))
CONSTANT_REGISTER_DECLARATION(Register, r8, (8)); // r8_RegisterEnumValue = ((8))
CONSTANT_REGISTER_DECLARATION(Register, r9, (9)); // r9_RegisterEnumValue = ((9))
CONSTANT_REGISTER_DECLARATION(Register, r10, (10)); // r10_RegisterEnumValue = ((10))
CONSTANT_REGISTER_DECLARATION(Register, r11, (11)); // r11_RegisterEnumValue = ((11))
CONSTANT_REGISTER_DECLARATION(Register, r12, (12)); // r12_RegisterEnumValue = ((12))
CONSTANT_REGISTER_DECLARATION(Register, r13, (13)); // r13_RegisterEnumValue = ((13))
CONSTANT_REGISTER_DECLARATION(Register, r14, (14)); // r14_RegisterEnumValue = ((14))
CONSTANT_REGISTER_DECLARATION(Register, r15, (15)); // r15_RegisterEnumValue = ((15))

巨集CONSTANT_REGISTER_DECLARATION定義如下:

原始碼位置:hotspot/src/share/vm/asm/register.hpp

#define CONSTANT_REGISTER_DECLARATION(type, name, value)   \
extern const type name; \
enum { name##_##type##EnumValue = (value) }

經過巨集擴充套件後如下:

extern const Register  rax;
enum { rax_RegisterEnumValue = ((0)) }
extern const Register rcx;
enum { rcx_RegisterEnumValue = ((1)) }
extern const Register rdx;
enum { rdx_RegisterEnumValue = ((2)) }
extern const Register rbx;
enum { rbx_RegisterEnumValue = ((3)) }
extern const Register rsp;
enum { rsp_RegisterEnumValue = ((4)) }
extern const Register rbp;
enum { rbp_RegisterEnumValue = ((5)) }
extern const Register rsi;
enum { rsi_RegisterEnumValue = ((6)) }
extern const Register rsi;
enum { rdi_RegisterEnumValue = ((7)) }
extern const Register r8;
enum { r8_RegisterEnumValue = ((8)) }
extern const Register r9;
enum { r9_RegisterEnumValue = ((9)) }
extern const Register r10;
enum { r10_RegisterEnumValue = ((10)) }
extern const Register r11;
enum { r11_RegisterEnumValue = ((11)) }
extern const Register r12;
enum { r12_RegisterEnumValue = ((12)) }
extern const Register r13;
enum { r13_RegisterEnumValue = ((13)) }
extern const Register r14;
enum { r14_RegisterEnumValue = ((14)) }
extern const Register r15;
enum { r15_RegisterEnumValue = ((15)) }

如上的列舉類給暫存器指定了一個常量值。

在cpu/x86/vm/register_definitions_x86.cpp檔案中定義的暫存器如下:

const Register  noreg = ((Register)noreg_RegisterEnumValue)
const Register rax = ((Register)rax_RegisterEnumValue)
const Register rcx = ((Register)rcx_RegisterEnumValue)
const Register rdx = ((Register)rdx_RegisterEnumValue)
const Register rbx = ((Register)rbx_RegisterEnumValue)
const Register rsp = ((Register)rsp_RegisterEnumValue)
const Register rbp = ((Register)rbp_RegisterEnumValue)
const Register rsi = ((Register)rsi_RegisterEnumValue)
const Register rdi = ((Register)rdi_RegisterEnumValue)
const Register r8 = ((Register)r8_RegisterEnumValue)
const Register r9 = ((Register)r9_RegisterEnumValue)
const Register r10 = ((Register)r10_RegisterEnumValue)
const Register r11 = ((Register)r11_RegisterEnumValue)
const Register r12 = ((Register)r12_RegisterEnumValue)
const Register r13 = ((Register)r13_RegisterEnumValue)
const Register r14 = ((Register)r14_RegisterEnumValue)
const Register r15 = ((Register)r15_RegisterEnumValue)

當我們需要使用通用暫存器時,通過rax、rcx等變數引用就可以了。

2、FloatRegisterImpl

在HotSpot VM中,使用FloatRegisterImpl來表示浮點暫存器,此類的定義如下:

原始碼位置:hotspot/src/cpu/x86/vm/register_x86.hpp

// 使用FloatRegister做為簡稱
class FloatRegisterImpl;
typedef FloatRegisterImpl* FloatRegister; class FloatRegisterImpl: public AbstractRegisterImpl {
public:
enum {
number_of_registers = 8
};
// ...
}

浮點暫存器有8個,分別是st0~st7,這是8個80位暫存器。

這裡需要注意的是,還有一種暫存器MMX,MMX並非一種新的暫存器,而是借用了80位浮點暫存器的低64位,也就是說,使用MMX指令集,會影響浮點運算!

3、MMXRegisterImpl

MMX 為一種 SIMD 技術,即可通過一條指令執行多個數據運算,共有8個64位暫存器(借用了80位浮點暫存器的低64位),分別為mm0 – mm7,他與其他普通64位暫存器的區別在於通過它的指令進行運算,可以同時計算2個32位資料,或者4個16位資料等等,可以應用為影象處理過程中圖形 顏色的計算。

MMXRegisterImpl類的定義如下:

class MMXRegisterImpl;
typedef MMXRegisterImpl* MMXRegister;

MMX暫存器的定義如下:

CONSTANT_REGISTER_DECLARATION(MMXRegister, mnoreg , (-1));
CONSTANT_REGISTER_DECLARATION(MMXRegister, mmx0 , ( 0));
CONSTANT_REGISTER_DECLARATION(MMXRegister, mmx1 , ( 1));
CONSTANT_REGISTER_DECLARATION(MMXRegister, mmx2 , ( 2));
CONSTANT_REGISTER_DECLARATION(MMXRegister, mmx3 , ( 3));
CONSTANT_REGISTER_DECLARATION(MMXRegister, mmx4 , ( 4));
CONSTANT_REGISTER_DECLARATION(MMXRegister, mmx5 , ( 5));
CONSTANT_REGISTER_DECLARATION(MMXRegister, mmx6 , ( 6));
CONSTANT_REGISTER_DECLARATION(MMXRegister, mmx7 , ( 7));

巨集擴充套件後如下:

extern const MMXRegister  mnoreg;
enum { mnoreg_MMXRegisterEnumValue = ((-1)) }
extern const MMXRegister mmx0;
enum { mmx0_MMXRegisterEnumValue = (( 0)) }
extern const MMXRegister mmx1;
enum { mmx1_MMXRegisterEnumValue = (( 1)) }
extern const MMXRegister mmx2;
enum { mmx2_MMXRegisterEnumValue = (( 2)) }
extern const MMXRegister mmx3;
enum { mmx3_MMXRegisterEnumValue = (( 3)) }
extern const MMXRegister mmx4;
enum { mmx4_MMXRegisterEnumValue = (( 4)) }
extern const MMXRegister mmx5;
enum { mmx5_MMXRegisterEnumValue = (( 5)) }
extern const MMXRegister mmx6;
enum { mmx6_MMXRegisterEnumValue = (( 6)) }
extern const MMXRegister mmx7;
enum { mmx7_MMXRegisterEnumValue = (( 7)) }

MMX Pentium以及Pentium II之後的CPU中有從mm0到mm7共8個64位暫存器。但實際上MMX暫存器和浮點數暫存器是共用的,即無法同時使用浮點數暫存器和MMX暫存器。  

cpu/x86/vm/register_definitions_x86.cpp檔案中定義的暫存器變數如下:

const MMXRegister  mnoreg = ((MMXRegister)mnoreg_MMXRegisterEnumValue)
const MMXRegister mmx0 = ((MMXRegister)mmx0_MMXRegisterEnumValue)
const MMXRegister mmx1 = ((MMXRegister)mmx1_MMXRegisterEnumValue)
const MMXRegister mmx2 = ((MMXRegister)mmx2_MMXRegisterEnumValue)
const MMXRegister mmx3 = ((MMXRegister)mmx3_MMXRegisterEnumValue)
const MMXRegister mmx4 = ((MMXRegister)mmx4_MMXRegisterEnumValue)
const MMXRegister mmx5 = ((MMXRegister)mmx5_MMXRegisterEnumValue)
const MMXRegister mmx6 = ((MMXRegister)mmx6_MMXRegisterEnumValue)
const MMXRegister mmx7 = ((MMXRegister)mmx7_MMXRegisterEnumValue)

當我們需要使用MMX暫存器時,通過mmx0、mmx1等變數引用就可以了。

4、XMMRegisterImpl類

XMM暫存器是SSE指令用的暫存器。Pentium iii以及之後的CPU中提供了xmm0到xmm7共8個128位寬的XMM暫存器。另外還有個mxcsr暫存器,這個暫存器用來表示SSE指令的運算狀態的暫存器。在HotSpot VM中,通過XMMRegisterImpl類來表示暫存器。這個類的定義如下:

原始碼位置:hotspot/src/share/x86/cpu/vm/register_x86.hpp

// 使用XMMRegister暫存器做為簡稱
class XMMRegisterImpl;
typedef XMMRegisterImpl* XMMRegister; class XMMRegisterImpl: public AbstractRegisterImpl {
public:
enum {
number_of_registers = 16
};
...
}

XMM暫存器的定義如下:

CONSTANT_REGISTER_DECLARATION(XMMRegister, xnoreg , (-1));
CONSTANT_REGISTER_DECLARATION(XMMRegister, xmm0 , ( 0));
CONSTANT_REGISTER_DECLARATION(XMMRegister, xmm1 , ( 1));
CONSTANT_REGISTER_DECLARATION(XMMRegister, xmm2 , ( 2));
CONSTANT_REGISTER_DECLARATION(XMMRegister, xmm3 , ( 3));
CONSTANT_REGISTER_DECLARATION(XMMRegister, xmm4 , ( 4));
CONSTANT_REGISTER_DECLARATION(XMMRegister, xmm5 , ( 5));
CONSTANT_REGISTER_DECLARATION(XMMRegister, xmm6 , ( 6));
CONSTANT_REGISTER_DECLARATION(XMMRegister, xmm7 , ( 7));
CONSTANT_REGISTER_DECLARATION(XMMRegister, xmm8, (8));
CONSTANT_REGISTER_DECLARATION(XMMRegister, xmm9, (9));
CONSTANT_REGISTER_DECLARATION(XMMRegister, xmm10, (10));
CONSTANT_REGISTER_DECLARATION(XMMRegister, xmm11, (11));
CONSTANT_REGISTER_DECLARATION(XMMRegister, xmm12, (12));
CONSTANT_REGISTER_DECLARATION(XMMRegister, xmm13, (13));
CONSTANT_REGISTER_DECLARATION(XMMRegister, xmm14, (14));
CONSTANT_REGISTER_DECLARATION(XMMRegister, xmm15, (15));

經過巨集擴充套件後為:

extern const XMMRegister  xnoreg;
enum { xnoreg_XMMRegisterEnumValue = ((-1)) }
extern const XMMRegister xmm0;
enum { xmm0_XMMRegisterEnumValue = (( 0)) }
extern const XMMRegister xmm1;
enum { xmm1_XMMRegisterEnumValue = (( 1)) }
extern const XMMRegister xmm2;
enum { xmm2_XMMRegisterEnumValue = (( 2)) }
extern const XMMRegister xmm3;
enum { xmm3_XMMRegisterEnumValue = (( 3)) }
extern const XMMRegister xmm4;
enum { xmm4_XMMRegisterEnumValue = (( 4)) }
extern const XMMRegister xmm5;
enum { xmm5_XMMRegisterEnumValue = (( 5)) }
extern const XMMRegister xmm6;
enum { xmm6_XMMRegisterEnumValue = (( 6)) }
extern const XMMRegister xmm7;
enum { xmm7_XMMRegisterEnumValue = (( 7)) }
extern const XMMRegister xmm8;
enum { xmm8_XMMRegisterEnumValue = ((8)) }
extern const XMMRegister xmm9;
enum { xmm9_XMMRegisterEnumValue = ((9)) }
extern const XMMRegister xmm10;
enum { xmm10_XMMRegisterEnumValue = ((10)) }
extern const XMMRegister xmm11;
enum { xmm11_XMMRegisterEnumValue = ((11)) }
extern const XMMRegister xmm12;
enum { xmm12_XMMRegisterEnumValue = ((12)) }
extern const XMMRegister xmm13;
enum { xmm13_XMMRegisterEnumValue = ((13)) }
extern const XMMRegister xmm14;
enum { xmm14_XMMRegisterEnumValue = ((14)) }
extern const XMMRegister xmm15;
enum { xmm15_XMMRegisterEnumValue = ((15)) }

在cpu/x86/vm/register_definitions_x86.cpp檔案中定義的暫存器變數如下:

const XMMRegister  xnoreg = ((XMMRegister)xnoreg_XMMRegisterEnumValue)
const XMMRegister xmm0 = ((XMMRegister)xmm0_XMMRegisterEnumValue)
const XMMRegister xmm1 = ((XMMRegister)xmm1_XMMRegisterEnumValue)
const XMMRegister xmm2 = ((XMMRegister)xmm2_XMMRegisterEnumValue)
const XMMRegister xmm3 = ((XMMRegister)xmm3_XMMRegisterEnumValue)
const XMMRegister xmm4 = ((XMMRegister)xmm4_XMMRegisterEnumValue)
const XMMRegister xmm5 = ((XMMRegister)xmm5_XMMRegisterEnumValue)
const XMMRegister xmm6 = ((XMMRegister)xmm6_XMMRegisterEnumValue)
const XMMRegister xmm7 = ((XMMRegister)xmm7_XMMRegisterEnumValue)
const XMMRegister xmm8 = ((XMMRegister)xmm8_XMMRegisterEnumValue)
const XMMRegister xmm9 = ((XMMRegister)xmm9_XMMRegisterEnumValue)
const XMMRegister xmm10 = ((XMMRegister)xmm10_XMMRegisterEnumValue)
const XMMRegister xmm11 = ((XMMRegister)xmm11_XMMRegisterEnumValue)
const XMMRegister xmm12 = ((XMMRegister)xmm12_XMMRegisterEnumValue)
const XMMRegister xmm13 = ((XMMRegister)xmm13_XMMRegisterEnumValue)
const XMMRegister xmm14 = ((XMMRegister)xmm14_XMMRegisterEnumValue)
const XMMRegister xmm15 = ((XMMRegister)xmm15_XMMRegisterEnumValue)

當我們需要使用XMM暫存器時,直接通過xmm0、xmm1等變數引用就可以了。

推薦閱讀:

第1篇-關於JVM執行時,開篇說的簡單些

第2篇-JVM虛擬機器這樣來呼叫Java主類的main()方法

第3篇-CallStub新棧幀的建立

第4篇-JVM終於開始呼叫Java主類的main()方法啦

第5篇-呼叫Java方法後彈出棧幀及處理返回結果

第6篇-Java方法新棧幀的建立

第7篇-為Java方法建立棧幀

第8篇-dispatch_next()函式分派位元組碼

第9篇-位元組碼指令的定義

第10篇-初始化模板表

第11篇-認識Stub與StubQueue

第12篇-認識CodeletMark

第13篇-通過InterpreterCodelet儲存機器指令片段

第14篇-生成重要的例程

第15章-直譯器及直譯器生成器

第16章-虛擬機器中的彙編器

如果有問題可直接評論留言或加作者微信mazhimazh

關注公眾號,有HotSpot VM原始碼剖析系列文章!