Question: What is purpose of `les` instruction in assembly?

Why do we need to load `es` segment **and** a register? Book gives following example:

```
les    bx, p           ; Load p into ES:BX
mov    es:[bx], al     ; Store away AL

```

Why do we need to load `es` **and** `bx` in this case?

Also why do we use `es:[bx]`? If `p` points to 100h in memory, isn't both `es` and `bx` 100h = 200h (`bx+es`)?

Answer: 
The 8086 segment registers `cs`, `ds`, `es`, and `ss` are the original mechanism by which 16-bit registers can address more than 64K of memory. In the 8086/8088, there were 20 bit addresses (1024 K) to be generated. Subsequent versions of the x86 processors added new schemes to address even more, but generating 20+ bits of address from a pair of 16-bit values is the basic reason.

In so-called "real mode" (native to 8086/8088/80186), an address is computed by multiplying the contents of the segment register by 16 (or, equivalently, shifted left by four places) and adding the offset.

In protected mode (available with the 80286 and later), the segment register selects a "descriptor" which contains a base physical address. The operand `es:[bx]`, for example, adds `bx` to that physical address to generate the operand address.
p points to a 32-bit FAR pointer with segment and offset part (in contrast to a NEAR pointer, which is only the offset part).
LES will load segment:offset into `ES:BX`.

Otherwise, you would have to use three instructions.
One for loading `BX`, and two for loading `ES` (segment registers cannot be loaded directly from memory but have to be loaded into a general-purpose register and then into the segment register).

Oh, yeah, wallyk had a good point with mentioning protected mode (although that is beside the point of your question).
Here, `ES` will be interpreted as a selector, not an actual segment.

A segment (address) in this context is a part of the physical address:  

Shift the segment by 4 bits to the left (i.e. multiply it by 2^4 = 16) and add the offset to get the physical address from segment:offset.

In contrast, a selector is a pointer to an entry in a so-called descriptor table (i.e. a selector points to a descriptor) and is used in protected mode.
A descriptor table (e.g. [GDT](http://wiki.osdev.org/Global_Descriptor_Table)) may contain entries of information about chunks of memory, including information about the physical memory address, the chunk size, access rights etc. (there are some slightly other uses as well).