操作碼 |
指令 |
說明 |
88 /r |
MOV r/m8,r8 |
將 r8 移到 r/m8 |
89 /r |
MOV r/m16,r16 |
將 r16 移到 r/m16 |
89 /r |
MOV r/m32,r32 |
將 r32 移到 r/m32 |
8A /r |
MOV r8,r/m8 |
將 r/m8 移到 r8 |
8B /r |
MOV r16,r/m16 |
將 r/m16 移到 r16 |
8B /r |
MOV r32,r/m32 |
將 r/m32 移到 r32 |
8C /r |
MOV r/m16,Sreg** |
將段暫存器移到 r/m16 |
8E /r |
MOV Sreg,r/m16** |
將 r/m16 移到段暫存器 |
A0 |
MOV AL,moffs8* |
將位於 (seg:offset) 的位元組移到 AL |
A1 |
MOV AX,moffs16* |
將位於 (seg:offset) 的字移到 AX |
A1 |
MOV EAX,moffs32* |
將位於 (seg:offset) 的雙字移到 EAX |
A2 |
MOV moffs8*,AL |
將 AL 移到 (seg:offset) |
A3 |
MOV moffs16*,AX |
將 AX 移到 (seg:offset) |
A3 |
MOV moffs32*,EAX |
將 EAX 移到 (seg:offset) |
B0+ rb |
MOV r8,imm8 |
將 imm8 移到 r8 |
B8+ rw |
MOV r16,imm16 |
將 imm16 移到 r16 |
B8+ rd |
MOV r32,imm32 |
將 imm32 移到 r32 |
C6 /0 |
MOV r/m8,imm8 |
將 imm8 移到 r/m8 |
C7 /0 |
MOV r/m16,imm16 |
將 imm16 移到 r/m16 |
C7 /0 |
MOV r/m32,imm32 |
將 imm32 移到 r/m32 |
備註:*moffs8、moffs16 及 moffs32 運算元指定相對於段基址的簡單偏移量,其中 8、16 及 32 指數據的大小。指令的地址大小屬性確定偏移量的大小,它可以是 16 位或 32 位。**在 32 位模式中,彙編器可能會在這條指令前面插入 16 位運算元大小字首(如需有關詳細資訊,請參閱下面的“說明”部分)。
將第二個運算元(源運算元)複製到第一個運算元(目標運算元)。源運算元可以是立即數、通用暫存器、段暫存器或記憶體位置;目標暫存器可以是通用暫存器、段暫存器或記憶體位置。兩個運算元的大小必須一樣,可以是位元組、字或雙字。
MOV 指令不能用於載入 CS 暫存器。試圖這樣做會導致操作碼無效異常 (#UD)。要載入 CS 暫存器,請使用遠 JMP、CALL 或 RET 指令。
如果目標運算元是段暫存器 (DS、ES、FS、GS 或 SS),則源運算元必須是有效的段選擇器。在保護模式中,將段選擇器移到段暫存器會導致將該段選擇器關聯的段描述符資訊自動載入到段暫存器的隱藏(陰影)部分。載入此資訊時,段選擇器與段描述符資訊生效(請參閱下面的“操作”演算法)。段描述符數據從指定的段選擇器對應的 GDT 或 LDT 項中獲取。
空的段選擇器(值為 0000 到 0003)可以載入到 DS、ES、FS 及 GS 暫存器,而不會導致保護異常。不過,隨後試圖引用段暫存器中載入空值的段時,都將導致一般保護性異常 (#GP),並且不發生任何記憶體引用。
使用 MOV 指令載入 SS 暫存器時,會禁止所有中斷,直到執行下一條指令之後。此操作可用於在發生中斷之前,將堆疊指針與下一條指令載入到 ESP (MOV ESP, 堆疊指針值)。LSS 指令是更有效的載入 SS 與 ESP 暫存器的方法。
在 32 位模式中操作並在段暫存器與通用暫存器之間移動數據時,“英特爾(R) 體系結構”32 位處理器不要求配合 16 位運算元大小字首(值為 66H 的位元組)使用此指令,但如果使用標準形式的指令(如 MOV DS, AX),大多數彙編器都會插入此字首。處理器將正確執行此指令,但通常要額外花費一個時鐘週期。對於大多數彙編器而言,通過使用指令形式 MOV DS, EAX 可以避免插入這個不必要的 66H 字首。處理器執行使用 32 位通用暫存器的此指令時,它會假定通用暫存器的 16 個最低有效位是目標運算元或源運算元。如果暫存器是目標運算元,則暫存器的兩個高位位元組中產生的值取決於具體實現的版本。對於奔騰(R) Pro 處理器,這兩個高位位元組用 0 填充;對於早期的 32 位“英特爾® 體系結構”處理器,這兩個高位位元組未定義。
DEST SRC;
在保護模式中,載入段暫存器會導致執行特殊的檢查與操作,具體如下所述。這些檢查的對象是段選擇器及其指向的段描述符。
IF SS is loaded;
THEN
IF segment selector is null
THEN #GP(0);
FI;
IF segment selector index is outside descriptor table limits
OR segment selector's RPL CPL
OR segment is not a writable data segment
OR DPL CPL
THEN #GP(selector);
FI;
IF segment not marked present
THEN #SS(selector);
ELSE
SS segment selector;
SS segment descriptor;
FI;
FI;
IF DS, ES, FS, or GS is loaded with non-null selector;
THEN
IF segment selector index is outside descriptor table limits
OR segment is not a data or readable code segment
OR ((segment is a data or nonconforming code segment)
AND (both RPL and CPL > DPL))
THEN #GP(selector);
IF segment not marked present
THEN #NP(selector);
ELSE
SegmentRegister segment selector;
SegmentRegister segment descriptor;
FI;
FI;
IF DS, ES, FS, or GS is loaded with a null selector;
THEN
SegmentRegister segment selector;
SegmentRegister segment descriptor;
FI;
無。
#GP(0) - 如果試圖將空的段選擇器載入到 SS 暫存器。如果目標運算元位於不可寫的段。如果記憶體運算元有效地址超出 CS、DS、ES、FS 或 GS 段限制。如果 DS、ES、FS 或 GS 暫存器包含空的段選擇器。
#GP(選擇器) - 如果段選擇器索引超出描述符表格限制。如果載入 SS 暫存器,並且段選擇器的 RPL 與段描述符的 DPL 不等於 CPL。如果載入 SS 暫存器,且指向的段不是可寫的數據段。如果載入 DS、ES、FS 或 GS 暫存器,且指向的段不是數據段或可讀程式碼段。如果載入 DS、ES、FS 或 GS 暫存器,且指向的段是數據段或非相容程式碼段,但 RPL 與 CPL 都大於 DPL。
#SS(0) - 如果記憶體運算元有效地址超出 SS 段限制。
#SS(選擇器) - 如果載入 SS 暫存器且指向的段標記為不存在。
#NP - 如果載入 DS、ES、FS 或 GS 暫存器且指向的段標記為不存在。
#PF(錯誤程式碼) - 如果發生頁錯誤。
#AC(0) - 如果啟用對齊檢查並在目前特權級別為 3 時進行未對齊的記憶體引用。
#UD - 如果試圖載入 CS 暫存器。
#GP - 如果記憶體運算元有效地址超出 CS、DS、ES、FS 或 GS 段限制。
#SS - 如果記憶體運算元有效地址超出 SS 段限制。
#UD - 如果試圖載入 CS 暫存器。
#GP(0) - 如果記憶體運算元有效地址超出 CS、DS、ES、FS 或 GS 段限制。
#SS(0) - 如果記憶體運算元有效地址超出 SS 段限制。
#PF(錯誤程式碼) - 如果發生頁錯誤。
#AC(0) - 如果在啟用對齊檢查的情況下進行未對齊的記憶體引用。
#UD - 如果試圖載入 CS 暫存器。