Each memory operand has a default segment: SS when the address uses BP, DS otherwise. Writing a segment register and a colon before the operand, as in MOV AX, ES:[BX], makes the CPU use that segment instead. The assembler turns it into a one-byte prefix in front of the instruction. It applies to that instruction only, and changes no flags.
| Prefix | Byte | Typical use |
|---|---|---|
| ES: | 26h | a second data area, video memory |
| CS: | 2Eh | variables stored with the code, in interrupt handlers |
| SS: | 36h | stack data addressed with BX, SI or DI |
| DS: | 3Eh | data addressed with BP |
MOV AX, 0B800hMOV ES, AX ; ES -> colour text memoryMOV DI, 140 ; row 0, column 70 (two bytes per cell)MOV SI, OFFSET TXT1MOV CX, 5COPY1:MOV AL, CS:[SI] ; read our data through CSMOV AH, 1Eh ; yellow on blueMOV ES:[DI], AX ; write through ESADD DI, 2INC SILOOP COPY1TXT1 DB 'HELLO'
What cannot be overridden
Instruction fetch always uses CS:IP. The stack operations (PUSH, POP, CALL, RET, interrupts) always use SS:SP. The destination of a string instruction is always ES:DI. The source of a string instruction, DS:SI, can be overridden, so MOVS can copy from ES or CS to ES.
Why an interrupt handler uses CS:
When a hardware interrupt arrives, DS still belongs to whichever program was running. A handler that keeps its variables in its own code segment reads them with CS: until it has set DS, or without ever touching DS.
Pitfalls
In a .COM all segment registers start equal, so a missing override can go unnoticed until the code moves into a .EXE. In a .EXE, SS and DS usually differ, and [BP+...] pointing at data needs DS:. MASM also inserts overrides on its own, based on ASSUME, when a variable lives in a segment that DS is not assumed to hold. On the 8086 and 8088, a repeated string instruction with both REP and a segment prefix can lose one of its prefixes if an interrupt arrives in the middle; disable interrupts around it or avoid the combination.
Later CPUs
The 80386 adds FS: (64h) and GS: (65h).