SHL moves every bit of a byte or word one place to the left, as many times as the count says. A 0 enters at bit 0, and the bit pushed out of the top goes into CF; after several steps CF holds the last bit that left. SAL (shift arithmetic left) is another name for exactly the same instruction.
CF <- b7 b6 b5 b4 b3 b2 b1 b0 <- 00000 0110 6SHL 1 0000 1100 12, CF = 0
Forms
The operand is a register or memory (SHL WORD PTR [BX], 1). On the 8086 the count is either the constant 1 or the CL register. SHL AL, 3 does not exist; write MOV CL, 3 then SHL AL, CL. If CL is 0, nothing is shifted and the flags are left alone.
Flags
CF gets the last bit shifted out. SF, ZF and PF describe the result. OF is defined only for a count of 1: it is set when the top bit changed, which means the value changed sign when read as signed (CF and the new top bit differ). For larger counts OF is undefined, and AF is always undefined.
Multiplying
Shifting left by n multiplies an unsigned or signed number by 2 to the power n, as long as the result fits. With single-bit shifts, CF=1 tells you an unsigned value overflowed. Shifts and adds combine into other factors, for example times 10:
SHL AX, 1 ; x * 2MOV BX, AXSHL AX, 1 ; x * 4SHL AX, 1 ; x * 8ADD AX, BX ; x * 8 + x * 2 = x * 10
Pitfalls and later CPUs
The 8086 uses all 8 bits of CL as the count, so a word shifted by 16 or more simply becomes 0. The 80186 and later CPUs keep only the low 5 bits of the count (0..31). The 186 also added an immediate count, as in SHL AX, 4, which MASM accepts only after .186. To shift a 32-bit value in DX:AX, use SHL AX, 1 then RCL DX, 1.
MOV AL, 3 ; 0000 0011CALL SHOWBINSHL AL, 1 ; 6CALL SHOWBINMOV CL, 5SHL AL, CL ; 6 * 32 = 192CALL SHOWBINCALL SHOWCFSHL AL, 1 ; 384 does not fit: CF = 1CALL SHOWBINCALL SHOWCFSHOWBIN PROC NEAR ; print AL as 8 binary digits and a spacePUSHF ; keep the caller's flagsPUSH AXPUSH BXPUSH CXPUSH DXMOV BL, ALMOV CX, 8NEXTBIT:SHL BL, 1 ; the top bit falls into CFMOV DL, "0"ADC DL, 0 ; "0" + CF = "0" or "1"MOV AH, 02hINT 21hLOOP NEXTBITMOV DL, " "MOV AH, 02hINT 21hPOP DXPOP CXPOP BXPOP AXPOPFRETSHOWBIN ENDPSHOWCF PROC NEAR ; print "CF=0" or "CF=1" and a spacePUSHFPUSH AXPUSH DXMOV DL, "0"ADC DL, 0 ; "0" + CF, before anything changes CFPUSH DXMOV AH, 09hMOV DX, OFFSET CFTXTINT 21hPOP DXMOV AH, 02hINT 21hMOV DL, " "MOV AH, 02hINT 21hPOP DXPOP AXPOPFRETSHOWCF ENDPCFTXT DB "CF=$"