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
| Register | Name | Usual job |
|---|---|---|
| AX | accumulator | arithmetic; INT 21h's service number goes in its high byte, AH |
| BX | base | holds an address, to reach memory: [BX] |
| CX | count | counts loops (LOOP uses it) |
| DX | data | the high half of big results; INT 21h's data (DL, DX) |
| SI, DI | source and destination index | walk through arrays and strings |
| BP, SP | base pointer and stack pointer | the stack |
| IP | instruction pointer | the address of the next instruction |
| CS, DS, SS, ES | segment registers | where the code, data, stack and extra data are |
| FLAGS | the flags | single 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:
| Decimal | Hex | Binary |
|---|---|---|
| 10 | 0AH | 1010B |
| 65 | 41H | 01000001B |
| 255 | 0FFH | 11111111B |
| 4660 | 1234H | 0001001000110100B |
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 MAINWatch 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
| Rule | Wrong | Right |
|---|---|---|
| Both sides are the same size | MOV AX, BL | MOV AL, BL |
| At most one side is memory | MOV X, Y | MOV AL, Y then MOV X, AL |
| No number into a segment register | MOV DS, 0720H | MOV AX, 0720H then MOV DS, AX |
| The destination is a place, not a number | MOV 5, AX | MOV 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 MAINCommon mistakes
- Mixing sizes:
MOV AX, BL. Use the matching half:MOV AL, BL. - Writing hex without a leading digit:
FFHinstead of0FFH. - Expecting
MOVto empty the source. It only copies. - Forgetting that AH and AL are parts of AX: setting AX changes both.
Quick check
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.