Changes

Intel 8086

13,326 bytes added, 12 May
/* Links */
[[File:Siemens 8086-2 PDIP.jpg|thumb|right|Intel 8086 manufactured by Siemens for Amstrad PC1512]]
 
The Intel 8086 is a landmark 16‑bit microprocessor introduced by Intel in 1978. It was the first in the x86 family and established many architectural conventions that continue to influence modern personal computing.
= History =
After the release of the [[Intel 8080 ]] CPU, Intel began working on the iAPX 432 project. It was an ambitious 32‑bit design—aimed at supporting advanced, high‑level programming features in hardware—which took several years and a large team to develop, partly because it awaited further improvements in chip density per Moore’s Law.
Meanwhile, to quickly counter the competition, Intel rushed a simpler, lower‑risk design: the 8086. This chip, developed as an incremental evolution of the 8080 and managed by a separate team, was ready for mass market in 1978.
The 8086's microcode ROM holds 512 micro-instructions, each 21 bits wide. The microcode engine is assisted by two smaller ROMs: the "Group Decode ROM" to categorize machine instructions, and the "Translation ROM" to branch to microcode subroutines for address calculation and other roles.
See: [https://righto.com/8086/groupRom.html Group Decode ROM viewer] [https://www.righto.com/2022/11/how-8086-processors-microcode-engine.html How the 8086 processor's microcode engine works] [https://www.righto.com/2023/07/undocumented-8086-instructions.html Undocumented 8086 instructions, explained by the microcode] [https://www.reenigne.org/blog/8086-microcode-disassembled/ 8086 microcode disassembled]
Reverse-engineering the: [https://www.righto.com/2023/03/8086-multiplication-microcode.html multiplication algorithm] [https://www.righto.com/2023/04/reverse-engineering-8086-divide-microcode.html division microcode] [https://www.righto.com/2023/04/8086-microcode-string-operations.html string operations] [https://www.righto.com/2023/01/reverse-engineering-conditional-jump.html conditional jumps] [https://www.righto.com/2023/03/8086-register-codes.html register codes] [https://www.righto.com/2023/02/8086-modrm-addressing.html ModR/M addressing microcode] [https://www.righto.com/2023/02/how-8086-processor-determines-length-of.html instructions length] [https://www.righto.com/2023/02/silicon-reverse-engineering-intel-8086.html flags circuitry] [https://www.righto.com/2023/02/8086-interrupt.html interrupt circuitry] [https://www.righto.com/2023/01/reverse-engineering-intel-8086.html HALT circuitry] [https://www.righto.com/2020/08/reverse-engineering-8086s.html ALU circuitry] in the Intel 8086 processor
== Pipeline Design Block Diagrams ==
Internally, the 8086 features a 16‑bit execution unit Execution Unit (EU) that performs arithmetic, logic, and control functions, while simultaneously a separate bus interface unit Bus Interface Unit (BIU) handles all data transfers and external communications.
The BIU includes a 6‑byte prefetch queue (4-byte for 8088). The EU fetches instructions from the prefetch queue (not directly from memory). It has no direct connection to the external system bus, relying entirely on the BIU for data and instruction access.
See: [https://www.righto.com/2023/01/the-8086-processors-microcode-pipeline.html The 8086 processor's microcode pipeline from die analysis] [https://www.righto.com/2024/03/8088-prefetch-circuitry.html Intel 8088 processor's instruction prefetch circuitry] [https://www.righto.com/2024/04/intel-8088-bus-state-machine.html Inside the Intel 8088 processor's bus interface state machine]
 
== Block Diagrams ==
[[File:Block-diagram-of-8086.jpg]]
In this scheme, the BIU forms memory addresses by shifting a 16‑bit segment register four bits to the left and then adding a 16‑bit offset. This results in a 20‑bit physical address.
Although this model can be seen as complex, it allowed small programs (fitting within a 64‑KB 64KB segment) to be loaded at a fixed offset, simplifying relocation in many cases.
See: [https://www.righto.com/2023/07/8086-pins.html Reverse-engineering the 8086 processor's address and data pin circuits]
== Register Structure File ==
The 8086 provides fourteen 16‑bit registers. Its register file includes{| class="wikitable" style="white-space:nowrap;"! Register !! Size !! Description !! Notes*'''Data Registers:''' |-| AX (accumulatorAccumulator)|| 16-bit || Primary register for arithmetic, logic, I/O. || Can be accessed as two 8-bit registers: AH (High) and AL (Low). Often an implied operand.|-| BX (baseBase)|| 16-bit || General-purpose, often used as a base pointer for memory addressing. || Can be accessed as BH and BL. Only GP register usable as an offset in memory addressing (e.g., `[BX]`).|-| CX (counterCount)|| 16-bit || General-purpose, often used as a loop counter (`LOOP` instruction) and DX for string operations (data`REP` prefixes). Each accessible || Can be accessed as high (AH, BH, CH, DH) and low CL.|-| DX (ALData) || 16-bit || General-purpose, BLused for I/O port addressing (`IN`, CL`OUT`), and holds high word in 16x16 multiplication / 32/16 division. || Can be accessed as DH and DL) 8‑bit registers.*'''Pointer and Index Registers:''' |-| SP (Stack Pointer) || 16-bit || Points to the top of the current stack pointer(offset within SS). || Used implicitly by `PUSH`, `POP`, `CALL`, `RET`, interrupts.|-| BP (base pointerBase Pointer), || 16-bit || Points to data within the stack segment (offset within SS). || Often used to access function parameters and local variables on the stack.|-| SI (Source Index) || 16-bit || Used as a source indexpointer offset (usually within DS)for string operations. Can be used as a general-purpose index register. || Default segment is DS, and can be overridden.|-| DI (Destination Index) || 16-bit || Used as a destination indexpointer offset (usually within ES) for string operations. Can be used as a general-purpose index register. || Default segment is ES for addressing and data manipulationstring ops, can be overridden.|-| IP (Instruction Pointer) || 16-bit || Holds the offset address of the next instruction to be executed within the current Code Segment (CS). || Analogous to Program Counter (PC). Cannot be directly manipulated by most instructions (modified by jumps, calls, etc.). Physical address = (CS *16) + IP.|-| FLAGS || 16-bit || Contains status and control flags: <br/> '''Segment RegistersStatus Flags:''' CS <br/> * bit 0 - CF (codeCarry Flag), DS <br/> * bit 2 - PF (dataParity Flag), SS <br/> * bit 4 - AF (stackAuxiliary Carry Flag), and ES <br/> * bit 6 - ZF (extraZero Flag) which define the memory segments for program code, data, and the stack.<br/> *bit 7 - SF (Sign Flag) <br/> * bit 11 - OF (Overflow Flag) <br/> '''Instruction Pointer and Control Flags:''' A 16‑bit instruction pointer <br/> * bit 8 - TF (IPTrap Flag) and a 16‑bit status register <br/> * bit 9 - IF (FlagsInterrupt Enable Flag)<br/> * bit 10 - DF (Direction Flag) <br/> (Other bits are undefined/reserved in 8086) || AF used for BCD arithmetic. This register includes six status flags DF controls string op direction (zero, carry, sign, overflow, parity, and auxiliary carryinc/dec SI/DI) . TF enables single-stepping. IF enables maskable interrupts.|-| CS (Code Segment) || 16-bit || Points to indicate the outcomes base address of operationsthe current code segment. It also contains three control flags: || Used with IP to find the Direction Flag controls next instruction.|-| DS (Data Segment) || 16-bit || Points to the direction in which string instructions act, base address of the Interrupt Flag current data segment. || Default segment for most data access.|-| SS (Stack Segment) || 16-bit || Points to enable/disable interrupts the base address of the current stack segment. || Used with SP and BP.|-| ES (Extra Segment) || 16-bit || Points to the Trap Flag base address of an extra data segment. || Often used as the destination segment for single-step debuggingstring operations (with DI).|}
<br>
== Instruction Set ==
As a complex instruction set computer (CISC), the 8086 supports a rich array of operations, including multiple addressing modes such as register, immediate, and memory addressing.
Although most operations execute on 16‑bit operands, the chip allows manipulation of 8‑bit data as well—an important feature for compatibility with legacy 8‑bit software.
See: [https://yassinebridi.github.io/asm-docs/ 8086_instruction_set.html Complete 8086 instruction set] [https://www.righto.com/2023/08/datapoint-to-8086.html Tracing the roots of the 8086 instruction set to the Datapoint 2200 minicomputer] {| class="wikitable" style="text-align: center;"|+ 8086 Instruction Set Summary! rowspan=2 | Mnemonic !! rowspan=2 | Description !! rowspan=2 | Operation !! colspan=6 | Flags Affected|-! OF !! SF !! ZF !! AF !! PF !! CF|-| AAA || ASCII Adjust After Addition || Adjust AL after BCD addition || U || U || U || * || U || *|-| AAD || ASCII Adjust Before Division || Adjust AX before BCD division || U || * || * || U || * || U|-| AAM || ASCII Adjust After Multiply || Adjust AX after BCD multiplication || U || * || * || U || * || U|-| AAS || ASCII Adjust After Subtraction || Adjust AL after BCD subtraction || U || U || U || * || U || *|-| ADC || Add with Carry || Destination + Source + CF → Destination || * || * || * || * || * || *|-| ADD || Add || Destination + Source → Destination || * || * || * || * || * || *|-| AND || Logical AND || Destination ∧ Source → Destination || 0 || * || * || U || * || 0|-| CALL || Call Procedure || Push IP (and CS); Target → IP (and CS) || – || – || – || – || – || –|-| CBW || Convert Byte to Word || Sign extend AL into AH || – || – || – || – || – || –|-| CLC || Clear Carry Flag || 0 → CF || – || – || – || – || – || 0|-| CLD || Clear Direction Flag || 0 → DF || – || – || – || – || – || –|-| CLI || Clear Interrupt Flag || 0 → IF || – || – || – || – || – || –|-| CMC || Complement Carry Flag || ¬CF → CF || – || – || – || – || – || *|-| CMP || Compare || Destination - Source (Flags set, result discarded) || * || * || * || * || * || *|-| CMPSB || Compare String Byte || Compare byte [DS:SI] with [ES:DI]; Update SI, DI || * || * || * || * || * || *|-| CMPSW || Compare String Word || Compare word [DS:SI] with [ES:DI]; Update SI, DI || * || * || * || * || * || *|-| CWD || Convert Word to Double Word || Sign extend AX into DX:AX || – || – || – || – || – || –|-| DAA || Decimal Adjust After Addition || Adjust AL after packed BCD addition || U || * || * || * || * || *|-| DAS || Decimal Adjust After Subtraction || Adjust AL after packed BCD subtraction || U || * || * || * || * || *|-| DEC || Decrement by 1 || Destination - 1 → Destination || * || * || * || * || * || –|-| DIV || Unsigned Divide || AX / Src(Byte) → AL (Q), AH (R) <br> DX:AX / Src(Word) → AX (Q), DX (R) || U || U || U || U || U || U|-| ESC || Escape (to coprocessor) || Used for floating-point/coprocessor instructions || – || – || – || – || – || –|-| HLT || Halt || Halt processor until interrupt or reset || – || – || – || – || – || –|-| IDIV || Signed Divide || AX / Src(Byte) → AL (Q), AH (R) <br> DX:AX / Src(Word) → AX (Q), DX (R) || U || U || U || U || U || U|-| IMUL || Signed Multiply || AL * Src(Byte) → AX <br> AX * Src(Word) → DX:AX || * || U || U || U || U || *|-| IN || Input from Port || Port → AL or AX || – || – || – || – || – || –|-| INC || Increment by 1 || Destination + 1 → Destination || * || * || * || * || * || –|-| INT || Interrupt || Push Flags, CS, IP; Vector → CS:IP || Clears TF, IF || – || – || – || – || –|-| INTO || Interrupt on Overflow || If OF=1 then INT 4 || Clears TF, IF if trap || – || – || – || – || –|-| IRET || Interrupt Return || Pop IP, CS, Flags || * || * || * || * || * || *|-| Jcc || Conditional Jump (e.g., JE, JNE, JG...) || If condition is met then IP + disp → IP || – || – || – || – || – || –|-| JMP || Unconditional Jump || Target → IP (and possibly CS) || – || – || – || – || – || –|-| LAHF || Load AH from Flags || Low byte of Flags → AH || – || – || – || – || – || –|-| LDS || Load Pointer using DS || mem → reg; mem+2 → DS || – || – || – || – || – || –|-| LEA || Load Effective Address || Effective Address of Source → Destination Register || – || – || – || – || – || –|-| LES || Load Pointer using ES || mem → reg; mem+2 → ES || – || – || – || – || – || –|-| LOCK || Lock Bus Prefix || Assert LOCK# signal during next instruction || – || – || – || – || – || –|-| LODSB || Load String Byte || [DS:SI] → AL; Update SI || – || – || – || – || – || –|-| LODSW || Load String Word || [DS:SI] → AX; Update SI || – || – || – || – || – || –|-| LOOP || Loop || CX - 1 → CX; If CX ≠ 0 then Jump || – || – || – || – || – || –|-| LOOPE / LOOPZ || Loop while Equal / Zero || CX - 1 → CX; If CX ≠ 0 and ZF=1 then Jump || – || – || – || – || – || –|-| LOOPNE / LOOPNZ || Loop while Not Equal / Not Zero || CX - 1 → CX; If CX ≠ 0 and ZF=0 then Jump || – || – || – || – || – || –|-| MOV || Move || Source → Destination || – || – || – || – || – || –|-| MOVSB || Move String Byte || Move byte [DS:SI] to [ES:DI]; Update SI, DI || – || – || – || – || – || –|-| MOVSW || Move String Word || Move word [DS:SI] to [ES:DI]; Update SI, DI || – || – || – || – || – || –|-| MUL || Unsigned Multiply || AL * Src(Byte) → AX <br> AX * Src(Word) → DX:AX || * || U || U || U || U || *|-| NEG || Negate (Two's Complement) || 0 - Destination → Destination || * || * || * || * || * || *|-| NOP || No Operation || No operation || – || – || – || – || – || –|-| NOT || Logical NOT (One's Complement) || ¬Destination → Destination || – || – || – || – || – || –|-| OR || Logical OR || Destination ∨ Source → Destination || 0 || * || * || U || * || 0|-| OUT || Output to Port || AL or AX → Port || – || – || – || – || – || –|-| POP || Pop Word from Stack || [SS:SP] → Destination; SP + 2 → SP || – || – || – || – || – || –|-| POPF || Pop Flags from Stack || [SS:SP] → Flags; SP + 2 → SP || * || * || * || * || * || *|-| PUSH || Push Word onto Stack || SP - 2 → SP; Source → [SS:SP] || – || – || – || – || – || –|-| PUSHF || Push Flags onto Stack || SP - 2 → SP; Flags → [SS:SP] || – || – || – || – || – || –|-| RCL || Rotate Left through Carry || Rotate Destination left, CF fills LSB, MSB fills CF || * || – || – || – || – || *|-| RCR || Rotate Right through Carry || Rotate Destination right, CF fills MSB, LSB fills CF || * || – || – || – || – || *|-| REP || String Repeat Prefix || Repeat following string op while CX ≠ 0 || – || – || – || – || – || –|-| REPE / REPZ || Repeat While Equal / Zero Prefix || Repeat following string op while CX ≠ 0 and ZF=1 || – || – || – || – || – || –|-| REPNE / REPNZ || Repeat While Not Equal / Not Zero Prefix || Repeat following string op while CX ≠ 0 and ZF=0 || – || – || – || – || – || –|-| RET || Return from Procedure || Pop IP (and CS) from stack || – || – || – || – || – || –|-| ROL || Rotate Left || Rotate Destination left, MSB fills LSB and CF || * || – || – || – || – || *|-| ROR || Rotate Right || Rotate Destination right, LSB fills MSB and CF || * || – || – || – || – || *|-| SAHF || Store AH into Flags || AH → Low byte of Flags || * || * || * || * || * || *|-| SAL / SHL || Shift Arithmetic/Logical Left || Shift Destination left, 0 fills LSB, MSB fills CF || * || * || * || U || * || *|-| SAR || Shift Arithmetic Right || Shift Destination right, MSB preserved, LSB fills CF || * || * || * || U || * || *|-| SBB || Subtract with Borrow || Destination - Source - CF → Destination || * || * || * || * || * || *|-| SCASB || Scan String Byte || Compare AL with byte [ES:DI]; Update DI || * || * || * || * || * || *|-| SCASW || Scan String Word || Compare AX with word [ES:DI]; Update DI || * || * || * || * || * || *|-| SHR || Shift Logical Right || Shift Destination right, 0 fills MSB, LSB fills CF || * || 0 || * || U || * || *|-| STC || Set Carry Flag || 1 → CF || – || – || – || – || – || 1|-| STD || Set Direction Flag || 1 → DF || – || – || – || – || – || –|-| STI || Set Interrupt Flag || 1 → IF || – || – || – || – || – || –|-| STOSB || Store String Byte || AL → [ES:DI]; Update DI || – || – || – || – || – || –|-| STOSW || Store String Word || AX → [ES:DI]; Update DI || – || – || – || – || – || –|-| SUB || Subtract || Destination - Source → Destination || * || * || * || * || * || *|-| TEST || Logical Compare (AND) || Destination ∧ Source (Flags set, result discarded) || 0 || * || * || U || * || 0|-| WAIT || Wait || Wait for TEST# pin active (for coprocessor sync) || – || – || – || – || – || –|-| XCHG || Exchange || Source ↔ Destination || – || – || – || – || – || –|-| XLAT / XLATB || Translate Byte || AL → [DS:BX + AL] || – || – || – || – || – || –|-| XOR || Logical Exclusive OR || Destination ⊕ Source → Destination || 0 || * || * || U || * || 0|} Note: Some instructions like LOOPE and LOOPZ are mnemonics for the same opcode. They are provided to match different programming contexts: LOOPE when thinking in terms of equality (e.g., a comparison was equal), LOOPZ when thinking in terms of zero (e.g., result was zero). == Secret Instruction == The secret instruction is SALC (Set AL register to Carry). Its opcode is 0xD6. This instruction sets the AL register to 0 if the carry flag is 0, and sets the AL register to FF if the carry flag is 1. Intel put this in all its x86 processors but didn't document it, using it as a trap. If a manufacturer cloned an Intel processor, the presence of the SALC instruction would prove that the clone stole Intel's microcode. Intel sued NEC for making 8086 clones, claiming that NEC ripped off Intel's microcode. NEC claimed they wrote their own microcode. NEC's chip didn't have the secret SALC instruction and Intel lost the case. See: [https://www.righto.com/2023/07/undocumented-8086-instructions.html Undocumented 8086 instructions, explained by the microcode] <br> = 8087 Floating Point Unit = Intel introduced the 8087 chip in 1980 to improve floating-point performance on 8086/8088 computers. Since early microprocessors were designed to operate on integers, arithmetic on floating point numbers was slow, and transcendental operations such as trig or logarithms were even worse. But the 8087 co-processor greatly improved floating point speed, up to 100 times faster. The benefits of floating point hardware are so great that Intel started integrating the floating-point unit into the processor with the 80486DX in 1989. See: [https://www.righto.com/2018/08/inside-die-of-intels-8087-coprocessor.html Inside the die] [https://www.righto.com/2018/09/two-bits-per-transistor-high-density.html High-density ROM] [https://www.righto.com/2020/05/extracting-rom-constants-from-8087-math.html Extracting ROM constants] [https://www.righto.com/2020/05/die-analysis-of-8087-math-coprocessors.html Fast bit shifter] 8087 FPU reverse engineered
<br>
*{{EnWiki}}
*[https://www.computerhistory.org/collections/catalog/102702019 Intel 386 oral history panel]
*[https://www.chibialiens.com/8086/ Learn Assembly Programming with ChibiAliens] Multi-platform 8086 tutorial
*[https://userpages.umbc.edu/~squire/intel_book.pdf Intel Microprocessors Practical Reference]
*[https://slideshare.net/slideshow/pindiagramdetailsof8086microprocessor/266134566 Pin diagram of 8086]
*[https://github.com/SingleStepTests Tom Harte's SingleStepTests]
*[https://github.com/reenigne/reenigne/blob/master/8088/acid88/acid88.txt Acid88] A testsuite for cycle-exact 8088 PC/XT emulators
<br>
13,147
edits