1. 程式人生 > >64位彙編指令集的變化等

64位彙編指令集的變化等

指令集變化

1.地址寬度和運算元寬度字首
     64位模式中,預設的地址寬度是64位,預設的運算元寬度是32位。地址寬度和運算元寬度字首允許32位和64位資料和地址在指令序列中混用。下表(1-7)顯示了在IA-32e模式下需要指令字首地址寬度。注意,在64位模式下不支援16位地址。在敬愛內容和傳統模式下,地址寬度函式的功能和在IA-32傳動架構中一樣。

下表(1-8)顯示了66H指令字首和REX.W字首的有效組合來指定IA-32e操作模式下的運算元寬度問題。
    在64位模式下, 預設的運算元寬度是32位,REX字首包括4位域來指定16個不同的值。REX字首的W位域指定為REX.W。REX.W=1時字首表明運算元位64為運算元。注意,軟體依然能使用運算元寬度66H字首來切換到16位操作寬度。然而如果同時用REX.W和66H字首,REX.W的優先權要高。
    在SSE/SSE2/SSE3 SIMD指令的情況下,66H, F2H和F3H字首作為操作碼擴充套件,並被認為是指令的一部分。在這些情況下,有效的REX.W字首和66H程式碼擴充套件字首之間沒有相互關係。

2.REX字首
    REX字首是64位模式下引入的新的指令字首位元組,他作以下工作:

  • 指定新的GPRs和SSE暫存器
  • 指定64位程式碼寬度
  • 指定擴充套件的控制暫存器(只給系統軟體使用)

    不是所有的指令都需要REX字首。這個字首只在指令引用擴充套件的暫存器或使用64位運算元的時候才有必要。如果該字首放在不需要的地方將會被忽略。
一個指令只能有一個REX字首。這個字首一旦使用,就必須直接放在操作碼位元組或兩位元組操作碼擴充套件字首之前。 其他位置的REX字首將被忽略。
    包含有REX字首的指令依然要遵循傳統的15位元組的指令寬度的限制。下圖描述了REX字首如何符合指令的位元組次序的。

