>
section 2 of 136 min read

2. 8086 Programming

The 8086's instruction set is the seed crystal of the entire x86 instruction set. Master it and you can read most modern x86 assembly with a chapter of additions in your head.

2.1 The assembly toolchain

plaintext
   source.asm  ─[ MASM / NASM / TASM ]─→  source.obj

                                          [ LINK ]

                                          program.exe ──→ DOS / DOSBox / BIOS

The flow: write a .asm source file, assemble (nasm -f obj source.asm or masm /c source.asm) into an .obj, link (link source.obj) into an .exe, run on DOS or in a DOSBox emulator. Real PCs cannot natively run 8086 binaries today (they boot in long mode), but DOSBox is a clean emulator and is excellent for learning.

2.2 Instruction set categories

Data transfer. Move bytes and words between registers, memory, and I/O.

  • MOV dst, src — copy. The most-used instruction by far.
  • PUSH src, POP dst — to and from the stack.
  • XCHG a, b — swap.
  • IN AL, port, OUT port, AL — read/write I/O port.
  • LEA reg, mem — load effective address (the computed address itself, not the value at the address). Useful for pointer arithmetic.

Arithmetic.

  • ADD dst, src, ADC dst, src (add-with-carry, used to chain multi-precision adds).
  • SUB, SBB.
  • INC, DEC — by 1, no flags-write of CF.
  • MUL src — unsigned multiply: AX = AL × src (8-bit), or DX:AX = AX × src (16-bit). Result is wider than operands.
  • IMUL src — signed multiply.
  • DIV src — unsigned divide: AX/src → quotient AL, remainder AH (8-bit); or DX:AX/src → quotient AX, remainder DX (16-bit).
  • IDIV src — signed divide. Beware: dividing by zero, or producing a quotient too large to fit, fires interrupt 0.
  • NEG dst — two's-complement negate.
  • CMP a, b — compute a−b, set flags, discard result. Used before conditional jumps.

Logical.

  • AND, OR, XOR, NOT.
  • TEST a, b — like AND but discard result; used to test bits.
  • SHL/SHR — shift left/right (logical).
  • SAL/SAR — shift arithmetic (preserves sign on right shift).
  • ROL/ROR/RCL/RCR — rotate (with or without carry).

String. The 8086 has dedicated string-operation instructions that work on byte/word arrays at DS:SI (source) and ES:DI (destination), automatically incrementing or decrementing the indices based on the DF flag.

  • MOVS — copy DS:[SI] to ES:[DI], advance both.
  • CMPS — compare two strings.
  • SCAS — scan for a byte/word matching AL/AX.
  • LODS — load from DS:[SI] into AL/AX.
  • STOS — store AL/AX to ES:[DI].
  • REP/REPE/REPNE — repeat prefix; runs the string instruction CX times (or until ZF condition).

So REP MOVSB with CX=100 copies 100 bytes — memcpy in two assembly instructions.

Branch / control flow.

  • JMP target — unconditional. Can be near (within segment) or far (to another segment).
  • Conditional: JE/JZ (equal/zero), JNE/JNZ, JG/JNLE (signed greater), JL/JNGE, JA/JNBE (unsigned above), JB/JC, JS/JNS (sign), JO/JNO (overflow), JP/JNP (parity). About 30 mnemonics, all really six bits of flag-test.
  • LOOP target — decrement CX, jump if non-zero.
  • LOOPE/LOOPNE — extra ZF condition.
  • CALL target — push return address, jump.
  • RET — pop return, jump.
  • INT n — software interrupt.
  • IRET — return from interrupt.

Processor control.

  • STC/CLC — set/clear CF.
  • STI/CLI — set/clear IF (enable/disable interrupts).
  • STD/CLD — set/clear DF.
  • NOP — do nothing for one instruction (actually XCHG AX, AX).
  • HLT — halt until next interrupt.

2.3 Addressing modes

The 8086 has eight addressing modes. The compiler/assembler chooses based on how you write the operand.

ModeExampleEffective address
ImmediateMOV AX, 1234h(operand is the value 1234h)
RegisterMOV AX, BX(operand is in BX)
DirectMOV AX, [1000h]DS:1000h
Register indirectMOV AX, [BX]DS:BX
BasedMOV AX, [BX+10h]DS:(BX+10h)
IndexedMOV AX, [SI]DS:SI
Based indexedMOV AX, [BX+SI]DS:(BX+SI)
Based indexed + dispMOV AX, [BX+SI+10h]DS:(BX+SI+10h)

A few notes. The base register can be BX or BP (where BP defaults to SS instead of DS — useful for stack frames). The index register can be SI or DI. The displacement is an 8-bit or 16-bit signed value baked into the instruction. You can override the default segment with a prefix: MOV AX, ES:[BX] reads from ES instead of DS.

2.4 Assembler directives

These are not instructions. They tell the assembler how to lay out memory.

DirectiveEffect
DB 0xFF, 0x12Define byte(s).
DW 0x1234Define word (16-bit).
DD 0x12345678Define double word.
100 DUP(0)Duplicate: 100 copies of zero.
VAL EQU 50Equate: symbolic constant.
ORG 100hSet origin (current address).
SEGMENT name / ENDSBegin/end segment.
PROC name / ENDPBegin/end procedure.
END startEnd of source, with start label.

2.5 Sample programs

Add two 16-bit numbers and store the result.

asm
.MODEL SMALL
.STACK 100h
.DATA
    NUM1 DW 1234h
    NUM2 DW 5678h
    SUM  DW 0
.CODE
START:  MOV AX, @DATA       ; load DS with start of data segment
        MOV DS, AX
        MOV AX, NUM1        ; AX = 1234
        ADD AX, NUM2        ; AX = 1234 + 5678 = 68AC
        MOV SUM, AX         ; store
        MOV AX, 4C00h       ; DOS exit with code 0
        INT 21h
        END START

Loop counting (sum 1..10).

asm
        MOV CX, 10          ; counter
        MOV AX, 0           ; running sum
        MOV BX, 1           ; current value
NEXT:   ADD AX, BX
        INC BX
        LOOP NEXT           ; CX-- ; if CX != 0, jump back
        ; AX = 55

Multiply two 16-bit numbers (32-bit result in DX:AX).

asm
        MOV AX, 1000h
        MOV BX, 2000h
        MUL BX              ; DX:AX = AX * BX = 0200_0000h

Divide.

asm
        MOV AX, 0FFFFh
        MOV DX, 0           ; DX:AX = dividend (zero-extended)
        MOV CX, 10
        DIV CX              ; AX = quotient (6553), DX = remainder (5)

String copy (memcpy of N bytes).

asm
        MOV CX, N           ; count
        LEA SI, SOURCE      ; DS:SI = source
        LEA DI, DEST        ; ES:DI = dest
        CLD                 ; clear DF → SI/DI increment
        REP MOVSB           ; copy CX bytes

BCD addition (Binary-Coded Decimal — each nibble holds one decimal digit).

asm
        MOV AL, 25h         ; BCD 25
        ADD AL, 18h         ; binary add: AL = 3D
        DAA                 ; Decimal Adjust Accumulator: AL = 43h, the BCD answer 43

ASCII to binary (single digit).

asm
        SUB AL, '0'         ; '7' (37h) becomes 7

2.6 Tools

MASM (Microsoft Macro Assembler), NASM (Netwide), TASM (Borland) are the canonical assemblers. DOSBox is a free DOS emulator that runs on every modern OS — assemble with NASM, run in DOSBox, debug with the legendary DEBUG.EXE that ships with DOS. For Windows you can also try emu8086, a teaching IDE that highlights flag changes step-by-step.