r0mheat z80 lessons

8086 reference

Trainer

Loading…

How to read this page

Each instruction lists its forms: reg8 and reg16 are a register, mem8 and mem16 a byte or word in memory, imm8 and imm16 a value in the instruction. Encoding is the machine code: /r is a ModRM byte with a register and a register or memory operand, /n a ModRM byte whose register field is the number n (it extends the opcode), +rb and +rw a register number (0 to 7) added to the opcode, ib and iw an immediate byte or word (low byte first), cb and cw a relative offset, cd a far pointer (offset, then segment). Size is the length in bytes, with the ModRM byte but without a displacement. Cycles are clock cycles measured on the emulator of this trainer. Two numbers such as 17/5 mean: 17 when the jump or loop is taken, 5 when not; for a shift by CL they mean the time with CL = 2 and with CL = 0 (a shift takes 8 cycles plus 4 for each bit shifted).

The cycles of a memory form are for [BX]. Other addressing modes cost more: see the table of addressing modes below.

Registers

Flags (register FLAGS)

Addressing modes

Memory operands

The 8086 builds the offset of a memory operand from one of these eight forms, with an optional displacement of 8 bits (−128 to 127) or 16 bits, or from a 16-bit address alone. The offset is in the segment shown (DS, or SS when BP is used) unless the instruction has a segment override. Only these combinations exist: one of BX or BP, one of SI or DI, in any pair, or one register alone. [BP] has no form without a displacement: the assembler writes [BP+0] with a zero byte.

Measured on the emulator for MOV CX,[mode], a 16-bit read from memory. The Intel data book gives the same differences: 5 cycles of address for one register, 7 or 8 for a base plus an index, 6 for an address alone, and 4 more for a displacement. The one difference is that this emulator charges [BP+disp] one cycle more than the other registers with a displacement (it adds 4 to the 6 cycles of an address alone), where the data book gives 9 for all of them.

Idioms

Short ways to do common jobs. Bytes and cycles are added up from the measured forms below; 17/5 means 17 when the jump is taken, 5 when not.

The machine

An 8088 with 1 MB of RAM, run as a DOS .COM program. CS, DS, ES and SS are 0100H, IP is 0100H (or the first byte of the program), SP is FFFEH and IF is set. The program is loaded at 0100:0100. Offset 0 of the segment holds INT 20H and the word at the top of the stack is 0, so a RET from the program ends it, as under DOS. A segment is 64 KB; the address of seg:off is seg × 16 + off, and it wraps at 1 MB.

A run ends at HLT, at the end of the program, at a breakpoint, when a watched byte changes, at the cycle limit, at a divide error, or at an interrupt that nothing handles.

While the interrupt vector (the four bytes at 0000:n×4) is empty, these services are built in. When the program sets a vector, the CPU runs the program's handler instead. Each costs the cycles of the INT and of an IRET.

An INT with no service and no vector, the TF trap and INTO stop the run, and the page says which interrupt it was. A zero byte sent to the console is not printed.

Notes on the cycles

  • The cycles are those of the emulator: the 8088 timings of VirtualXT, with the penalty of the 8-bit bus (4 more cycles for each word that goes to or from memory). They are close to the Intel data book, but not always the same: INC reg16 takes 3 cycles here and 2 in the manual.
  • The numbers assume that the prefetch queue is full. A real 8088 also waits for its queue after a jump or a long instruction, so a real machine can be slower.
  • The time of MUL, IMUL, DIV and IDIV depends on the operands; the number shown is for small values.
  • A conditional jump, LOOP and JCXZ show two numbers: taken, then not taken. A shift by CL takes 8 cycles, plus 4 for each bit shifted; the two numbers are for CL = 2 and CL = 0.
  • With a REP prefix a string instruction runs CX times, so the total is about CX times the cycles shown, plus a start-up cost.