35

I have learned how to work with 80x86 assembler, so in bit-wise shift operation, I faced a problem with SAL and SHL usage. I means the difference between lines of code as follow :

MOV X, 0AAH
SAL X, 4

MOV X, 0AAH
SHL X, 4

When we should use SHL and when use SAL? What is the difference of them?

ROMANIA_engineer
  • 54,432
  • 29
  • 203
  • 199
Hossein Mobasher
  • 4,382
  • 5
  • 46
  • 73
  • 3
    There is no official instruction named `sal` though some times this mnemonic is used for an undcumented encoding variant of the `shl` instruction. – fuz Dec 14 '21 at 11:45
  • 5
    The two names are purely for symmetry with `sar` and `shr` (which actually differ due to how the sign bit is used). – ecm Dec 14 '21 at 11:52
  • 2
    [SAL and SHL are simple aliases to the same opcode](https://www.felixcloutier.com/x86/sal:sar:shl:shr) – phuclv Dec 14 '21 at 13:10
  • 3
    Similarly there are the alternatives `je` and `jz` and several other branch instructions. They aren't opcodes: they are *mnemonics* which are assembled into the same opcode. – Weather Vane Dec 14 '21 at 15:08
  • 2
    @fuz: `sal` is fully official [in Intel manuals](https://www.felixcloutier.com/x86/sal:sar:shl:shr), listed just like `shl` on separate lines, just happening to share the same opcode. Separately from docs, GCC likes to emit `sal` for any left shift: https://godbolt.org/z/7qnYa8vzc. (Although GNU Binutils (including `objdump`) disassembles it as `shl`). There is zero mention anywhere of the `/6` *encoding*, though; calling that `sal` is the unofficial thing. – Peter Cordes Dec 15 '21 at 04:01
  • 1
    (@fuz: And see also my edit to Vitsoft's answer: Stephen Morse, architect of the ISA, explains it in his book in terms of having signed and unsigned shifts, and left shift just happening to be the same for both, unlike right.) – Peter Cordes Dec 15 '21 at 09:30

9 Answers9

44

According to this, they are the same:

The shift arithmetic left (SAL) and shift logical left (SHL) instructions perform the same operation; they shift the bits in the destination operand to the left (toward more significant bit locations). For each shift count, the most significant bit of the destination operand is shifted into the CF flag, and the least significant bit is cleared (see Figure 7-7 in the Intel®64 and IA-32 Architectures Software Developer'sManual, Volume 1).

Both were probably included just for completeness since there is a distinction for right-shifts.

Mysticial
  • 464,885
  • 45
  • 335
  • 332
  • 7
    SAL and SHLhave the same opcode, it's just a mnemonic synonym like `jne` vs. `jnz`. So there's no possible way the CPU can even know which one you wrote; they have to behave the same. – Peter Cordes Jan 02 '18 at 00:01
  • 1
    Fun Fact: There could be a difference in encoding. The (rotate- and ) shift-instructions are encoded with 0xc0/0xc1/0xd0/0xd1/0xd2/0xd3 and a Mod-Reg-R/M-field with the actual opcode encoded in the Reg-Field: 0–3 for rotate-instructions, 4 for `shl`, 5 for `shr`, 6 for `sal` and 7 for `sar`. Most assemblers encode `shl` and `sal` the same and with 4, but 6 is still possible, even with amd64. ^^ (http://sandpile.org/x86/opc_grp.htm) – sivizius Apr 27 '19 at 18:42
  • @sivizius: Related: [Is there any valid use for a sign-preserving left shift?](//stackoverflow.com/q/56440020) also mentions the existence of the ROL/ROR, RCL/RCR, SHL/SHR, and SAL/SAR opcodes that use the `/r` field (as an example of what it's *not* asking about). Plus [What did the 8086 (and 8088) do upon encountering an illegal instruction?](//retrocomputing.stackexchange.com/q/11327) explains that 8086 didn't have a #UD exception: every sequence decoded as *something*, so having `/6` alias `/4` originally was probably the only good option, since `#UD` wasn't possible. – Peter Cordes Jun 16 '19 at 18:25
  • @PeterCordes I did not know the reason, only that x86 is weird.^^ – sivizius Jun 16 '19 at 21:03
  • Update, there's now another Q&A just about having two names for the same shift opcode ([Why left shift instruction has two names in x86-64 ISA?](https://stackoverflow.com/q/70348306)) where the answer proposes the /4 /6 distinction as a reason for it. Or maybe just as a coincidence. – Peter Cordes Dec 14 '21 at 21:42
9

shl and sal are the same.They have same machine code.
shr and sar are NOT the same.They have almost same machine code.(but not)
Check this.

ARISTOS
  • 336
  • 3
  • 7
6

SHL and SAL are equivalent functionally, but not conceptually. Operation code D3 reserved by x86 architecture for shift/rotate instructions in format r/m32, CL had eight position distinguished by Reg/Opcode field in ModR/M byte:

D3 /0 ROL
D3 /1 ROR
D3 /2 RCL
D3 /3 RCR
D3 /4 SHL
D3 /5 SHR
D3 /6 SAL     # not officially documented
D3 /7 SAR

As both SAL and SHL work in identical way, official Intel documentation leaves the position
of D3 /6 SAL vacant but its encoding works. Some assemblers allow to select this encoding by an undocumented mnemonic SAL2.

SHL/SAL is not the only case of such redundancy. TEST reg, imm encoded by F7 /0 works identically with undocumented encoding F7 /1.

Stephen Morse, architect of 8086's ISA / machine code, wrote a book, the 8086 Primer, currently readable for free on his web site; pages 65, 66 describe shift/rotate machine code, but he doesn't mention the unused /6 encoding, instead saying both SHL and SAL are the same operation and use the D0 /4 opcode. (The book is aimed at programmers using 8086, not directly at analyzing the design decisions, so that's not a total surprise.)

8086 had no #UD illegal-instruction exception: everything decoded as something, and it was likely easiest to arrange for /6 to run the same as /4 so they can both be left shifts instead of making it a NOP. (High bit of the 3-bit /r field is set so its a shift, not rotate, low bit clear so it's left, not right. In that case the middle bit has no effect since we're shifting out of the high bit, not into it.)


Related:

Peter Cordes
  • 328,167
  • 45
  • 605
  • 847
vitsoft
  • 5,515
  • 1
  • 18
  • 31
  • 4
    I think having two names for one opcode is separate from having a redundant opcode. Stephen Morse's book just says they're the same operation so can share an opcode; I think it's just happenstance that there was an unused encoding that 8086 decodes the same as `/4` SHL/SAL. – Peter Cordes Dec 14 '21 at 21:34
4

There's no difference apart from Intel and AMD wanting to deprecate the duplicate SAL.

Alexey Frunze
  • 61,140
  • 12
  • 83
  • 180
3

I would also have a look at the table in the Intel 64 and IA-32 Architectures Software Developer's Manuals Volume 2 "SAL/SAR/SHL/SHR—Shift" which contains a table with:

D0 /4             SHL r/m8, 1
REX + D0 /4       SHL r/m8**, 1
D2 /4             SHL r/m8, CL
REX + D2 /4       SHL r/m8**, CL
C0 /4 ib          SHL r/m8, imm8
REX + C0 /4 ib    SHL r/m8**, imm8
D1 /4             SHL r/m16,1
D3 /4             SHL r/m16, CL
C1 /4 ib          SHL r/m16, imm8
D1 /4             SHL r/m32,1
REX.W + D1 /4     SHL r/m64,1
D3 /4             SHL r/m32, CL
REX.W + D3 /4     SHL r/m64, CL
C1 /4 ib          SHL r/m32, imm8
REX.W + C1 /4 ib  SHL r/m64, imm8

D0 /4             SAL r/m8, 1
REX + D0 /4       SAL r/m8**, 1
D2 /4             SAL r/m8, CL
REX + D2 /4       SAL r/m8**, CL
C0 /4 ib          SAL r/m8, imm8
REX + C0 /4 ib    SAL r/m8**, imm8
D1 /4             SAL r/m16, 1
D3 /4             SAL r/m16, CL
C1 /4 ib          SAL r/m16, imm8
D1 /4             SAL r/m32, 1
REX.W + D1 /4     SAL r/m64, 1
D3 /4             SAL r/m32, CL
REX.W + D3 /4     SAL r/m64, CL
C1 /4 ib          SAL r/m32, imm8
REX.W + C1 /4 ib  SAL r/m64, imm8

By comparing both parts, we see that each operand choice has the same encoding for both SHL and SAL, so they are identical.

Mystical's quote follows in the same section further confirming it.

Ciro Santilli OurBigBook.com
  • 347,512
  • 102
  • 1,199
  • 985
  • 1
    Related: [What did the 8086 (and 8088) do upon encountering an illegal instruction?](//retrocomputing.stackexchange.com/q/11327) is probably the `/6` encoding is an alias: 8086 didn't have `#UD`, and there was one shift-type `/r` value left over with ROL/ROR, RCL/RCR, SHL/SHR, and SAL/SAR, unless there are separate opcodes for SHL and SAL. But yes modern x86 only documents the `/4` encoding, despite some sources claiming that one of the mnemonics should be `/6`. – Peter Cordes Jun 16 '19 at 22:04
2

As mention by @ecm in the comments, the probable reason for sal and shl is symmetry with sar and shr. Both left-shift instructions are listed as separate instructions in Intel's Software Developer’s Manual, but have the same op code, i.e. from the processor's point of view they are the same.

1

they work the same, since an arithmetic shift is the same as a bitwise shift when it's to the left (increasing). sar, on the other hand, will be different from shr if the sign bit is set.

jcomeau_ictx
  • 37,688
  • 6
  • 92
  • 107
1

They are the same if you use the left direction.

-2

actually both are same ..! but SAL Used when numeric multiplication is intended EXAMPLE SAL:

Multiply AX by 8
MOV CL, 3
SAL AX, CL

BOTH ARE MOSTLY WORK SAME AND HAVE SAME MACHINE CODE