SAL/SAR/SHL/SHR - 移位

操作碼

指令

說明

D0 /4

SAL r/m8

r/m8 乘以 2 一次

D2 /4

SAL r/m8,CL

r/m8 乘以 2 CL 次

C0 /4 ib

SAL r/m8,imm8

r/m8 乘以 2 imm8

D1 /4

SAL r/m16

r/m16 乘以 2 一次

D3 /4

SAL r/m16,CL

r/m16 乘以 2 CL 次

C1 /4 ib

SAL r/m16,imm8

r/m16 乘以 2 imm8

D1 /4

SAL r/m32

r/m32 乘以 2 一次

D3 /4

SAL r/m32,CL

r/m32 乘以 2 CL 次

C1 /4 ib

SAL r/m32,imm8

r/m32 乘以 2 imm8

D0 /7

SAR r/m8

將有符號 r/m8 除以* 2 一次

D2 /7

SAR r/m8,CL

將有符號 r/m8 除以* 2 CL 次

C0 /7 ib

SAR r/m8,imm8

將有符號 r/m8 除以* 2 imm8

D1 /7

SAR r/m16

將有符號 r/m16 除以* 2 一次

D3 /7

SAR r/m16,CL

將有符號 r/m16 除以* 2 CL 次

C1 /7 ib

SAR r/m16,imm8

將有符號 r/m16 除以* 2 imm8

D1 /7

SAR r/m32

將有符號 r/m32 除以* 2 一次

D3 /7

SAR r/m32,CL

將有符號 r/m32 除以* 2 CL 次

C1 /7 ib

SAR r/m32,imm8

將有符號 r/m32 除以* 2 imm8

D0 /4

SHL r/m8

r/m8 乘以 2 一次

D2 /4

SHL r/m8,CL

r/m8 乘以 2 CL 次

C0 /4 ib

SHL r/m8,imm8

r/m8 乘以 2 imm8

D1 /4

SHL r/m16

r/m16 乘以 2 一次

D3 /4

SHL r/m16,CL

r/m16 乘以 2 CL 次

C1 /4 ib

SHL r/m16,imm8

r/m16 乘以 2 imm8

D1 /4

SHL r/m32

r/m32 乘以 2 一次

D3 /4

SHL r/m32,CL

r/m32 乘以 2 CL 次

C1 /4 ib

SHL r/m32,imm8

r/m32 乘以 2 imm8

D0 /5

SHR r/m8

將無符號 r/m8 除以* 2 一次

D2 /5

SHR r/m8,CL

將無符號 r/m8 除以* 2 CL 次

C0 /5 ib

SHR r/m8,imm8

將無符號 r/m8 除以* 2 imm8

D1 /5

SHR r/m16

將無符號 r/m16 除以* 2 一次

D3 /5

SHR r/m16,CL

將無符號 r/m16 除以* 2 CL 次

C1 /5 ib

SHR r/m16,imm8

將無符號 r/m16 除以* 2 imm8

D1 /5

SHR r/m32

將無符號 r/m32 除以* 2 一次

D3 /5

SHR r/m32,CL

將無符號 r/m32 除以* 2 CL 次

C1 /5 ib

SHR r/m32,imm8

將無符號 r/m32 除以* 2 imm8

註:*與 IDIV 形式的除法有所不同;它向負無窮大取整。

說明

按第二個運算元(計數運算元)指定的位數,將第一個運算元(目標運算元)中的位向左或向右移位。移出目標運算元邊界的位會首先移到 CF 標誌,然後再丟棄。移位操作結束時,CF 標誌包含最後從目標運算元移出的位。

目標運算元可以是暫存器或記憶體位置。計數運算元可以是立即數或暫存器 CL。計數通過設定掩碼變成 5 位,從而將計數範圍限制為 0 到 31。計數 1 提供特殊的操作碼編碼。

算術左移 (SAL) 與邏輯左移 (SHL) 指令執行相同的操作;它們將目標運算元中的位向左(朝向更高有效位的位置)移位。對於每個移位計數,目標運算元的最高有效位將移入 CF 標誌,最低有效位將被清除(請參閱“IA-32 英特爾(R) 體系結構軟件開發人員手冊”第 1 卷的“圖 6-6”)。

