sal
Shift Arithmetic Left
Shifts bits left (Alias for SHL).
Details
Shifts the bits of the destination operand left by the count specified (immediate or ECX). Each shifted-out bit is moved into CF; vacated bits are filled with zeros. Sets OF if the sign bit changed after the shift, CF from the last shifted bit, ZF and SF based on the result, and PF is undefined. Available in 8/16/32/64-bit variants across all modes.
Pseudocode Operation
if (count > 0) {
temp_cf ← dest >> (operand_width - count)
dest ← (dest << count) & ((1 << operand_width) - 1)
CF ← temp_cf
ZF ← (dest == 0 ? 1 : 0)
SF ← (dest >> (operand_width - 1)) & 1
if (count == 1) { OF ← (SF != CF ? 1 : 0) }
else { OF ← undefined }
PF ← undefined
}
Example
Encoding
Operands
-
dest
Reg/Mem -
count
Immediate
Reference (Intel® SDM)
Instruction Forms
| Opcode | Instruction | Op/En | 64/32-bit Mode | CPUID | Description |
|---|---|---|---|---|---|
| D0 /4 | SAL r/m8, 1 | M1 | Valid Valid | Multiply r/m8 by 2, once. | |
| D2 /4 | SAL r/m8, CL | MC | Valid Valid | Multiply r/m8 by 2, CL times. | |
| C0 /4 ib | SAL r/m8, imm8 | MI | Valid Valid | Multiply r/m8 by 2, imm8 times. | |
| D1 /4 | SAL r/m16, 1 | M1 | Valid Valid | Multiply r/m16 by 2, once. | |
| D3 /4 | SAL r/m16, CL | MC | Valid Valid | Multiply r/m16 by 2, CL times. | |
| C1 /4 ib | SAL r/m16, imm8 | MI | Valid Valid | Multiply r/m16 by 2, imm8 times. | |
| D1 /4 | SAL r/m32, 1 | M1 | Valid Valid | Multiply r/m32 by 2, once. | |
| REX.W + D1 /4 | SAL r/m64, 1 | M1 | Valid N.E. | Multiply r/m64 by 2, once. | |
| D3 /4 | SAL r/m32, CL | MC | Valid Valid | Multiply r/m32 by 2, CL times. | |
| REX.W + D3 /4 | SAL r/m64, CL | MC | Valid N.E. | Multiply r/m64 by 2, CL times. | |
| C1 /4 ib | SAL r/m32, imm8 | MI | Valid Valid | Multiply r/m32 by 2, imm8 times. | |
| REX.W + C1 /4 ib | SAL r/m64, imm8 | MI | Valid N.E. | Multiply r/m64 by 2, imm8 times. | |
| D0 /7 | SAR r/m8, 1 | M1 | Valid Valid | Signed divide3 r/m8 by 2, once. | |
| D2 /7 | SAR r/m8, CL | MC | Valid Valid | Signed divide3 r/m8 by 2, CL times. | |
| C0 /7 ib | SAR r/m8, imm8 | MI | Valid Valid | Signed divide3 r/m8 by 2, imm8 times. | |
| D1 /7 | SAR r/m16,1 | M1 | Valid Valid | Signed divide3 r/m16 by 2, once. | |
| D3 /7 | SAR r/m16, CL | MC | Valid Valid | Signed divide3 r/m16 by 2, CL times. | |
| C1 /7 ib | SAR r/m16, imm8 | MI | Valid Valid | Signed divide3 r/m16 by 2, imm8 times. | |
| D1 /7 | SAR r/m32, 1 | M1 | Valid Valid | Signed divide3 r/m32 by 2, once. | |
| REX.W + D1 /7 | SAR r/m64, 1 | M1 | Valid N.E. | Signed divide3 r/m64 by 2, once. | |
| D3 /7 | SAR r/m32, CL | MC | Valid Valid | Signed divide3 r/m32 by 2, CL times. | |
| REX.W + D3 /7 | SAR r/m64, CL | MC | Valid N.E. | Signed divide3 r/m64 by 2, CL times. | |
| C1 /7 ib | SAR r/m32, imm8 | MI | Valid Valid | Signed divide3 r/m32 by 2, imm8 times. | |
| REX.W + C1 /7 ib | SAR r/m64, imm8 | MI | Valid N.E. | Signed divide3 r/m64 by 2, imm8 times | |
| D0 /4 | SHL r/m8, 1 | M1 | Valid Valid | Multiply r/m8 by 2, once. | |
| D2 /4 | SHL r/m8, CL | MC | Valid Valid | Multiply r/m8 by 2, CL times. | |
| C0 /4 ib | SHL r/m8, imm8 | MI | Valid Valid | Multiply r/m8 by 2, imm8 times. | |
| D1 /4 | SHL r/m16,1 | M1 | Valid Valid | Multiply r/m16 by 2, once. | |
| D3 /4 | SHL r/m16, CL | MC | Valid Valid | Multiply r/m16 by 2, CL times. | |
| C1 /4 ib | SHL r/m16, imm8 | MI | Valid Valid | Multiply r/m16 by 2, imm8 times. | |
| D1 /4 | SHL r/m32,1 | M1 | Valid Valid | Multiply r/m32 by 2, once. | |
| REX.W + D1 /4 | SHL r/m64,1 | M1 | Valid N.E. | Multiply r/m64 by 2, once. | |
| D3 /4 | SHL r/m32, CL | MC | Valid Valid | Multiply r/m32 by 2, CL times. | |
| REX.W + D3 /4 | SHL r/m64, CL | MC | Valid N.E. | Multiply r/m64 by 2, CL times. | |
| C1 /4 ib | SHL r/m32, imm8 | MI | Valid Valid | Multiply r/m32 by 2, imm8 times. | |
| REX.W + C1 /4 ib | SHL r/m64, imm8 | MI | Valid N.E. | Multiply r/m64 by 2, imm8 times. | |
| D0 /5 | SHR r/m8,1 | M1 | Valid Valid | Unsigned divide r/m8 by 2, once. | |
| D2 /5 | SHR r/m8, CL | MC | Valid Valid | Unsigned divide r/m8 by 2, CL times. | |
| C0 /5 ib | SHR r/m8, imm8 | MI | Valid Valid | Unsigned divide r/m8 by 2, imm8 times. | |
| D1 /5 | SHR r/m16, 1 | M1 | Valid Valid | Unsigned divide r/m16 by 2, once. SAL/SAR/SHL/SHR—Shift Vol. 2B 4-603 Opcode1 Instruction Op/ 64-Bit Compat/ Description En Mode Leg Mode | |
| D3 /5 | SHR r/m16, CL | MC | Valid Valid | Unsigned divide r/m16 by 2, CL times | |
| C1 /5 ib | SHR r/m16, imm8 | MI | Valid Valid | Unsigned divide r/m16 by 2, imm8 times. | |
| D1 /5 | SHR r/m32, 1 | M1 | Valid Valid | Unsigned divide r/m32 by 2, once. | |
| REX.W + D1 /5 | SHR r/m64, 1 | M1 | Valid N.E. | Unsigned divide r/m64 by 2, once. | |
| D3 /5 | SHR r/m32, CL | MC | Valid Valid | Unsigned divide r/m32 by 2, CL times. | |
| REX.W + D3 /5 | SHR r/m64, CL | MC | Valid N.E. | Unsigned divide r/m64 by 2, CL times. | |
| C1 /5 ib | SHR r/m32, imm8 | MI | Valid Valid | Unsigned divide r/m32 by 2, imm8 times. | |
| REX.W + C1 /5 ib | SHR r/m64, imm8 | MI | Valid N.E. | Unsigned divide r/m64 by 2, imm8 times. |
Description
Operation
IF OperandSize = 64 THEN countMASK := 3FH; ELSE countMASK := 1FH; FI tempCOUNT := (COUNT AND countMASK); origDEST := DEST; tempDEST := DEST; WHILE (tempCOUNT ≠ 0) DO IF instruction is SAL or SHL THEN CF := MSB(tempDEST); ELSE (* Instruction is SAR or SHR *) CF := LSB(tempDEST); FI; IF instruction is SAL or SHL THEN tempDEST := tempDEST ∗ 2; ELSE IF instruction is SAR THEN tempDEST := tempDEST / 2; (* Signed divide, rounding toward negative infinity *) ELSE (* Instruction is SHR *) tempDEST := tempDEST / 2 ; (* Unsigned divide *) FI; FI; tempCOUNT := tempCOUNT – 1; OD; (* Determine overflow for the various instructions *) IF (COUNT and countMASK) = 1 THEN IF instruction is SAL or SHL SAL/SAR/SHL/SHR—Shift Vol. 2B 4-605 THEN OF := MSB(tempDEST) XOR CF; ELSE IF instruction is SAR THEN OF := 0; ELSE (* Instruction is SHR *) OF := MSB(origDEST); FI; FI; ELSE IF (COUNT AND countMASK) = 0 THEN All flags unchanged; ELSE (* COUNT not 1 or 0 *) OF := undefined; FI; FI; DEST := tempDEST;
Flags Affected
The CF flag contains the value of the last bit shifted out of the destination operand; it is undefined for SHL and SHR instructions where the count is greater than or equal to the size (in bits) of the destination operand. The OF flag is affected only for 1-bit shifts (see “Description” above); otherwise, it is undefined. The SF, ZF, and PF flags are set according to the result. If the count is 0, the flags are not affected. For a non-zero count, the AF flag is undefined.