We do not have any official Intel documentation of 8086/8088 errata, but the following are well-known “features” of those CPUs.
On early Intel 8088 processors (marked “INTEL ‘78” or “(C) 1978”), if an interrupt occurs immediately after a
MOV SS,xxx or
POP SS instruction, data may be pushed using an incorrect stack address, resulting in memory
The work-around is to change SS (along with SP) only when hardware interrupts are disabled. However, that does not resolve NMIs (non-maskable interrupts); on IBM PCs, you can work around the NMI problem by temporarily disabling NMIs (see port 0x61).
Intel provided a fix for this on later processors, by delaying the acknowledgement of hardware interrupts immediately
MOV SS,xxx or
POP SS instruction; the delay lasts only one instruction, so you’re obliged to change SP on
the very next instruction.
Intel’s fix also appears to have been overbroad: all
MOV segreg,xxx and
instructions delay interrupts, not just
MOV SS,xxx and
POP SS. In fact, it’s been
reported that all
PUSH segreg instructions may also have the same delaying effect, at least on some 80C88 processors.
If a repeated string instruction includes more than one override prefix; eg:
REP ES: MOVSB
and an interrupt occurs, the instruction will restart with the last override prefix byte, ignoring any preceding prefix bytes. This was never fixed in any 8086/8088.
The recommended work-around is to ensure that the segment override is the last prefix byte, and then rewrite the operation like this:
top: REP ES: MOVSB JCXZ done JMP top done:
If you’re not sure your assembler will output the
ES: overrides in the order shown, then you should
generate the override bytes manually, using DB or a similar assembler directive.
Some of the following information is courtesy of the OS/2 Museum.
This single-byte opcode existed only on the 8086/8088, and was of limited use, since it altered CS without a corresponding IP.
There is no
POP CS instruction on later x86 CPUs. The opcode was explicitly made invalid on the 80186/80188,
but was reused on later CPUs (starting with the 80286) as the first byte in a series of two-byte opcodes.
Opcodes 0x60 through 0x6F decode identically to the conditional jump opcodes at 0x70 through 0x7F, respectively. This is not true for any other x86 CPU.
POP CS, this instruction was of limited value when the selected segreg was CS.
Note that segreg is encoded as a 3-bit value in the second byte of the instruction, where:
On the 8086/8088/80186/80188, values 0-3 were treated the same as values 4-7, and all values were allowed.
Starting with the 80186, opcodes 0xC0 and 0xC1 were reused for new shift and rotate instruction groups,
and opcodes 0xC8 and 0xC9 became the
While AAM is documented, it has undocumented features (eg, its ability to divide by values other than 10, and its effect on the flags). See the AAM instruction for details.
While AAD is documented, it has undocumented features (eg, its ability to multiply by values other than 10, and its effect on the flags). See the AAD instruction for details.
Performs an operation equivalent to
SBB AL,AL, but without modifying any flags. In other words, AL will be set to
0xFF or 0x00, depending on whether CF is set or clear. This instruction exists on all later x86 CPUs, but for some
reason, it has never been documented. Also known as SETALC.
It is believed that 0xF1 decodes identically to 0xF0 (the
On newer processors, 0xF1 is an undocumented instruction usually called
INT1. See the
ICEBP instruction for details.