算術右移 (SAR) 與邏輯右移 (SHR) 指令將目標運算元的位向右(朝向更低有效位的位置)移位。對於每個移位計數,目標運算元的最低有效位將移入 CF 標誌,根據指令型別,最高有效位將設定為 1 或清除為 0。SHR 指令清除最高有效位(請參閱“IA-32 英特爾(R) 體系結構軟件開發人員手冊”第 1 卷的“圖 6-7”);根據目標運算元中原始值的符號(最高有效位),SAR 指令將設定或清除最高有效位。實際上,SAR 指令使用移位之前的值的符號來填充移位之後的值的空位(請參閱“IA-32 英特爾(R) 體系結構軟件開發人員手冊”第 1 卷的“圖 6-8”)。

SAR 與 SHR 指令可分別用於對目標運算元執行以 2 的冪為除數的有符號或無符號除法。例如,使用 SAR 指令將有符號整數右移 1 位,相當於將該值除以 2。

使用 SAR 指令執行除法操作產生的結果與 IDIV 指令的不同。IDIV 指令的商會向零取整,而 SAR 指令的“商”則會向負無窮大取整。此差異僅在操作負數時才會表現出來。例如,使用 IDIV 指令將 -9 除以 4 時,結果為 -2,餘數為 -1。如果使用 SAR 指令將 -9 右移兩位,則結果為 -3,“餘數”為 +3;不過,SAR 指令只儲存餘數的最高有效位(儲存在 CF 標誌中)。

只有 1 位移位會影響 OF 標誌。對於左移,如果結果的最高有效位與 CF 標誌相同(即原始運算元的最高兩位相同),則將 OF 標誌清除為 0;否則設定為 1。對於 SAR 指令,OF 標誌在所有的 1 位移位中都會被清除。對於 SHR 指令,OF 標誌設定為原始運算元的最高有效位。

英特爾(R) 體系結構相容性

8086 不給移位計數設定掩碼。不過,其它所有的“英特爾(R) 體系結構”處理器(從 Intel(R) 286 處理器起)都會通過掩碼處理,將移位計數限制成 5 位,這樣最大計數就是 31。在所有的操作模式(包括虛 8086 模式)中,都會執行這樣的掩碼處理,以縮短指令的最大執行時間。

操作

tempCOUNT (COUNT AND 1FH);
tempDEST DEST;
WHILE (tempCOUNT 0)
DO
IF instruction is SAL or SHL
THEN
CF MSB(DEST);
ELSE (* instruction is SAR or SHR *)
CF LSB(DEST);
FI;
IF instruction is SAL or SHL
THEN
DEST DEST * 2;
ELSE
IF instruction is SAR
THEN
DEST DEST / 2 (*Signed divide, rounding toward negative infinity*);
ELSE (* instruction is SHR *)
DEST DEST / 2 ; (* Unsigned divide *);
FI;
FI;
tempCOUNT tempCOUNT - 1;
OD;
(* Determine overflow for the various instructions *)
IF COUNT 1
THEN
IF instruction is SAL or SHL
THEN
OF MSB(DEST) XOR CF;
ELSE
IF instruction is SAR
THEN
OF 0;
ELSE (* instruction is SHR *)
OF MSB(tempDEST);
FI;
FI;
ELSE IF COUNT 0
THEN
All flags remain unchanged;
ELSE (* COUNT neither 1 or 0 *)
OF undefined;
FI;
FI;

影響的標誌

CF 標誌包含最後從目標運算元移出的位的值;對於計數大於或等於目標運算元大小(以位計)的 SHL 與 SHR 指令,它未定義。只有 1 位移位會影響 OF 標誌(請參閱上面的“說明”);否則它未定義。SF、ZF 及 PF 標誌根據結果設定。如果計數為 0,則這些標誌不受影響。對於非零計數,AF 標誌未定義。

保護模式異常

#GP(0) - 如果目標位於不可寫的段。如果記憶體運算元有效地址超出 CS、DS、ES、FS 或 GS 段限制。如果 DS、ES、FS 或 GS 暫存器包含空的段選擇器。

#SS(0) - 如果記憶體運算元有效地址超出 SS 段限制。

#PF(錯誤程式碼) - 如果發生頁錯誤。

#AC(0) - 如果啟用對齊檢查並在目前特權級別為 3 時進行未對齊的記憶體引用。

實地址模式異常

#GP - 如果記憶體運算元有效地址超出 CS、DS、ES、FS 或 GS 段限制。

#SS - 如果記憶體運算元有效地址超出 SS 段限制。

虛 8086 模式異常

#GP(0) - 如果記憶體運算元有效地址超出 CS、DS、ES、FS 或 GS 段限制。

#SS(0) - 如果記憶體運算元有效地址超出 SS 段限制。

#PF(錯誤程式碼) - 如果發生頁錯誤。

#AC(0) - 如果在啟用對齊檢查的情況下進行未對齊的記憶體引用。