I have questions regarding some x86 instructions that were documented for the 80386 and later x86 CPUs, but not for earlier chips.

  • "OR reg/mem16, immed8" (0x83/1) "AND reg/mem16, immed8" (0x83/4) and "XOR reg/mem16, immed8" (0x83/6) These opcodes are "not used" on 8086/8088 according to this manual: https://edge.edx.org/c4x/BITSPilani/EEE231/asset/8086_family_Users_Manual_1_.pdf page 4-31 (but the meaning of "not used" is unclear). Old assemblers seem to avoid generating these, even if this means a four-byte instruction instead of a three-byte one (except for AX).

  • XLAT with a segment override prefix: Manuals for 8086 and 80286 only mention that it uses the DS register. It was first mentioned in the 80386 manual that it accepts segment prefixes.

Does somebody have any information on what these instructions actually do on CPUs where they are undocumented (8086/8088/80286/NEC V20)?

  • 1
    There are plenty of resources about undocumented 8086 opcodes per se (<os2museum.com/wp/undocumented-8086-opcodes-part-i> surveys some, for example), but under the constraint that those are documented for the 80386? I doubt you’ll find much. Jun 5 at 8:01
  • 1
    Fun one: REP IMUL inverts the sign of the multiply result.
    – Joshua
    Jun 5 at 17:46

They behave like aliases for the documented instructions. They are present and functionally equivalent. There's also SALC (D6 but not on the NEC), ICEBP (F1), string instructions using ES: override; and AAM and AAD accepting values other than 10, though those last two are fairly obvious.

  • 2
    I suspect that during the design process, it wasn't clear whether it would be easier to have microcode that would treat the operand as an 8-bit value, treat the operand as a 4-bit value, or always perform the operation in a manner suitable for the value 10. Specifying the opcode has having a second-byte value of 0x0A accommodates all of those possibilities.
    – supercat
    Jun 5 at 16:25

In the days of "no unnecessary transistors allowed", it was common to simply let the decoding logic do whatever it naturally did in cases that weren't intended to have defined behavior. The 6502 was particularly notorious. At the same time, designers often wanted the possibility of using those cases for new behaviors in the future. So, it was common to declare those cases "undefined", making the programmer responsible for any future compatibility problems even if the actual behavior was predictable.

  • 1
    Whilst that's true, it doesn't address the specific question of what behaviour these opcodes have on the 8086 or 80286. Jun 7 at 7:21

MAME's 8086/88/186/188/286 emulator here, V20/V30/V33/V33A emulator here, and V30MZ emulator here all support 83/1, 83/4, and 83/6, and they all don't support a segment override for XLAT (the prefix is allowed but ignored). Search for 0x83 and 0xd7 to find the implementations.

The fact that they all agree doesn't necessarily mean they're correct, since they all seem to have been forked from common code at some point. But I suppose that whoever implemented 83/x with no CPU-version test and put an explicit DS in the XLAT implementation probably knew what they were doing.


These opcodes are "not used" on 8086/8088 according to this manual: [...] but the meaning of "not used" is unclear [...]

Err... what of 'not used' is unclear? For a CPU, its manual is holy scripture, to be taken word for word. If it says something then it must be. Assuming otherwise, even if it can be proven, is blasphemous.

Not each opcode combination possible does make sense. In this case they are simply not assigned to any functionality, because it would not make much sense for the basic 16 bit CPU. They are essentially duplicates.

The block 80..83 must be seen as one encoding case. The the basic opcode is 1000.00sw, marking an ALU operation with

  • w defining whether it's an 8 or 16 bit operation and
  • s defining whether a sign extension is to be applied or not

83h is a bit special, as with a 16 bit target and a 16 bit immediate, a sign extension wouldn't make much sense, would it? So having both set (word and sign extension) marks a signed 8 bit immediate to follow instead of a 16 bit one.

  • w=0; s=0 -> 8 bit target and 8 bit immediate
  • w=0; s=1 -> 8 bit target and 8 bit immediate
  • w=1; s=0 -> 16 bit target and 16 bit immediate
  • w=1; s=1 -> 16 bit target and 8 bit immediate

The ALU operation to be used is specified in the second byte as xxxOOOxx:

  • 000 -> ADD
  • 001 -> OR
  • 010 -> ADC
  • 011 -> SBB
  • 100 -> AND
  • 101 -> SUB
  • 110 -> XOR
  • 111 -> CMP

So, while sign extension does make much sense for arithmetic operation, it isn't as useful for logical operations.

No matter if it's about byte handling (82h, <op> rm8,i8) or word handling (83h, <op> rm16,i16) sign extension would be of no difference to non-sign-extending opcodes (80h/81h). They are simply the same operation.

There are two oddities here:

  • The whole 82h opcodes are kind of redundant with the 80h range. Only the 8086 manual marks them in that single table as explicit opcodes. Later manuals (186, 286) still list the S/W encoding for arithmetic immediate operations, but no longer list the 82h opcodes (or any unassigned opcode at all). The 386 manual also drops the entire description of the S/W encoding.

  • Why only the logic operation within 82/83h have been marked as unused in the 8086 manual can only be speculated. It's possible that the structure of the ALU simply didn't allow the use of sign extension and bit operations at the same time.

So, why were they introduced with the 80386?

For space reasons. Regardless of target size selected, 83h always uses an 8 bit immediate. While this is not a really big thing in an 8/16 bit environment, it becomes more useful when target size depends on modal operation - not to mention substantial space savings in 32 bit code, at least as long as operations are fine with only 7 usable bits.

XLAT with a segment override prefix: Manuals for 8086 and 80286 only mention that it uses the DS register. It was first mentioned in the 80386 manual that it accepts segment prefixes.

Oh, that's an easy one. The operand of XLAT is not a memory location, which has a segment assigned, but the register AL. One can't overwrite a non-existent segment. The ability to use a segment is simply an addition introduced with the 80386.

Does somebody have any information on what these instructions actually do on CPUs where they are undocumented (8086/8088/80286/NEC V20)?

Not really sure what that should be good for, as it's simply not defined.

  • 2
    That the instructions are simply not defined is the obvious conclusion from what the linked manual says, but I cannot find any evidence that is the case. Every other reference says these instructions work fine, going back to the 8088/86. Do you have an independent source for this claim that these instructions are not defined/unsupported?
    – Cody Gray
    Jun 5 at 7:06
  • 3
    @CodyGray If the manual doesn’t define them, they are undefined by, ahem, definition. Whether an opcode is defined or not is entirely a matter of official documentation. Independent sources can report on how undefined opcodes behave in practice, but cannot actually define them. Jun 5 at 7:47
  • Ah, is what is linked in the question a copy of the official manual? That wasn't clear to me. It certainly isn't a link to an official looking source. I assumed it was a third-party compilation (there were lots of those in the days before the Internet, some of them even professionally done). If the Intel manual says they are undefined, then, yeah, that'd be a pretty good clue, you're right, @user3840170.
    – Cody Gray
    Jun 5 at 8:53
  • @CodyGray The copyright notice at the bottom says ‘Mnemonics © Intel, 1979’ (asserting copyright claim on the assembly language, meaning the document itself was probably created by Intel as well), and there is a PDF annotation next to it whose contents suggests this is the official manual. Jun 5 at 11:08
  • @CodyGray It is the regular 8086 manual. See here for the very same page on Achive.org
    – Raffzahn
    Jun 5 at 13:31

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.