Registers and MOV

A register is a small storage place inside the CPU itself, far faster than memory. The 8086 has fourteen of them, each 16 bits wide.

The registers

RegisterNameUsual job
AXaccumulatorarithmetic; INT 21h's service number goes in its high byte, AH
BXbaseholds an address, to reach memory: [BX]
CXcountcounts loops (LOOP uses it)
DXdatathe high half of big results; INT 21h's data (DL, DX)
SI, DIsource and destination indexwalk through arrays and strings
BP, SPbase pointer and stack pointerthe stack
IPinstruction pointerthe address of the next instruction
CS, DS, SS, ESsegment registerswhere the code, data, stack and extra data are
FLAGSthe flagssingle bits set by results: zero, carry, sign, ...

AX, BX, CX and DX can also be used in halves of 8 bits: AH is the high byte of AX and AL the low byte, and likewise BH/BL, CH/CL and DH/DL. They are not separate registers: change AL and AX changes too.

Hex and binary

Registers are easiest to read in hexadecimal (base 16): each hex digit is exactly 4 bits, so a byte is 2 hex digits and a word 4. The assembler reads all three bases:

DecimalHexBinary
100AH1010B
6541H01000001B
2550FFH11111111B
46601234H0001001000110100B

A hex number must start with a digit, so 255 is 0FFH, not FFH (which the assembler would read as a name).

MOV copies

MOV destination, source copies the source into the destination. The source keeps its value: MOV copies, it does not move.

; A 16-bit register and its two 8-bit halves.
.MODEL SMALL
.STACK 100H
.CODE
MAIN PROC
    MOV AX, 1234H     ; AH = 12h, AL = 34h
    MOV AL, 0FFH      ; only the low byte changes: AX = 12FFh
    MOV BX, AX        ; BX gets a copy; AX keeps its value
    MOV BH, AL        ; a byte into BX's high half: BX = FFFFh
    MOV CX, 10        ; decimal 10 = 000Ah
    MOV DL, 01000001B ; binary: 41h, the code of 'A'
    MOV AH, 2
    INT 21H           ; print DL
    MOV AH, 4CH
    INT 21H
MAIN ENDP
END MAIN
Open in compiler

Watch AX in the CPU view: putting 0FFH in AL changes only the low byte of AX, and MOV BH, AL copies a byte into the high half of BX.

The rules MOV must follow

RuleWrongRight
Both sides are the same sizeMOV AX, BLMOV AL, BL
At most one side is memoryMOV X, YMOV AL, Y then MOV X, AL
No number into a segment registerMOV DS, 0720HMOV AX, 0720H then MOV DS, AX
The destination is a place, not a numberMOV 5, AXMOV AX, 5

These rules come from how the instructions are encoded in machine code, and StepVioz explains each one when it is broken. XCHG swaps two places in one instruction:

; Swap two registers: with a third register, then with XCHG.
.MODEL SMALL
.STACK 100H
.CODE
MAIN PROC
    MOV AX, 5
    MOV BX, 9
    MOV CX, AX        ; CX = 5 (a spare copy)
    MOV AX, BX        ; AX = 9
    MOV BX, CX        ; BX = 5: swapped
    XCHG AX, BX       ; and back again in one instruction
    MOV AH, 4CH
    INT 21H
MAIN ENDP
END MAIN
Open in compiler

Common mistakes

  • Mixing sizes: MOV AX, BL. Use the matching half: MOV AL, BL.
  • Writing hex without a leading digit: FFH instead of 0FFH.
  • Expecting MOV to empty the source. It only copies.
  • Forgetting that AH and AL are parts of AX: setting AX changes both.

Quick check

1. AX = 1234h. What is AL?
2. Which is allowed on the 8086?
3. How is 255 written in hex for the assembler?
4. After MOV BX, AX, what is in AX?
My notes

Write down what you want to remember from this lesson. Notes are saved on this device as you type, and appear on your dashboard.