3.控制和除錯暫存器的新編碼
     在64位模式下,有為控制機存器和除錯暫存器指定的附加的編碼。當ModRM暫存器的域編碼一個控制或除錯暫存器的時候,REX.R位被用來修改這些域。這些編碼允許處理器訪問CR8-CR15和DR8-DR15。
     在64位模式中附加了一個控制暫存器(CR8)。CR8成為任務優先順序暫存器(TPR)。在IA-32e技術的首次實現的時候,CR9-CR15和DR8-DR15都沒有實現,對它們的訪問將引起無效程式碼異常(#UD)。

4.新的指令
    下面的新指令在帶有64位擴充套件的64位模式下被引入。

  • SWAPGS 指令
  • SYSCALL and SYSRET 指令
  • CDQE 指令
  • CMPSQ 指令
  • CMPXCHG16B 指令
  • LODSQ 指令
  • MOVSQ 指令
  • MOVZX(64-bits) 指令
  • STOSQ 指令

5.堆疊指標
    在64位模式,堆疊指標為64位。堆疊大小不是像相容模式或傳統模式中那樣靠SS段描述符中的某位來控制,也不通過指令字首來指示。
    對隱式堆疊引用將忽略地址大小的指示。除遠分支以外,所有隱式引用RSP的指令在64位模式下預設為64位運算元。影響到的指令包括:PUSH, POP, PUSHF, POPF, ENTER, 和LEAVE。使用這些指令在64位模式下將不可能產生32位堆疊值的壓棧和退棧。如果使用66H運算元字首,將支援16位的壓棧和退棧。
    當暫存器RAX-RSP被用作運算元的時候,64位模式預設的操作尺寸無需REX字首作為這些指令的先導。如果式R8-R15作為運算元,則REX依然是需要的。這是因為字首在訪問新擴充套件暫存器中是需要的。

6.分支轉移
     64位擴充套件技術擴充2個分支機制來適應64位線性地址空間的分支。他們是:

  • 64位模式下近分支轉移被重新定義
  • 在64位模式和相容模式下,64位呼叫門描述符定義成遠呼叫

     64位模式下,所有近分支轉移(CALL, RET, JCC, JCXZ, JMP 和 LOOP)被強迫為64位。這些指令被更新為提供64位的RIP值而無需REX字首。下面的近轉移被有效的運算元寬度所控制:

  • 指令指標的寬度的截斷
  • 由於CALL或RET引起的退棧壓棧或退棧的大小
  • 由於CALL或RET而引起的堆疊指標增加或減少的大小
  • 間接轉移運算元大小

    在64位模式下,以上的所有操作都被強制為64位而不管運算元字首(運算元大小的字首被忽略)。然而相對轉移的位移區域依然受到32位的限制;近轉移的地址大小沒有被強制為64位。
    地址大小影響到JCXZ和LOOP中RCX的大小;他們也影響到記憶體間接轉移的地址計算。這樣的地址預設是64位,但是他們可以通過地址寬度字首轉換到32位寬度。
    軟體會用遠轉移來改變優先順序。傳統IA-32結構提供呼叫門機制來允許軟體去從一個優先順序轉到另一個優先順序,儘管呼叫門也可以不改變優先順序而只是做轉移。當呼叫門使用的時候,直接或間接的選擇器指標會指向一個門描述符(指令重的便宜被忽略)目的程式碼段的偏移可以從呼叫門描述符中獲得。IA-32e模式重新定義了32位呼叫門描述符的型別值,使其成為64位呼叫門描述符,並擴充套件64位描述符使其能夠容納64位的偏移。64位模式呼叫門描述符允許遠轉移訪問有效的線性地址空間的任何地方。這些呼叫門也控制程式碼段選擇器(CS),允許轉換到特權級和預設尺寸並作為門轉換的結果。
    因為通常情況下是指定32位的,唯一在64位模式下指定完全64位絕對RIP的是間接分支轉移,由於這個原因,直接遠分支轉移被從64位模式的指令集中刪除了。
    IA-32e模式擴充了SYSENTER和SYSEXIT指令的語義,以便他們操作在64位儲存空間。IA-32e也引入了兩個新的指令:SYSCALL和SYSRET,他們只在64位模式有效。

四、儲存組織

1.64位模式下的地址計算
    在64位模式(如果沒有地址大小的轉變),有效地址計算的大小是64位的。一個有效地址計算使用一個64位的基和索引暫存器以及符號擴充套件變換成64位。
    對於64位模式下平面地址空間,線性地址等同於有效地址。在使用FS和GS段的非0為基的事務中,這個規則不被使用。在64位模式下,有效地址成分被加進來,並且有效地址在加64位基地址之前被縮短。地址對映模式在64位模式時,基地址從不會被縮短。
    在IA-32e模式下,指令指標被擴充套件到64位來支援64位程式碼偏移。64位指令指標在呼叫中將值賦給RIP。下表描述了RIP、EIP和IP之間的不同。

    通常,替換和直接在64位模式下不被擴充套件到64位。他們在有效地址計算中依然被限制在32位和符號擴充套件。然而,在64位模式提供了MOV指令的64位替換和直接形式的支援。
    所有的在IA-32e模式下的16位和32位地址計算用0擴充套件來形成64位地址。地址計算搜現是縮短到當前模式的有效地址寬度,就像地址寬度字首的指定那樣。其結果是用0擴充套件得到完全的64位地址寬度。因為這個,16位和32位應用程式執行在相容模式只能存取64位模式有效地址的低4GB。同樣,在64位模式產生一個32位地址只能訪問64位模式有效地址的低4GB。

2.規範的定址
    一個規範形式的地址有地址位63直到更有效的實現位,巨集結構設定其為全1或全0。
    IA-32e模式定義一個64位的線性地址,但實現的時候支援的位數要少些。第一個具有64位擴充套件技術的IA-32e結構的處理器將支援48位線性地址。這意味著規範的地址必須將位63到位48全填0或全填1,填0還是填1要看位47是0還是1。
    儘管實現並不用先行地址的全部64位,他們需要檢查位63知道更有效的實現位來看是否地址是規範形式。如果一個線性儲存引用不是規範形式,該實現將會產生一個異常。在很多情況下,會產生一個一般保護異常(#GP)。然而,在顯示或隱式對戰應用的情況下,會產生一個堆疊錯(#SS)。隱式堆疊引用指令包括PUSH/POP指令和使用RSP/RBP暫存器來作為預設堆疊段暫存器的指令。在這些情況下,一個規範錯誤式#SF,如果一個指令使用RSP/RBP作為基暫存器並且有段超越給出一個非SS段,將引起一個一般保護錯誤(#GP)的規範錯誤。隱式堆疊引用包括所有PUSH/POP型別指令和任何使用RSP或RBP作為一個基暫存器。規範地址形式的檢查將在特權檢查之後頁面和邊界檢查之前完成。