Intel 8086 opcodes - CP/M

This is a discussion on Intel 8086 opcodes - CP/M ; On 2007-09-13, roche182@laposte.net wrote: > However, if I have well understood, the only difference between the > 8086 and the 8088 (that Intel was obliged to introduce 2 years later, > since everybody was using 8-bit systems at the time. ...

+ Reply to Thread
Page 3 of 4 FirstFirst 1 2 3 4 LastLast
Results 41 to 60 of 65

Thread: Intel 8086 opcodes

  1. Re: Intel 8086 opcodes

    On 2007-09-13, roche182@laposte.net wrote:
    > However, if I have well understood, the only difference between the
    > 8086 and the 8088 (that Intel was obliged to introduce 2 years later,
    > since everybody was using 8-bit systems at the time. Introducing a 16-
    > bit CPU alone, without any 16-bit environment was, of course, crazy.
    > Finally, a little company chose the 8088...) is the "size" of the I/O
    > words (16 versus 8).


    As Allison has mentioned, they also differ in the depth of their
    prefetch buffer. Software used to be able to detect which processor
    (8088 vs 8086) they were running on by using self-modifying code,
    changing an opcode close to where they were executing. If the old
    opcode was executed, the processor was an 8086 with a deep buffer
    (it had already prefetched the opcode, so missed the update). If
    the new opcode was exectued, the processor was an 8088.

    I don't recall which software I saw that tested this, or why it
    needed to know.

    IIRC, on an 8086 only even I/O ports can be 16 bits wide...
    --
    roger ivie
    rivie@ridgenet.net

  2. Re: Intel 8086 opcodes

    Roger Ivie writes:
    >
    > I don't recall which software I saw that tested this, or why it
    > needed to know.


    I could imagine that precisely BECAUSE of the different prefetch
    behavior that information could be used to color various unrolling
    decisions.

    > IIRC, on an 8086 only even I/O ports can be 16 bits wide...


    I seem to remember the same requirement for the 8088 - I had a
    programmer friend who swore up and down that you couldn't do 16-bit
    IN/OUT instructions at ALL on the 8088, and was flabbergasted when I
    showed my system that used them all the time (talking to an on-board
    68000) ...

    --
    Lawrence Statton - lawrenabae@abaluon.abaom s/aba/c/g
    Computer software consists of only two components: ones and
    zeros, in roughly equal proportions. All that is required is to
    place them into the correct order.

  3. Re: Intel 8086 opcodes

    On 13 Sep 2007 14:54:41 -0500, Lawrence Statton
    wrote:

    >Roger Ivie writes:
    >>
    >> I don't recall which software I saw that tested this, or why it
    >> needed to know.

    >
    >I could imagine that precisely BECAUSE of the different prefetch
    >behavior that information could be used to color various unrolling
    >decisions.


    It wasn't that smart. If the prefetch was busted the que is flushed
    and the next fetch was the required instruction or data and the que
    refilled.

    >
    >> IIRC, on an 8086 only even I/O ports can be 16 bits wide...

    >
    >I seem to remember the same requirement for the 8088 - I had a
    >programmer friend who swore up and down that you couldn't do 16-bit
    >IN/OUT instructions at ALL on the 8088, and was flabbergasted when I
    >showed my system that used them all the time (talking to an on-board
    >68000) ...


    Of course it can... 8bits at a time!

    Allison


  4. Re: Intel 8086 opcodes

    On Thu, 13 Sep 2007 06:29:44 -0700, roche182@laposte.net wrote:

    >Hello, Steve!
    >
    >> The issue here is that the source is a signed byte, but the
    >> destination is word_sized, so..
    >>
    >> 83 nn OP Reg16|Mem16,signed Immed8
    >>
    >> assures sign extention into the larger destination. I wonder how many
    >> subtle bugs involve this detail being missed.

    >
    >Hum... Question: Do you think that I should leave it alone?
    >
    >My first feeling was to remove the "signed byte" distinction, and to
    >replace it with "byte".
    >
    >But, then, of course, the sign bit would not be "extended"...
    >
    >Damned! All that for 5 bytes out of 40 K! As I said, I could not find
    >any instance of a "signed byte" anywhere else in the Intel doc. (It
    >would be funny to ask this question to some "gurus"...)
    >
    >Opinions welcomed.
    >
    >Yours Sincerely,
    >Mr Emmanuel Roche
    >


    Your flogging a dead horse.

    One of the things you haven't considered is the work alike NEC V20
    and friends. They are different inside and yet they execute all
    Intel opcodes plus those for the 8080 emulation. They even fit the
    same socket.

    Soon as you look at 80186/8 and the later parts your vision will
    clear.

    The intel docs were official but not the most well written.

    Allison

  5. Re: Intel 8086 opcodes

    On Sep 13, 7:29 am, roche...@laposte.net wrote:
    > Hello, Steve!
    >
    > > The issue here is that the source is a signed byte, but the
    > > destination is word_sized, so..

    >
    > > 83 nn OP Reg16|Mem16,signed Immed8

    >
    > > assures sign extention into the larger destination. I wonder how many
    > > subtle bugs involve this detail being missed.

    >
    > Hum... Question: Do you think that I should leave it alone?
    >

    Hello!

    Yes, it is an important difference. If anything it should be
    emphasized.
    Byte FDh == -3, cast to a word_size with sign extention -> FFFDh ==
    -3.
    Byte FDh cast to word_size without extention -> 00FDh == 253.

    Steve

    > My first feeling was to remove the "signed byte" distinction, and to
    > replace it with "byte".
    >
    > But, then, of course, the sign bit would not be "extended"...
    >
    > Damned! All that for 5 bytes out of 40 K! As I said, I could not find
    > any instance of a "signed byte" anywhere else in the Intel doc. (It
    > would be funny to ask this question to some "gurus"...)
    >
    > Opinions welcomed.
    >
    > Yours Sincerely,
    > Mr Emmanuel Roche




  6. Re: Intel 8086 opcodes

    Lawrence Statton wrote:
    (snip)

    >>IIRC, on an 8086 only even I/O ports can be 16 bits wide...


    > I seem to remember the same requirement for the 8088 - I had a
    > programmer friend who swore up and down that you couldn't do 16-bit
    > IN/OUT instructions at ALL on the 8088, and was flabbergasted when I
    > showed my system that used them all the time (talking to an on-board
    > 68000) ...


    The 8088 presumably does two IN or OUT cycles to successive
    addresses for word I/O instructions. The 8086 should do two
    cycles for word I/O to an odd address. It will look to
    the device like two 8 bit I/O instructions. That will work
    for some devices, and not others.

    I believe that the 8086's HBE does not go low for a byte IN on an
    even address, but I can't be sure about that.

    -- glen


  7. Re: Intel 8086 opcodes

    no.spam@no.uce.bellatlantic.net wrote:

    > On Thu, 13 Sep 2007 02:26:00 -0800, glen herrmannsfeldt


    (snip regarding 8086 ESC)

    >>If I (remember,understand) right, the 8086 fetches one byte from
    >>the target address. It doesn't modify the register indicated, but
    >>does it ever fetch two bytes? I believe an 8088 will only fetch
    >>one, as will an 8086 with an odd address. In the case of an
    >>even address, does the 8086 fetch the whole word, even when only
    >>one byte is needed? Does a load of al from an even memory
    >>address do a 16 bit fetch or an 8 bit fetch?


    > If memory is right the 86 fetches three and the 88 only one.


    I am pretty sure it is only one cycle, and I believe one
    byte even on the 8086. I am a little unsure in general if the
    8086 guarantees to keep HBE high on an even byte read cycle.

    It is much more important to get right on a write cycle!

    > However what has been forgotton is the 8089 IOP also hasan interacting
    > mechanism like a NDP.


    I actually have an 8089, though nothing to use it on.

    -- glen


  8. Re: Intel 8086 opcodes

    Hello, Glen!

    Back home, here is what I found about the 8086/8088 difference
    (I mistook "I/O" for "memory".)

    (By the way, when re-(etc.)reading the book, I found somewhere
    that "primary opcode" are usually coded on 5 bits, and
    "secondary opcodes" are coded on 7 bits (in the "primary
    opcode") and 3 bits (between MOD and R/M). So simple, isn't it?)

    Yours Sincerely,
    Mr Emmanuel Roche


    The 8086, as well as the 8088, has some instructions that access
    (read or write) bytes, and other instructions that access words.
    Now, here comes the difference between the two processors. Let
    us consider the 8088 first. The amount of information that the
    8088 transfers to, or from, memory at one time is always 8 bits.
    A byte instruction in the 8088 can perform its function with one
    memory access, whereas an 8088 word instruction must do two
    memory accesses to two consecutive bytes. Examples of 8088 byte
    and word reads are shown in Figure 2.4.

    8088 Memory
    +------+ : : Lower addresses
    | | <---- Byte being read ---- | // |
    | | | |
    +------+ : : Higher addresses

    (a) Reading in a byte


    8088 Memory
    +------+ : : Lower
    addresses
    | | <-- 1st byte of word being read -- | // |
    | | <-- 2nd byte of word being read -- | // |
    +------+ : : Higher
    addresses

    (b) Reading in a word

    Figure 2.4 Reading bytes and words from 8088 memory

    Now for the 8086. The amount of information it transfers to, or
    from, memory at one time is always 16 bits. In the case of byte
    instructions, only eight of those bits are used, and the other
    eight are ignored. The 16 bits are always the contents of two
    consecutive bytes in memory, starting with a byte at an even
    address. That means that a word instruction that reads, or
    writes, a word starting at an even address can perform its
    function with one memory access. However, word instructions for
    words starting at odd addresses must do more work; they must do
    two memory accesses to two consecutive even-address words,
    ignore the unwanted half of each, and do some byte juggling with
    the remaining halves. Examples of the various byte and word
    reads are shown in Figure 2.5.


    8088 Memory
    +------+ : : Lower addresses
    | | <---- Byte being read ---- | // | Even address
    | | <---- Byte ignored ------- | | Odd address
    +------+ : : Higher addresses

    (a) Reading in even-addressed byte


    8088 Memory
    +------+ : : Lower addresses
    | | <---- Byte ignored ------- | | Even address
    | | <---- Byte being read ---- | // | Odd address
    +------+ : : Higher addresses

    (b) Reading in odd-addressed byte


    8088 Memory
    +------+ : : Lower addresses
    | | <---- Word being read ---- | // | Even address
    | | <---- Word being read ---- | // | Odd address
    +------+ : : Higher addresses

    (c) Reading in even-addressed word


    8088 Memory
    +------+ : : Lower addresses
    | | <----- Byte ignored ------ | |
    | | <--- 1st byte of word ---- | // | Even address
    | | <--- 2nd byte of word ---- | // | Odd address
    | | <----- Byte ignored ------ | |
    +------+ : : Higher addresses

    (d) Reading in odd-addressed word requires two memory accesses

    Figure 2.5 Reading bytes and words from 8086 memory

    The program in the 8086 (or 8088) is oblivious to all of these
    memory-accessing contortions; an instruction merely requests the
    accessing (reading or writing) of a particular byte or word, and
    the processor does whatever is necessary to perform such an
    access.


    EOF



  9. Re: Intel 8086 opcodes

    Hello, Steve!

    Re-re-(etc.)reading the bloody book, here is what I found about
    the S field involved with "signed byte".

    Notice the following sentence: "This is particularly true of
    immediate operands used with addition, subtraction, and
    comparison instructions; it is less true of immediate operands
    used with logical instructions." So, with the exception that he
    does not mention "addition with carry" and "subtract with
    borrow", he confirms, indeed, that my "Imm5" line is correct...

    opc. | 000 | 001 | 010 | 011 | 100 | 101 | 110 | 111
    ------+-----+-----+-----+-----+-----+-----+-----+-----
    Immed | ADD | OR | ADC | SBB | AND | SUB | XOR | CMP
    ------+-----+-----+-----+-----+-----+-----+-----+-----
    Imm5 | ADD | --- | ADC | SBB | --- | SUB | --- | CMP

    It looks like I will, in the end, be obliged to keep the 83
    opcode in ASM-86.

    I particularly enjoyed the sentence: "Note that one byte is
    eliminated by having the S field." I wonder how many
    assemblers/compilers were aware of those 5 instructions, and
    used them? The 8086 CPU instruction set really seems to have
    been designed by newby electronics engineers for compilers, with
    a total disrespect for the instruction set of the 8080, which
    has stood the test of time (The 2 Mars rovers (still working
    after 3 years on Mars!) use 8080 CPUs... 30+ years later!)


    Yours Sincerely,
    Mr Emmanuel Roche


    Since two-operand instructions have only one W field, either
    both operands must be 8 bits, or both must be 16 bits. However,
    immediate operands are frequently small numbers that don't
    require 16 bits. This is particularly true of immediate operands
    used with addition, subtraction, and comparison instructions; it
    is less true of immediate operands used with logical
    instructions. It follows that we could reduce the size of
    immediate-operand instructions if we did not have to use 16 bits
    to house small numbers. To accomplish this, some of the
    immediate-operand instructions (additions, subtractions, and
    comparisons) contain an S field (S means Sign-extend). This
    field only has significance for 16-bit operands (W = 1), and
    signifies whether all 16 bits of the immediate operand are
    contained in the instruction (S = 0), or whether only the 8
    least significant bits are contained in the instruction and must
    be sign-extended to form the 16-bit operand (S = 1). This form
    is illustrated in Figure 2.24.

    +--------+---+---+ +-----+----+-----+ +------+ +---------------------+
    | opcode | S | W | | MOD |opc.| R/M | | data | | data if S, W = 0, 1 |
    +--------+---+---+ +-----+----+-----+ +------+ +---------------------+

    Figure 2.24 Immediate-operand instruction containing an S
    field

    Figure 2.25 shows an example of such an instruction. In this
    example, the value 0000 0000 0000 1111 is added to the contents
    of a word in memory, and the result placed back into the memory
    word. The memory word is in the data segment at the offset
    contained in DI. Note that one byte is eliminated by having the
    S field.

    opcode S W MOD opcode R/M data
    +-------------+---+---+ +-----+-------+-------+ +-----------------+
    | 1 0 0 0 0 0 | 1 | 1 | | 0 0 | 0 0 0 | 1 1 1 | | 0 0 0 0 1 1 1 1 |
    +-------------+-+-+-+-+ +-+---+-------+-------+ +-----------------+
    ADD | | | ADD DI
    | | +--> memory
    | +--> word
    +--> sign extend

    Figure 2.25 Example of immediate-operand instruction
    containing an S field


    EOF



  10. Re: Intel 8086 opcodes

    - "8086 Instruction Set: The End?"

    Last evening, I wanted to know if I was really understanding
    clearly the instruction set of the Intel 8086 CPU. (The only way
    I know to check that you know a subject is to program a
    computer, since it finds so easily all the errors in your
    reasoning. Unfortunately, officially, this is not a subject to
    be taught. Instead, schools and Universities are filled with
    philosophers/sophists, who are talking and talking and
    talking...) (As you probably understood, I prefer "hard"
    Sciences.) So, I modified an old (8080) table-driven
    "disassembler" (I prefer to call it a Lister, since it produces
    an output as similar to an LST file as possible, from a CMD
    file).

    Testing it systematically against my I8086.A86 file, modeled
    after the official Intel "Machine Instruction Decoding Guide", I
    checked opcode after opcode.

    Since the end of the opcodes was arriving, I decided to
    continue, despite the very, very early hours of the next
    morning...

    It is then that I noticed the following patterns:

    02C0 F606111112 R test mem_8,12h
    ; F6 -- mod 001 r/m -- not used
    02C5 F6161111 R not mem_8
    02C9 F61E1111 R neg mem_8
    02CD F6261111 R mul mem_8
    02D1 F62E1111 R imul mem_8
    02D5 F6361111 R div mem_8
    02D9 F63E1111 R idiv mem_8

    02DD F70622225634 R test mem_16,3456h
    ; F7 -- mod 001 r/m -- not used
    02E3 F7162222 R not mem_16
    02E7 F71E2222 R neg mem_16
    02EB F7262222 R mul mem_16
    02EF F72E2222 R imul mem_16
    02F3 F7362222 R div mem_16
    02F7 F73E2222 R idiv mem_16

    0309 FF062222 R inc mem_16
    030D FF0E2222 R dec mem_16
    0311 FFD0 call ax
    0313 FF162222 R call mem_16
    0317 FFE0 jmp ax
    0319 FF262222 R jmp mem_16
    031D FF362222 R push mem_16
    ; FF -- mod 111 r/m -- not used

    In case you have not yet understood, those opcodes (F6, F7, and
    FF) have VARYING lengths...

    In the case of F6, only the first opcode is 5 bytes long: all
    the others are 4 bytes long.

    And, of course, my Lister is table-driven, has dozen of loops,
    all based upon the data in the initial table... which is
    expecting that opcodes have a fixed length (number of bytes)!

    So, those 3 opcodes break the logic of a program which has run
    without any problem since the Intel 8080 CPU was introduced in
    1973...

    Despair!


    Yours Sincerely,
    Mr Emmanuel Roche


    EOF



  11. Re: Intel 8086 opcodes

    roche182@laposte.net wrote:
    > Hello, Glen!
    >
    > Back home, here is what I found about the 8086/8088 difference
    > (I mistook "I/O" for "memory".)


    As far as I know, the difference between "memory" and I/O is
    the value of the M/IO line.

    > (By the way, when re-(etc.)reading the book, I found somewhere
    > that "primary opcode" are usually coded on 5 bits, and
    > "secondary opcodes" are coded on 7 bits (in the "primary
    > opcode") and 3 bits (between MOD and R/M). So simple, isn't it?)


    > The 8086, as well as the 8088, has some instructions that access
    > (read or write) bytes, and other instructions that access words.
    > Now, here comes the difference between the two processors. Let
    > us consider the 8088 first. The amount of information that the
    > 8088 transfers to, or from, memory at one time is always 8 bits.


    That makes it a little easier to design into systems, the reason
    that IBM chose it over the 8086 for the original IBM PC.

    (snip)

    > Now for the 8086. The amount of information it transfers to, or
    > from, memory at one time is always 16 bits. In the case of byte
    > instructions, only eight of those bits are used, and the other
    > eight are ignored.


    This isn't true on writes, and I don't believe for reads either.
    The HBE and A0 lines are used to select which half of the word
    is actually used. The 8086 is little-endian, so the low byte
    is at the even address. A0 is low for either word or byte
    access to an even address, and enables access to that byte.
    HBE is low for word access and odd byte access, enables
    access to that byte.

    (snip)

    > However, word instructions for
    > words starting at odd addresses must do more work; they must do
    > two memory accesses to two consecutive even-address words,
    > ignore the unwanted half of each, and do some byte juggling with
    > the remaining halves.


    For memory, you can return the whole word on read. For write,
    only the appropriate byte should be changed. I/O should
    use A0 and HBE on read.

    -- glen


  12. Re: Intel 8086 opcodes

    On Fri, 14 Sep 2007 00:15:48 -0800, glen herrmannsfeldt
    wrote:

    >no.spam@no.uce.bellatlantic.net wrote:
    >
    >> On Thu, 13 Sep 2007 02:26:00 -0800, glen herrmannsfeldt

    >
    >(snip regarding 8086 ESC)
    >
    >>>If I (remember,understand) right, the 8086 fetches one byte from
    >>>the target address. It doesn't modify the register indicated, but
    >>>does it ever fetch two bytes? I believe an 8088 will only fetch
    >>>one, as will an 8086 with an odd address. In the case of an
    >>>even address, does the 8086 fetch the whole word, even when only
    >>>one byte is needed? Does a load of al from an even memory
    >>>address do a 16 bit fetch or an 8 bit fetch?

    >
    >> If memory is right the 86 fetches three and the 88 only one.

    >
    >I am pretty sure it is only one cycle, and I believe one
    >byte even on the 8086. I am a little unsure in general if the
    >8086 guarantees to keep HBE high on an even byte read cycle.
    >
    >It is much more important to get right on a write cycle!
    >
    >> However what has been forgotton is the 8089 IOP also hasan interacting
    >> mechanism like a NDP.

    >
    >I actually have an 8089, though nothing to use it on.


    I have a few of them, nasty things they are.

    Allison

    >
    >-- glen



  13. Re: RISC vs CISC Re: Intel 8086 opcodes

    On Sep 3, 10:02 am, no.s...@no.uce.bellatlantic.net wrote:
    > On Mon, 3 Sep 2007 15:01:40 GMT, B'ichela
    > wrote:
    >
    > >In article <1188809693.591491.159...@d55g2000hsg.googlegroups. com>, roche...@laposte.net wrote:
    > >> 82OPCODE.WS4 "How to produce 82 opcodes with ASM-86"

    >
    > >Just a quick question. of the Major processors used in Home PCs from
    > >the 4004,

    >
    > 4004 never made it as PC cpu way to small (4bit data path).
    >
    > 8008 start of teh revolution at 8bits but still limited. NOT RISC.
    >
    > 8080,8086 (I doubt this one) NOT RISC by any stretch.
    >
    >

    ---snip---
    Hi
    I thought I'd add a little here. Current day x86 processors use RISC
    engines
    internally. Transmeta even took x86 instructions and created RISC
    instructions
    externally.
    With a wide memory bandwidth, such as many minis and main frames had
    in
    the past, RISC makes a lot of sense. It has been shown to be most
    effective
    at getting things done.
    This makes sense for a $100K machine. It doesn't make sense for a
    $1.5K
    machine. In order to make better use of memory bandwidth, the
    compaction
    of CISC like instructions makes better sense. Once in the processor,
    these
    can be expanded to RISC like operation in an internal cache.
    As we move into the future, we'll see the memory bottle neck issue
    even
    move into the larger machines.
    I'm not saying that the x86 set is the best useage of memory
    bandwidth
    but it is better than most RISC instruction sets.
    A next generation processor would have to consider that effective use
    of memory bandwidth is much more important than compiler simplicity.
    More complicated CISC processors will continue to move ahead of
    external RISC machines, even though the internal engine might still be
    RISC in nature.
    This is a simple problem of the speed increase of internal processing
    exceding the speed of wires.
    Dwight


  14. Re: RISC vs CISC Re: Intel 8086 opcodes

    dkelvey@hotmail.com wrote:
    [...]
    > More complicated CISC processors will continue to move ahead of
    > external RISC machines, even though the internal engine might still be
    > RISC in nature.


    Actually, the IA32 architecture is known for having lousy code density --- ARM
    is better than it, and ARM Thumb is better than ARM, and the M-Core (a
    Motorola Thumb rip-off) is even better than Thumb. All three processors are
    about as RISC as they get.

    (Comparing identical builds of gcc's cc1 internal executable, the ARM version
    has a code segment size of 0x0037857c; the IA32 version is 0x0041c0d8.
    Unfortunately I don't have a Thumb or M-Core version handy, but Thumb
    typically gains 30% over ARM.)

    It's interesting that one of the least code dense RISC processors is the
    PowerPC --- which also has one of the least RISC instruction sets around...

    --
    ┌── dg*cowlark.com ─── http://www.cowlark.com ──────────────── ──

    │ "There does not now, nor will there ever, exist a programming language in
    │ which it is the least bit hard to write bad programs." --- Flon's Axiom

  15. Re: Intel 8086 opcodes

    After quite a long session, I finally have something that seems
    to work. Before publishing its source code, here you will find a
    sample session, using the official "Machine Instruction Decoding
    Guide" as a template. However, of course, this does not contain
    all the possible combinations of the opcodes. So, it is quite
    probable (given the complexity of the 8086 instruction set) that
    some combinations of opcodes could produce erroneous values. You
    have the week-end to check the following.

    (I wanted to remove any "WORD" and "BYTE" (PTR) display but,
    then, some mnemonics would be redundant, and it would not be
    possible, at a glance, to know which particular form it is. I
    amm thinking, in particular, to the pair of INC/DEC mnemonics...
    Also, the [] helps to distinguish between opcodes 03 and 05.
    Your comments on the syntax are welcomed. Example: how do you
    distinguish the source and destination operands when both are to
    be stored in 16-bit registers, but their values fit in a byte?
    Do you need to add "WORD PTR" to both operands?)


    Yours Sincerely,
    Mr Emmanuel Roche


    0000| 00 06 11 11 ADD [1111], AL ; ....
    0004| 01 06 22 22 ADD [2222], AX ; ..""
    0008| 02 06 11 11 ADD AL, [1111] ; ....
    000C| 03 06 22 22 ADD AX, [2222] ; ..""
    0010| 04 12 ADD AL, 12 ; ..
    0012| 05 56 34 ADD AX, 3456 ; .V4
    0015| 06 PUSH ES ; .
    0016| 07 POP ES ; .
    0017| 08 06 11 11 OR [1111], AL ; ....
    001B| 09 06 22 22 OR [2222], AX ; ..""
    001F| 0A 06 11 11 OR AL, [1111] ; ....
    0023| 0B 06 22 22 OR AX, [2222] ; ..""
    0027| 0C 12 OR AL, 12 ; ..
    0029| 0D 56 34 OR AX, 3456 ; .V4
    002C| 0E PUSH CS ; .
    002D| 10 06 11 11 ADC [1111], AL ; ....
    0031| 11 06 22 22 ADC [2222], AX ; ..""
    0035| 12 06 11 11 ADC AL, [1111] ; ....
    0039| 13 06 22 22 ADC AX, [2222] ; ..""
    003D| 14 12 ADC AL, 12 ; ..
    003F| 15 56 34 ADC AX, 3456 ; .V4
    0042| 16 PUSH SS ; .
    0043| 17 POP SS ; .
    0044| 18 06 11 11 SBB [1111], AL ; ....
    0048| 19 06 22 22 SBB [2222], AX ; ..""
    004C| 1A 06 11 11 SBB AL, [1111] ; ....
    0050| 1B 06 22 22 SBB AX, [2222] ; ..""
    0054| 1C 12 SBB AL, 12 ; ..
    0056| 1D 56 34 SBB AX, 3456 ; .V4
    0059| 1E PUSH DS ; .
    005A| 1F POP DS ; .
    005B| 20 06 11 11 AND [1111], AL ; ...
    005F| 21 06 22 22 AND [2222], AX ; !.""
    0063| 22 06 11 11 AND AL, [1111] ; "...
    0067| 23 06 22 22 AND AX, [2222] ; #.""
    006B| 24 12 AND AL, 12 ; $.
    006D| 25 56 34 AND AX, [3456] ; %V4
    0070| 26 ES: ; &
    0071| 00 06 00 00 ADD [0000], AL ; ....
    0075| 27 DAA ; '
    0076| 28 06 11 11 SUB [1111], AL ; (...
    007A| 29 06 22 22 SUB [2222], AX ; ).""
    007E| 2A 06 11 11 SUB AL, [1111] ; *...
    0082| 2B 06 22 22 SUB AX, [2222] ; +.""
    0086| 2C 12 SUB AL, 12 ; ,.
    0088| 2D 56 34 SUB AX, 3456 ; -V4
    008B| 2E CS: ; .
    008C| 00 06 00 00 ADD [0000], AL ; ....
    0090| 2F DAS ; /
    0091| 30 06 11 11 XOR [1111], AL ; 0...
    0095| 31 06 22 22 XOR [2222], AX ; 1.""
    0099| 32 06 11 11 XOR AL, [1111] ; 2...
    009D| 33 06 22 22 XOR AX, [2222] ; 3.""
    00A1| 34 12 XOR AL, 12 ; 4.
    00A3| 35 56 34 XOR AX, 3456 ; 5V4
    00A6| 36 SS: ; 6
    00A7| 00 06 00 00 ADD [0000], AL ; ....
    00AB| 37 AAA ; 7
    00AC| 38 06 11 11 CMP [1111], AL ; 8...
    00B0| 39 06 22 22 CMP [2222], AX ; 9.""
    00B4| 3A 06 11 11 CMP AL, [1111] ; :...
    00B8| 3B 06 22 22 CMP AX, [2222] ; ;.""
    00BC| 3C 12 CMP AL, 12 ; <.
    00BE| 3D 56 34 CMP AX, 3456 ; =V4
    00C1| 3E DS: ; >
    00C2| 00 06 00 00 ADD [0000], AL ; ....
    00C6| 3F AAS ; ?
    00C7| 40 INC AX ; @
    00C8| 41 INC CX ; A
    00C9| 42 INC DX ; B
    00CA| 43 INC BX ; C
    00CB| 44 INC SP ; D
    00CC| 45 INC BP ; E
    00CD| 46 INC SI ; F
    00CE| 47 INC DI ; G
    00CF| 48 DEC AX ; H
    00D0| 49 DEC CX ; I
    00D1| 4A DEC DX ; J
    00D2| 4B DEC BX ; K
    00D3| 4C DEC SP ; L
    00D4| 4D DEC BP ; M
    00D5| 4E DEC SI ; N
    00D6| 4F DEC DI ; O
    00D7| 50 PUSH AX ; P
    00D8| 51 PUSH CX ; Q
    00D9| 52 PUSH DX ; R
    00DA| 53 PUSH BX ; S
    00DB| 54 PUSH SP ; T
    00DC| 55 PUSH BP ; U
    00DD| 56 PUSH SI ; V
    00DE| 57 PUSH DI ; W
    00DF| 58 POP AX ; X
    00E0| 59 POP CX ; Y
    00E1| 5A POP DX ; Z
    00E2| 5B POP BX ; [
    00E3| 5C POP SP ; \
    00E4| 5D POP BP ; ]
    00E5| 5E POP SI ; ^
    00E6| 5F POP DI ; _
    00E7| 70 FE JO 0167 ; p.
    00E9| 71 FC JNO 0167 ; q.
    00EB| 72 FA JB 0167 ; r.
    00ED| 72 F8 JB 0167 ; r.
    00EF| 72 F6 JB 0167 ; r.
    00F1| 73 F4 JNB 0167 ; s.
    00F3| 73 F2 JNB 0167 ; s.
    00F5| 73 F0 JNB 0167 ; s.
    00F7| 74 EE JZ 0167 ; t.
    00F9| 74 EC JZ 0167 ; t.
    00FB| 75 EA JNZ 0167 ; u.
    00FD| 75 E8 JNZ 0167 ; u.
    00FF| 76 E6 JBE 0167 ; v.
    0101| 76 E4 JBE 0167 ; v.
    0103| 77 E2 JA 0167 ; w.
    0105| 77 E0 JA 0167 ; w.
    0107| 78 DE JS 0167 ; x.
    0109| 79 DC JNS 0167 ; y.
    010B| 7A DA JP 0167 ; z.
    010D| 7A D8 JP 0167 ; z.
    010F| 7B D6 JNP 0167 ; {.
    0111| 7B D4 JNP 0167 ; {.
    0113| 7C D2 JL 0167 ; |.
    0115| 7C D0 JL 0167 ; |.
    0117| 7D CE JNL 0167 ; }.
    0119| 7D CC JNL 0167 ; }.
    011B| 7E CA JLE 0167 ; ~.
    011D| 7E C8 JLE 0167 ; ~.
    011F| 7F C6 JG 0167 ; ..
    0121| 7F C4 JG 0167 ; ..
    0123| 80 06 11 11 12 ADD [1111], 12 ; .....
    0128| 80 0E 11 11 12 OR [1111], 12 ; .....
    012D| 80 16 11 11 12 ADC [1111], 12 ; .....
    0132| 80 1E 11 11 12 SBB [1111], 12 ; .....
    0137| 80 26 11 11 12 AND [1111], 12 ; .&...
    013C| 80 2E 11 11 12 SUB [1111], 12 ; .....
    0141| 80 36 11 11 12 XOR [1111], 12 ; .6...
    0146| 80 3E 11 11 12 CMP [1111], 12 ; .>...
    014B| 81 06 22 22 56 34 ADD [2222], 3456 ; ..""V4
    0151| 81 0E 22 22 56 34 OR [2222], 3456 ; ..""V4
    0157| 81 16 22 22 56 34 ADC [2222], 3456 ; ..""V4
    015D| 81 1E 22 22 56 34 SBB [2222], 3456 ; ..""V4
    0163| 81 26 22 22 56 34 AND [2222], 3456 ; .&""V4
    0169| 81 2E 22 22 56 34 SUB [2222], 3456 ; ..""V4
    016F| 81 36 22 22 56 34 XOR [2222], 3456 ; .6""V4
    0175| 81 3E 22 22 56 34 CMP [2222], 3456 ; .>""V4
    017B| 82 C0 12 ADD AL, 12 ; ...
    017E| 82 D0 12 ADC AL, 12 ; ...
    0181| 82 D8 12 SBB AL, 12 ; ...
    0184| 82 E8 12 SUB AL, 12 ; ...
    0187| 82 F8 12 CMP AL, 12 ; ...
    018A| 83 C5 12 ADD BP, 12 ; ...
    018D| 83 D5 12 ADC BP, 12 ; ...
    0190| 83 DD 12 SBB BP, 12 ; ...
    0193| 83 ED 12 SUB BP, 12 ; ...
    0196| 83 FD 12 CMP BP, 12 ; ...
    0199| 84 06 11 11 TEST [1111], AL ; ....
    019D| 85 06 22 22 TEST [2222], AX ; ..""
    01A1| 86 06 11 11 XCHG AL, [1111] ; ....
    01A5| 87 06 22 22 XCHG AX, [2222] ; ..""
    01A9| 88 46 00 MOV [BP], AL ; .F.
    01AC| 89 46 00 MOV [BP], AX ; .F.
    01AF| 8A C1 MOV AL, CL ; ..
    01B1| 8B C1 MOV AX, CX ; ..
    01B3| 8C 1E 22 22 MOV [2222], DS ; ..""
    01B7| 8D 06 22 22 LEA AX, [2222] ; ..""
    01BB| 8E 1E 22 22 MOV DS, [2222] ; ..""
    01BF| 8F 06 22 22 POP [2222] ; ..""
    01C3| 90 NOP ; .
    01C4| 91 XCHG AX, CX ; .
    01C5| 92 XCHG AX, DX ; .
    01C6| 93 XCHG AX, BX ; .
    01C7| 94 XCHG AX, SP ; .
    01C8| 95 XCHG AX, BP ; .
    01C9| 96 XCHG AX, SI ; .
    01CA| 97 XCHG AX, DI ; .
    01CB| 98 CBW ; .
    01CC| 99 CWD ; .
    01CD| 9A 00 00 00 00 CALLF 0000:0000 ; .....
    01D2| 9B WAIT ; .
    01D3| 9C PUSHF ; .
    01D4| 9D POPF ; .
    01D5| 9E SAHF ; .
    01D6| 9F LAHF ; .
    01D7| A0 11 11 MOV AL, [1111] ; ...
    01DA| A1 22 22 MOV AX, [2222] ; .""
    01DD| A2 11 11 MOV [1111], AL ; ...
    01E0| A3 22 22 MOV [2222], AX ; .""
    01E3| A4 MOVSB ; .
    01E4| A5 MOVSW ; .
    01E5| A6 CMPSB ; .
    01E6| A7 CMPSW ; .
    01E7| A8 12 TEST AL, 12 ; ..
    01E9| A9 56 34 TEST AX, 3456 ; .V4
    01EC| AA STOSB ; .
    01ED| AB STOSW ; .
    01EE| AC LODSB ; .
    01EF| AD LODSW ; .
    01F0| AE SCASB ; .
    01F1| AF SCASW ; .
    01F2| B0 12 MOV AL, 12 ; ..
    01F4| B1 12 MOV CL, 12 ; ..
    01F6| B2 12 MOV DL, 12 ; ..
    01F8| B3 12 MOV BL, 12 ; ..
    01FA| B4 12 MOV AH, 12 ; ..
    01FC| B5 12 MOV CH, 12 ; ..
    01FE| B6 12 MOV DH, 12 ; ..
    0200| B7 12 MOV BH, 12 ; ..
    0202| B8 56 34 MOV AX, 3456 ; .V4
    0205| B9 56 34 MOV CX, 3456 ; .V4
    0208| BA 56 34 MOV DX, 3456 ; .V4
    020B| BB 56 34 MOV BX, 3456 ; .V4
    020E| BC 56 34 MOV SP, 3456 ; .V4
    0211| BD 56 34 MOV BP, 3456 ; .V4
    0214| BE 56 34 MOV SI, 3456 ; .V4
    0217| BF 56 34 MOV DI, 3456 ; .V4
    021A| C2 56 34 RET 3456 ; .V4

    021D| C3 RET ; .

    021E| C4 46 06 LES AX, 6[BP] ; .F.
    0221| C5 46 06 LDS AX, 6[BP] ; .F.
    0224| C6 06 11 11 12 MOV [1111], 12 ; .....
    0229| C7 06 22 22 56 34 MOV [2222], 3456 ; ..""V4
    022F| CA 56 34 RETF 3456 ; .V4

    0232| CB RETF ; .

    0233| CC INT 3 ; .
    0234| CD 12 INT 12 ; ..
    0236| CE INTO ; .
    0237| CF IRET ; .

    0238| D0 C0 ROL AL, 1 ; ..
    023A| D0 C9 ROR CL, 1 ; ..
    023C| D0 D2 RCL DL, 1 ; ..
    023E| D0 DB RCR BL, 1 ; ..
    0240| D0 E4 SHL AH, 1 ; ..
    0242| D0 E5 SHL CH, 1 ; ..
    0244| D0 EE SHR DH, 1 ; ..
    0246| D0 FF SAR BH, 1 ; ..
    0248| D1 C0 ROL AX, 1 ; ..
    024A| D1 C9 ROR CX, 1 ; ..
    024C| D1 D2 RCL DX, 1 ; ..
    024E| D1 DB RCR BX, 1 ; ..
    0250| D1 E0 SHL AX, 1 ; ..
    0252| D1 E1 SHL CX, 1 ; ..
    0254| D1 EA SHR DX, 1 ; ..
    0256| D1 FB SAR BX, 1 ; ..
    0258| D2 C0 ROL AL, CL ; ..
    025A| D2 C9 ROR CL, CL ; ..
    025C| D2 D2 RCL DL, CL ; ..
    025E| D2 DB RCR BL, CL ; ..
    0260| D2 E4 SHL AH, CL ; ..
    0262| D2 E5 SHL CH, CL ; ..
    0264| D2 EE SHR DH, CL ; ..
    0266| D2 FF SAR BH, CL ; ..
    0268| D3 C0 ROL AX, CL ; ..
    026A| D3 C9 ROR CX, CL ; ..
    026C| D3 D2 RCL DX, CL ; ..
    026E| D3 DB RCR BX, CL ; ..
    0270| D3 E0 SHL AX, CL ; ..
    0272| D3 E1 SHL CX, CL ; ..
    0274| D3 EA SHR DX, CL ; ..
    0276| D3 FB SAR BX, CL ; ..
    0278| D4 0A AAM ; ..
    027A| D5 0A AAD ; ..
    027C| D7 XLAT ; .
    027D| D8 C0 ESC 0, AL ; ..
    027F| D9 C1 ESC 8, CL ; ..
    0281| DA C2 ESC 16, DL ; ..
    0283| DB C3 ESC 24, BL ; ..
    0285| DC C4 ESC 32, AH ; ..
    0287| DD C5 ESC 40, CH ; ..
    0289| DE C6 ESC 48, DH ; ..
    028B| DF C7 ESC 56, BH ; ..
    028D| E0 FE LOOPNE 030D ; ..
    028F| E0 FC LOOPNE 030D ; ..
    0291| E1 FA LOOPE 030D ; ..
    0293| E1 F8 LOOPE 030D ; ..
    0295| E2 F6 LOOP 030D ; ..
    0297| E3 F4 JCXZ 030D ; ..
    0299| E4 12 IN AL, 12 ; ..
    029B| E5 12 IN AX, 12 ; ..
    029D| E6 12 OUT 12, AL ; ..
    029F| E7 12 OUT 12, AX ; ..
    02A1| E8 5C FD CALL FD5C ; .\.
    02A4| E9 59 FD JMP FD59 ; .Y.

    02A7| EA 00 00 00 00 JMPF 0000:0000 ; .....

    02AC| EB DF JMPS 030D ; ..

    02AE| EC IN AL, DX ; .
    02AF| ED IN AX, DX ; .
    02B0| EE OUT DX, AL ; .
    02B1| EF OUT DX, AX ; .
    02B2| F0 90 LOCK 90 ; ..
    02B4| F2 90 REPNE 90 ; ..
    02B6| F2 90 REPNE 90 ; ..
    02B8| F3 90 REP 90 ; ..
    02BA| F3 90 REP 90 ; ..
    02BC| F3 90 REP 90 ; ..
    02BE| F4 HLT ; .
    02BF| F5 CMC ; .
    02C0| F6 06 11 11 12 TEST [1111], 12 ; ....
    02C5| F6 16 11 11 NOT [1111] ; ....
    02C9| F6 1E 11 11 NEG [1111] ; ....
    02CD| F6 26 11 11 MUL [1111] ; .&..
    02D1| F6 2E 11 11 IMUL [1111] ; ....
    02D5| F6 36 11 11 DIV [1111] ; .6..
    02D9| F6 3E 11 11 IDIV [1111] ; .>..
    02DD| F7 06 22 22 56 34 TEST [2222], 3456 ; ..""
    02E3| F7 16 22 22 NOT [2222] ; ..""
    02E7| F7 1E 22 22 NEG [2222] ; ..""
    02EB| F7 26 22 22 MUL [2222] ; .&""
    02EF| F7 2E 22 22 IMUL [2222] ; ..""
    02F3| F7 36 22 22 DIV [2222] ; .6""
    02F7| F7 3E 22 22 IDIV [2222] ; .>""
    02FB| F8 CLC ; .
    02FC| F9 STC ; .
    02FD| FA CLI ; .
    02FE| FB STI ; .
    02FF| FC CLD ; .
    0300| FD STD ; .
    0301| FE 06 11 11 INC [1111] ; ....
    0305| FE 0E 11 11 DEC [1111] ; ....
    0309| FF 06 22 22 INC [2222] ; ..""
    030D| FF 0E 22 22 DEC [2222] ; ..""
    0311| FF D0 CALL AX ; ..
    0313| FF 16 22 22 CALL [2222] ; ..""
    0317| FF E0 JMP AX ; ..
    0319| FF 26 22 22 JMP [2222] ; .&""
    031D| FF 36 22 22 PUSH [2222] ; .6""


    EOF



  16. Re: Intel 8086 opcodes

    On Sep 14, 6:26 am, roche...@laposte.net wrote:
    > - "8086 Instruction Set: The End?"
    >

    Had you considered looking at the decode effort though using Octals?

    for example...

    01 ;; ok for nasm?
    02 ;; -f bin -l tst_fsgs.lst -o tst_fsgs.bin tst_fsgs.nsm
    03
    04 00000000 8CC0 mov ax,es ;; Q214 Q300
    05 00000002 8CC8 mov ax,cs ;; Q214 Q310
    06 00000004 8CD0 mov ax,ss ;; Q214 Q320
    07 00000006 8CD8 mov ax,ds ;; Q214 Q330
    08 00000008 8CE0 mov ax,fs ;; Q214 Q340 ;;note continued logic
    09 0000000A 8CE8 mov ax,gs ;; Q214 Q350 ;; for FS and GS
    10
    11 ;;eof
    12
    Note that 8Ch == Q214 octal which represents MOV Reg16|Mem16,SegmReg

    With the later processor instruction extention to handle FS & GS, the
    continued logic shows Octal as making simple sense where each byte
    forms 3 octal digits, or 9bits where the first octal digit's first bit
    is silent. i.e.
    81h := 1000 0001b := x10 000 001b := Q201

    I haven't gone thru the opcode table to see how the octal scheme
    fares, but I am curious to do so.

    Comments?

    Steve

    > Last evening, I wanted to know if I was really understanding
    > clearly the instruction set of the Intel 8086 CPU. (The only way
    > I know to check that you know a subject is to program a
    > computer, since it finds so easily all the errors in your
    > reasoning. Unfortunately, officially, this is not a subject to
    > be taught. Instead, schools and Universities are filled with
    > philosophers/sophists, who are talking and talking and
    > talking...) (As you probably understood, I prefer "hard"
    > Sciences.) So, I modified an old (8080) table-driven
    > "disassembler" (I prefer to call it a Lister, since it produces
    > an output as similar to an LST file as possible, from a CMD
    > file).
    >
    > Testing it systematically against my I8086.A86 file, modeled
    > after the official Intel "Machine Instruction Decoding Guide", I
    > checked opcode after opcode.
    >
    > Since the end of the opcodes was arriving, I decided to
    > continue, despite the very, very early hours of the next
    > morning...
    >
    > It is then that I noticed the following patterns:
    >
    > 02C0 F606111112 R test mem_8,12h
    > ; F6 -- mod 001 r/m -- not used
    > 02C5 F6161111 R not mem_8
    > 02C9 F61E1111 R neg mem_8
    > 02CD F6261111 R mul mem_8
    > 02D1 F62E1111 R imul mem_8
    > 02D5 F6361111 R div mem_8
    > 02D9 F63E1111 R idiv mem_8
    >
    > 02DD F70622225634 R test mem_16,3456h
    > ; F7 -- mod 001 r/m -- not used
    > 02E3 F7162222 R not mem_16
    > 02E7 F71E2222 R neg mem_16
    > 02EB F7262222 R mul mem_16
    > 02EF F72E2222 R imul mem_16
    > 02F3 F7362222 R div mem_16
    > 02F7 F73E2222 R idiv mem_16
    >
    > 0309 FF062222 R inc mem_16
    > 030D FF0E2222 R dec mem_16
    > 0311 FFD0 call ax
    > 0313 FF162222 R call mem_16
    > 0317 FFE0 jmp ax
    > 0319 FF262222 R jmp mem_16
    > 031D FF362222 R push mem_16
    > ; FF -- mod 111 r/m -- not used
    >
    > In case you have not yet understood, those opcodes (F6, F7, and
    > FF) have VARYING lengths...
    >
    > In the case of F6, only the first opcode is 5 bytes long: all
    > the others are 4 bytes long.
    >
    > And, of course, my Lister is table-driven, has dozen of loops,
    > all based upon the data in the initial table... which is
    > expecting that opcodes have a fixed length (number of bytes)!
    >
    > So, those 3 opcodes break the logic of a program which has run
    > without any problem since the Intel 8080 CPU was introduced in
    > 1973...
    >
    > Despair!
    >
    > Yours Sincerely,
    > Mr Emmanuel Roche
    >
    > EOF




  17. Re: Intel 8086 opcodes

    Hello, Steve!

    > Had you considered looking at the decode effort though using Octals?
    > (...)
    > I haven't gone thru the opcode table to see how the octal scheme
    > fares, but I am curious to do so.


    > Comments?


    You bet!

    LIST8086 started as a simple modification of LIST8080.BAS, which is
    simply an array with 256 entries containing the mnemonics of the 8080
    CPU.

    (I did it this way 20 years ago because I wanted to be able to "play"
    with any mnemonic: I wrote LIST8080 to investigate using another
    "system language" syntax to replace the mnemonics of the 8080
    assembler.)

    All the "secondary opcodes" (the term used by one of the 4 authors of
    the 8086 CPU) are decoded thanks to a table containing 8 entries for
    each opcode. That is to say: I am obliged to use octal in their case,
    since they are octal-coded.

    However, after I finish to finally get this program to list all the
    known 8086 opcodes, I could then modify it to display the opcodes in
    octal, then decide if I rewrite it from scratch to use an octal jump
    table.

    Also, the table-driven version is much faster (on a 4-MHz Z-80) than a
    version which was decoding each opcode, then deciding what to do. Of
    course, now, with my 400-MHz system, speed is less important. But
    table-driven programs are also much simpler to debug, then...

    I suggest that we finish to debug the program first. As I mentioned
    several times, Americans are fond of starting another thread at the
    slightest problem, even before finishing the original job. As a
    result, they often finish doing nothing. Me, I prefer to work step by
    step. Only after having finished a step do I think about what to do
    next. The comp.os.cpm Newsgroup now contains about 30 BASIC programs
    that helped me settled various problems. Each time I wrote them, I had
    no idea how I was going to solve the problem. Writing the programs
    helped me to define more precisely the problem, and to find a
    solution. If I rewrite the program, it would not be the first time
    that, having finally understood fully the problem, I would rewrite the
    program to more efficiently solve the problem. This is what I like
    into programming: it is so much logical. Impossible to argue anything.


    Yours Sincerely,
    Mr Emmanuel Roche



  18. Re: Intel 8086 opcodes

    - "The 8086 Instruction Set: The Sequel"

    Well, well, well...

    I was expecting today to publish the source code of a program
    listing all the "legal" Intel 8086 opcodes and mnemonics.
    Unfortunately, I have made a handful of discoveries this week-
    end that need to be further investigated before deciding if the
    program is finally fit for publication.

    (I never had so much trouble understanding the opcodes of a
    computer. Intel really goofed mightily when they designed the
    8086 CPU instruction set.)

    Ok. Let us start. This time, I used the Intel "The 8086 Family
    User's Manual", October 1979, and particularly Table 4-13,
    "Machine Instruction Decoding Guide", pages 4-27 to 4-35, as my
    guide, checking systematically each opcode listed by my program
    in this table.

    It is then that I discovered another "feature" of the doc. You
    may remember that I demonstrated (in "82 Opcodes: A bug made in
    1978?") that the "secondary Opcode Space" table present in the
    Appendix of the book "The 8086 Primer" written by one of the
    authors of the 8086 CPU (and also present, a little bit
    differently, in Table 4-14) is erroneous?

    Well, I have found 3 other opcodes that are, obviously,
    "secondary opcodes", yet are not documented in both books...

    Consider the following:

    0282| 8F 06 22 22 POP [2222] ; ..""
    0286| 8F 08 22 22 --- [2222] ; ..""
    028A| 8F 10 22 22 --- [2222] ; ..""
    028E| 8F 18 22 22 --- [2222] ; ..""
    0292| 8F 20 22 22 --- [2222] ; . ""
    0296| 8F 28 22 22 --- [2222] ; .(""
    029A| 8F 30 22 22 --- [2222] ; .0""
    029E| 8F 38 22 22 --- [2222] ; .8""

    (Reference: Pages 4-31 and 4-32.)

    0305| C6 06 11 11 12 MOV BYTE [1111], 12 ; .....
    030A| C6 08 11 11 12 --- BYTE [1111], 12 ; .....
    030F| C6 10 11 11 12 --- BYTE [1111], 12 ; .....
    0314| C6 18 11 11 12 --- BYTE [1111], 12 ; .....
    0319| C6 20 11 11 12 --- BYTE [1111], 12 ; . ...
    031E| C6 28 11 11 12 --- BYTE [1111], 12 ; .(...
    0323| C6 30 11 11 12 --- BYTE [1111], 12 ; .0...
    0328| C6 38 11 11 12 --- BYTE [1111], 12 ; .8...
    032D| C7 06 22 22 56 34 MOV WORD [2222], 3456 ; ..""V4
    0333| C7 08 22 22 56 34 --- WORD [2222], 3456 ; ..""V4
    0339| C7 10 22 22 56 34 --- WORD [2222], 3456 ; ..""V4
    033F| C7 18 22 22 56 34 --- WORD [2222], 3456 ; ..""V4
    0345| C7 20 22 22 56 34 --- WORD [2222], 3456 ; . ""V4
    034B| C7 28 22 22 56 34 --- WORD [2222], 3456 ; .(""V4
    0351| C7 30 22 22 56 34 --- WORD [2222], 3456 ; .0""V4
    0357| C7 38 22 22 56 34 --- WORD [2222], 3456 ; .8""V4

    (Reference: Page 4-33.)

    Only solution: to update yet another time the "Secondary Opcode
    Space" table.

    opc. | 000 | 001 | 010 | 011 | 100 | 101 | 110 | 111
    ------+-----+-----+-----+-----+-----+-----+-----+-----
    Immed | ADD | OR | ADC | SBB | AND | SUB | XOR | CMP
    ------+-----+-----+-----+-----+-----+-----+-----+-----
    Imm5 | ADD | --- | ADC | SBB | --- | SUB | --- | CMP
    ------+-----+-----+-----+-----+-----+-----+-----+-----
    Grp 4 | POP | --- | --- | --- | --- | --- | --- | ---
    ------+-----+-----+-----+-----+-----+-----+-----+-----
    Grp 5 | MOV | --- | --- | --- | --- | --- | --- | ---
    ------+-----+-----+-----+-----+-----+-----+-----+-----
    Grp 6 | MOV | --- | --- | --- | --- | --- | --- | ---
    ------+-----+-----+-----+-----+-----+-----+-----+-----
    Shift | ROL | ROR | RCL | RCR | SHL*| SHR | --- | SAR (*=SAL)
    ------+-----+-----+-----+-----+-----+-----+-----+-----
    Grp 1 | TEST| --- | NOT | NEG | MUL | IMUL| DIV | IDIV
    ------+-----+-----+-----+-----+-----+-----+-----+-----
    Grp 2 | INC | DEC | CALL| CALL| JMP | JMP | PUSH| ---
    | | | id | L,id| id | L,id| |
    ------+-----+-----+-----+-----+-----+-----+-----+-----
    Grp 3 | INC | DEC | --- | --- | --- | --- | --- | ---
    ------+-----+-----+-----+-----+-----+-----+-----+-----

    (This was yet another bug in the official Intel doc.)

    Now, continuing my systematic checking, I arrived to opcodes C4
    and C5:

    02FF| C4 46 06 LES AX, 6[BP] ; .F.
    0302| C5 46 06 LDS AX, 6[BP] ; .F.

    In case you did not notice, there is a problem with the above
    lines. "The 8086 Family User's Guide" says Page 4-33 that they
    should be 4 bytes long. However, Page 2-59, it says: "Bytes: 2-
    4" which, as far as I understand English, means that they are
    variable in length, which should be 2 to 4 bytes long. Let us
    assume that this is an error, and try to find the information in
    another source.

    Address-Object Transfers
    ------------------------

    The address-object transfers are LEA (Load Effective Address),
    LDS (Load pointer into DS), and LES (Load pointer into ES).
    These instructions provide the programmer with some control over
    the addressing mechanism. The formats for these instructions are
    shown in Figure 3.10.

    +-----------------+ +-----+-----+-----+
    | 1 0 0 0 1 1 0 1 | | mod | reg | r/m |
    +-----------------+ +-----+-----+-----+
    LEA: load EA to register

    +-----------------+ +-----+-----+-----+
    | 1 1 0 0 0 1 0 1 | | mod | reg | r/m |
    +-----------------+ +-----+-----+-----+
    LDS: load pointer to DS

    +-----------------+ +-----+-----+-----+
    | 1 1 0 0 0 1 0 0 | | mod | reg | r/m |
    +-----------------+ +-----+-----+-----+
    LES: load pointer to ES

    Figure 3.10 Formats of address-object transfer instructions

    Note that, although these instructions use a MOD and an R/M
    field to specify one operand, and a REG field to specify the
    other operand, there is no D field to specify which operand is
    the source, and which is the destination. The D field is
    unnecessary, because the source operand of these instructions
    always comes from, or refer to, memory, and hence has to be
    specified by the MOD and R/M fields. The reason why the source
    operand must come from, or refer to, memory will become apparent
    as each of the address-object transfers is described.

    The LEA instruction provides access to the offset address of the
    source operand, as opposed to the value of the operand. Hence,
    this instruction would be meaningless if the source operand did
    not refer to memory. The effect of the instruction is to
    transfer the 16-bit offset address of the source operand to the
    16-bit register designated as the destination operand. This
    facility is useful for passing the offset address of a variable
    from one part of the program to another, so that the other part
    of the program can modify the value of the variable if it so
    desired. Objects that are passed between different parts of the
    program are called parameters, and the different parts of the
    program are called subroutines. For example, suppose one
    subroutine had the reponsibility for incrementing variables.
    Other parts of the program could call on this incrementing
    subroutine, and have it increment a specific variable. The
    offset address of the variable to be incremented could be passed
    as a parameter to the incrementing subroutine, by placing the
    offset address in a mutually agreed upon register, such as BX,
    prior to calling the incrementing subroutine. The LEA
    instruction is tailor-made to do just that. The REG field of the
    LEA instruction would designate the BX register (011), and the
    MOD and R/M fields would designate the offset address of the
    variable. The instruction would be executed prior to calling the
    subroutine. The subroutine could then access the variable by
    using the appropriate operand- address mode involving BX
    (MOD=00, R/M=111). Note that, if the value of the variable,
    instead of its offset, were passed to the incrementing
    subroutine, the subroutine would know the value, but would be
    unable to alter the variable.

    The LDS instruction transfers four consecutive bytes (32 bits)
    from a source operand to a pair of 16-bit destination registers.
    The source operand must be in memory. One destination register
    is the 16-bit destination operand specified by the REG field in
    the instruction; the other destination register is DS. The LES
    instruction is similar to LDS, except that the other destination
    register is ES, instead of DS. The actual data transferred is
    illustrated in Figure 3.11.

    | +-------+
    | | |
    Offset address | |
    as specified by | |
    MOD and R/M fields | | 16-bit register
    of instruction. | | specified by REG
    | | | field of instruction.
    | +-------+-+
    +-------------->| 1 F | | +---------+
    +-------+ +---> | 3 C 1 F |
    | 3 C | | +---------+
    +-------+-+
    | A 5 | | +---------+
    +-------+ +---> | 8 7 A 5 | DS or ES
    | 8 7 | | +---------+
    +-------+-+
    | |
    | |
    +-------+

    Figure 3.11 Data movement for LDS and LES instructions

    The LDS and LES instructions provide an efficient means for
    setting up the segment start address and offset address of a
    variable, so that the variable can be accessed by succeeding
    instructions. This combination of segment start address and
    offset address is called a pointer; the LDS (or LES) instruction
    transfers a pointer from memory into registers appropriate for
    the operand-addressing modes. For example, assume offset
    addresses 0F1C to 0F1F (four bytes) in the current data segment
    contain a pointer to a 1-byte variable as shown in Figure
    3.12(a).

    Current
    data segment
    +---------+ +-----+
    DS: | 8 0 0 0 +--+--> 80000 | |
    +---------+ | | |
    0F1C | |
    | | |
    | +-----+
    +--> 80F1C | C 8 |
    +-----+ Segment containing
    | 1 0 | variable being
    +-----+ pointed at.
    | B 0 | +-----+
    +-----+--+--> 14B00 | |
    | 1 4 | | | |
    +-----+ 10C8 | |
    | | | +-----+
    | | +--> 15BC8 | 3 F | One-
    byte
    | | +-----+
    variable.
    | | | |
    | | | |
    +-----+ +-----+

    (a) Memory containing a pointer to a variable

    The two-instruction sequence for loading the value of the
    variable in the AL register is shown in Figure 3.12(b).

    LSBits of MSBits of
    offset offset
    opcode MOD REG R/M address address
    +----------+ +----+-----+-----+ +----------+ +----------+
    | 11000101 | | 00 | 111 | 110 | | 00011100 | | 00001111 |
    +----------+ +-+--+-----+-+---+ +----------+ +----------+
    LDS \ BX / 1C 0F
    \ /
    Offset is in
    next two bytes.

    (i) Instruction that load pointer into registers DS and BX

    +--------+---+---+ +----+-----+-----+
    | 100010 | 1 | 0 | | 00 | 000 | 111 |
    +--------+-+-+---+ +-+--+-----+-----+
    MOV | byte | AL BX
    | +--> no displacement
    +--> to REG operand

    (ii) Instruction that use operand-addressing mode
    involving DS and BX to access variable being pointed at.

    Figure 3.12 Example of using LDS instruction

    - "The 8086 Primer, 2nd Edition"
    Stephen P. Morse
    Hayden Books, 1982

    Figure 3.12 settle the question. The LEA, LDS, and LES
    instructions all produce 4 bytes of opcode. The problem being
    that ASM-86 (and RASM-86) produces 3 bytes for the LDS and LES
    mnemonics (LEA produces 4 bytes). So, I am afraid that I have
    discovered a real genuine bug inside both assemblers.

    So, I added a pair of "codemacros" (a feature of ASM-86) to my
    test file, resulting in the following output from my program:

    02FF| C4 06 22 22 LES [2222] ; ..""
    0303| C5 06 22 22 LDS [2222] ; ..""

    Well! I was not expecting so much trouble, just to list the
    mnemonics of a program...

    Continuing, I finally arrived another time to the FF opcode...

    0463| FF 06 22 22 INC WORD [2222] ; ..""
    0467| FF 0E 22 22 DEC WORD [2222] ; ..""
    046B| FF D0 22 22 CALL WORD [2222] ; ..""
    046F| FF 16 22 22 CALL WORD [2222] ; ..""
    0473| FF E0 22 22 JMP WORD [2222] ; ..""
    0477| FF 26 22 22 JMP WORD [2222] ; .&""
    047B| FF 36 22 22 PUSH WORD [2222] ; .6""
    047F| FF 38 22 22 --- WORD [2222] ; .8""

    Maybe you remember my question: "How do you distinguish between
    opcodes FE and FF, since both have a pair of INC/DEC?" Well,
    using SID-86, I got:

    0443| FE 06 11 11 INC BYTE [1111] ; ....
    0447| FE 0E 11 11 DEC BYTE [1111] ; ....

    that is to say: this is yet another case where the 8086 CPU has
    instructions first for bytes, then for words. So, FE=BYTE, and
    FF=WORD. Hence the idea of displaying "WORD" in front of all the
    FF opcodes (the subroutine is then much simpler...).

    If we compare this output with an ASM-86 program generating the
    opcodes:

    0309 FF062222 R inc mem_16
    030D FF0E2222 R dec mem_16
    0311 FFD0 call ax
    0313 FF162222 R call mem_16
    0317 FFE0 jmp ax
    0319 FF262222 R jmp mem_16
    031D FF362222 R push mem_16
    ; FF -- mod 111 r/m -- not used

    we notice that both CALL and JMP to 16-bit register does not
    take a parameter, according to Digital Research. However, in the
    Intel book, we find that all the FF opcodes are 4 bytes long...
    This is the first problem.

    The second problem is the comments for both CALL and JMP. Each
    time, Intel writes that the first instance is "intrasegment",
    while the second one is "intersegment". In Digital Research
    syntax, that means CALL, CALLF, JMP, and JMPF. The problem
    being, then, that the "intersegment" versions would be 6 bytes
    long, not 4...

    (The third problem is that ASM-86 refuses the CALLF and JMPF
    mnemonics.)

    So, is anybody out there who knows the "legal" forms of the FF
    opcodes of the Intel 8086 CPU? (It was introduced in 1978... I
    hope it is officially documented, by now?)

    To finish, since I managed to reach opcode FF, you will find
    following the output by the present program. Depending upon the
    reactions to this message, I could modify the program, to
    improve it.

    (As you can see, at the moment, the program outputs "=??" to
    signal a "not used" (primary) opcode, and "---" to signal "not
    used secondary opcodes". The final version will output only
    "=??", like the debuggers of Digital Research. For now, they
    help debugging which table is holding the "mnemonic".)

    Yours Sincerely,
    Mr Emmanuel Roche


    0080| 00 06 11 11 ADD [1111], AL ; ....
    0084| 01 06 22 22 ADD [2222], AX ; ..""
    0088| 02 06 11 11 ADD AL, [1111] ; ....
    008C| 03 06 22 22 ADD AX, [2222] ; ..""
    0090| 04 12 ADD AL, 12 ; ..
    0092| 05 56 34 ADD AX, 3456 ; .V4
    0095| 06 PUSH ES ; .
    0096| 07 POP ES ; .
    0097| 08 06 11 11 OR [1111], AL ; ....
    009B| 09 06 22 22 OR [2222], AX ; ..""
    009F| 0A 06 11 11 OR AL, [1111] ; ....
    00A3| 0B 06 22 22 OR AX, [2222] ; ..""
    00A7| 0C 12 OR AL, 12 ; ..
    00A9| 0D 56 34 OR AX, 3456 ; .V4
    00AC| 0E PUSH CS ; .
    00AD| 0F =?? ; .
    00AE| 10 06 11 11 ADC [1111], AL ; ....
    00B2| 11 06 22 22 ADC [2222], AX ; ..""
    00B6| 12 06 11 11 ADC AL, [1111] ; ....
    00BA| 13 06 22 22 ADC AX, [2222] ; ..""
    00BE| 14 12 ADC AL, 12 ; ..
    00C0| 15 56 34 ADC AX, 3456 ; .V4
    00C3| 16 PUSH SS ; .
    00C4| 17 POP SS ; .
    00C5| 18 06 11 11 SBB [1111], AL ; ....
    00C9| 19 06 22 22 SBB [2222], AX ; ..""
    00CD| 1A 06 11 11 SBB AL, [1111] ; ....
    00D1| 1B 06 22 22 SBB AX, [2222] ; ..""
    00D5| 1C 12 SBB AL, 12 ; ..
    00D7| 1D 56 34 SBB AX, 3456 ; .V4
    00DA| 1E PUSH DS ; .
    00DB| 1F POP DS ; .
    00DC| 20 06 11 11 AND [1111], AL ; ...
    00E0| 21 06 22 22 AND [2222], AX ; !.""
    00E4| 22 06 11 11 AND AL, [1111] ; "...
    00E8| 23 06 22 22 AND AX, [2222] ; #.""
    00EC| 24 12 AND AL, 12 ; $.
    00EE| 25 56 34 AND AX, 3456 ; %V4
    00F1| 26 ES: ; &
    00F2| 00 06 00 00 ADD [0000], AL ; ....
    00F6| 27 DAA ; '
    00F7| 28 06 11 11 SUB [1111], AL ; (...
    00FB| 29 06 22 22 SUB [2222], AX ; ).""
    00FF| 2A 06 11 11 SUB AL, [1111] ; *...
    0103| 2B 06 22 22 SUB AX, [2222] ; +.""
    0107| 2C 12 SUB AL, 12 ; ,.
    0109| 2D 56 34 SUB AX, 3456 ; -V4
    010C| 2E CS: ; .
    010D| 00 06 00 00 ADD [0000], AL ; ....
    0111| 2F DAS ; /
    0112| 30 06 11 11 XOR [1111], AL ; 0...
    0116| 31 06 22 22 XOR [2222], AX ; 1.""
    011A| 32 06 11 11 XOR AL, [1111] ; 2...
    011E| 33 06 22 22 XOR AX, [2222] ; 3.""
    0122| 34 12 XOR AL, 12 ; 4.
    0124| 35 56 34 XOR AX, 3456 ; 5V4
    0127| 36 SS: ; 6
    0128| 00 06 00 00 ADD [0000], AL ; ....
    012C| 37 AAA ; 7
    012D| 38 06 11 11 CMP [1111], AL ; 8...
    0131| 39 06 22 22 CMP [2222], AX ; 9.""
    0135| 3A 06 11 11 CMP AL, [1111] ; :...
    0139| 3B 06 22 22 CMP AX, [2222] ; ;.""
    013D| 3C 12 CMP AL, 12 ; <.
    013F| 3D 56 34 CMP AX, 3456 ; =V4
    0142| 3E DS: ; >
    0143| 00 06 00 00 ADD [0000], AL ; ....
    0147| 3F AAS ; ?
    0148| 40 INC AX ; @
    0149| 41 INC CX ; A
    014A| 42 INC DX ; B
    014B| 43 INC BX ; C
    014C| 44 INC SP ; D
    014D| 45 INC BP ; E
    014E| 46 INC SI ; F
    014F| 47 INC DI ; G
    0150| 48 DEC AX ; H
    0151| 49 DEC CX ; I
    0152| 4A DEC DX ; J
    0153| 4B DEC BX ; K
    0154| 4C DEC SP ; L
    0155| 4D DEC BP ; M
    0156| 4E DEC SI ; N
    0157| 4F DEC DI ; O
    0158| 50 PUSH AX ; P
    0159| 51 PUSH CX ; Q
    015A| 52 PUSH DX ; R
    015B| 53 PUSH BX ; S
    015C| 54 PUSH SP ; T
    015D| 55 PUSH BP ; U
    015E| 56 PUSH SI ; V
    015F| 57 PUSH DI ; W
    0160| 58 POP AX ; X
    0161| 59 POP CX ; Y
    0162| 5A POP DX ; Z
    0163| 5B POP BX ; [
    0164| 5C POP SP ; \
    0165| 5D POP BP ; ]
    0166| 5E POP SI ; ^
    0167| 5F POP DI ; _
    0168| 60 =?? ; `
    0169| 61 =?? ; a
    016A| 62 =?? ; b
    016B| 63 =?? ; c
    016C| 64 =?? ; d
    016D| 65 =?? ; e
    016E| 66 =?? ; f
    016F| 67 =?? ; g
    0170| 68 =?? ; h
    0171| 69 =?? ; i
    0172| 6A =?? ; j
    0173| 6B =?? ; k
    0174| 6C =?? ; l
    0175| 6D =?? ; m
    0176| 6E =?? ; n
    0177| 6F =?? ; o
    0178| 70 FE JO 0178 ; p.
    017A| 71 FC JNO 0178 ; q.
    017C| 72 FA JB 0178 ; r.
    017E| 72 F8 JB 0178 ; r.
    0180| 72 F6 JB 0178 ; r.
    0182| 73 F4 JNB 0178 ; s.
    0184| 73 F2 JNB 0178 ; s.
    0186| 73 F0 JNB 0178 ; s.
    0188| 74 EE JZ 0178 ; t.
    018A| 74 EC JZ 0178 ; t.
    018C| 75 EA JNZ 0178 ; u.
    018E| 75 E8 JNZ 0178 ; u.
    0190| 76 E6 JBE 0178 ; v.
    0192| 76 E4 JBE 0178 ; v.
    0194| 77 E2 JA 0178 ; w.
    0196| 77 E0 JA 0178 ; w.
    0198| 78 DE JS 0178 ; x.
    019A| 79 DC JNS 0178 ; y.
    019C| 7A DA JP 0178 ; z.
    019E| 7A D8 JP 0178 ; z.
    01A0| 7B D6 JNP 0178 ; {.
    01A2| 7B D4 JNP 0178 ; {.
    01A4| 7C D2 JL 0178 ; |.
    01A6| 7C D0 JL 0178 ; |.
    01A8| 7D CE JNL 0178 ; }.
    01AA| 7D CC JNL 0178 ; }.
    01AC| 7E CA JLE 0178 ; ~.
    01AE| 7E C8 JLE 0178 ; ~.
    01B0| 7F C6 JG 0178 ; ..
    01B2| 7F C4 JG 0178 ; ..
    01B4| 80 06 11 11 12 ADD BYTE [1111], 12 ; .....
    01B9| 80 0E 11 11 12 OR BYTE [1111], 12 ; .....
    01BE| 80 16 11 11 12 ADC BYTE [1111], 12 ; .....
    01C3| 80 1E 11 11 12 SBB BYTE [1111], 12 ; .....
    01C8| 80 26 11 11 12 AND BYTE [1111], 12 ; .&...
    01CD| 80 2E 11 11 12 SUB BYTE [1111], 12 ; .....
    01D2| 80 36 11 11 12 XOR BYTE [1111], 12 ; .6...
    01D7| 80 3E 11 11 12 CMP BYTE [1111], 12 ; .>...
    01DC| 81 06 22 22 56 34 ADD WORD [2222], 3456 ; ..""V4
    01E2| 81 0E 22 22 56 34 OR WORD [2222], 3456 ; ..""V4
    01E8| 81 16 22 22 56 34 ADC WORD [2222], 3456 ; ..""V4
    01EE| 81 1E 22 22 56 34 SBB WORD [2222], 3456 ; ..""V4
    01F4| 81 26 22 22 56 34 AND WORD [2222], 3456 ; .&""V4
    01FA| 81 2E 22 22 56 34 SUB WORD [2222], 3456 ; ..""V4
    0200| 81 36 22 22 56 34 XOR WORD [2222], 3456 ; .6""V4
    0206| 81 3E 22 22 56 34 CMP WORD [2222], 3456 ; .>""V4
    020C| 82 C0 12 ADD AL, 12 ; ...
    020F| 82 08 12 --- AL, 12 ; ...
    0212| 82 D0 12 ADC AL, 12 ; ...
    0215| 82 D8 12 SBB AL, 12 ; ...
    0218| 82 20 12 --- AL, 12 ; . .
    021B| 82 E8 12 SUB AL, 12 ; ...
    021E| 82 30 12 --- AL, 12 ; .0.
    0221| 82 F8 12 CMP AL, 12 ; ...
    0224| 83 C5 12 ADD BP, 12 ; ...
    0227| 83 08 12 --- AX, 12 ; ...
    022A| 83 D5 12 ADC BP, 12 ; ...
    022D| 83 DD 12 SBB BP, 12 ; ...
    0230| 83 20 12 --- AX, 12 ; . .
    0233| 83 ED 12 SUB BP, 12 ; ...
    0236| 83 30 12 --- AX, 12 ; .0.
    0239| 83 FD 12 CMP BP, 12 ; ...
    023C| 84 06 11 11 TEST [1111], AL ; ....
    0240| 85 06 22 22 TEST [2222], AX ; ..""
    0244| 86 06 11 11 XCHG AL, [1111] ; ....
    0248| 87 06 22 22 XCHG AX, [2222] ; ..""
    024C| 88 46 00 MOV [BP], AL ; .F.
    024F| 89 46 00 MOV [BP], AX ; .F.
    0252| 8A C1 MOV AL, CL ; ..
    0254| 8B C1 MOV AX, CX ; ..
    0256| 8C 1E 22 22 MOV [2222], DS ; ..""
    025A| 8C 20 22 22 MOV [2222], -- ; . ""
    025E| 8C 28 22 22 MOV [2222], -- ; .(""
    0262| 8C 30 22 22 MOV [2222], -- ; .0""
    0266| 8C 38 22 22 MOV [2222], -- ; .8""
    026A| 8D 06 22 22 LEA AX, [2222] ; ..""
    026E| 8E 1E 22 22 MOV DS, [2222] ; ..""
    0272| 8E 20 22 22 MOV --, [2222] ; . ""
    0276| 8E 28 22 22 MOV --, [2222] ; .(""
    027A| 8E 30 22 22 MOV --, [2222] ; .0""
    027E| 8E 38 22 22 MOV --, [2222] ; .8""
    0282| 8F 06 22 22 POP [2222] ; ..""
    0286| 8F 08 22 22 --- [2222] ; ..""
    028A| 8F 10 22 22 --- [2222] ; ..""
    028E| 8F 18 22 22 --- [2222] ; ..""
    0292| 8F 20 22 22 --- [2222] ; . ""
    0296| 8F 28 22 22 --- [2222] ; .(""
    029A| 8F 30 22 22 --- [2222] ; .0""
    029E| 8F 38 22 22 --- [2222] ; .8""
    02A2| 90 NOP ; .
    02A3| 91 XCHG AX, CX ; .
    02A4| 92 XCHG AX, DX ; .
    02A5| 93 XCHG AX, BX ; .
    02A6| 94 XCHG AX, SP ; .
    02A7| 95 XCHG AX, BP ; .
    02A8| 96 XCHG AX, SI ; .
    02A9| 97 XCHG AX, DI ; .
    02AA| 98 CBW ; .
    02AB| 99 CWD ; .
    02AC| 9A 00 00 00 00 CALLF 0000:0000 ; .....
    02B1| 9B WAIT ; .
    02B2| 9C PUSHF ; .
    02B3| 9D POPF ; .
    02B4| 9E SAHF ; .
    02B5| 9F LAHF ; .
    02B6| A0 11 11 MOV AL, [1111] ; ...
    02B9| A1 22 22 MOV AX, [2222] ; .""
    02BC| A2 11 11 MOV [1111], AL ; ...
    02BF| A3 22 22 MOV [2222], AX ; .""
    02C2| A4 MOVSB ; .
    02C3| A5 MOVSW ; .
    02C4| A6 CMPSB ; .
    02C5| A7 CMPSW ; .
    02C6| A8 12 TEST AL, 12 ; ..
    02C8| A9 56 34 TEST AX, 3456 ; .V4
    02CB| AA STOSB ; .
    02CC| AB STOSW ; .
    02CD| AC LODSB ; .
    02CE| AD LODSW ; .
    02CF| AE SCASB ; .
    02D0| AF SCASW ; .
    02D1| B0 12 MOV AL, 12 ; ..
    02D3| B1 12 MOV CL, 12 ; ..
    02D5| B2 12 MOV DL, 12 ; ..
    02D7| B3 12 MOV BL, 12 ; ..
    02D9| B4 12 MOV AH, 12 ; ..
    02DB| B5 12 MOV CH, 12 ; ..
    02DD| B6 12 MOV DH, 12 ; ..
    02DF| B7 12 MOV BH, 12 ; ..
    02E1| B8 56 34 MOV AX, 3456 ; .V4
    02E4| B9 56 34 MOV CX, 3456 ; .V4
    02E7| BA 56 34 MOV DX, 3456 ; .V4
    02EA| BB 56 34 MOV BX, 3456 ; .V4
    02ED| BC 56 34 MOV SP, 3456 ; .V4
    02F0| BD 56 34 MOV BP, 3456 ; .V4
    02F3| BE 56 34 MOV SI, 3456 ; .V4
    02F6| BF 56 34 MOV DI, 3456 ; .V4
    02F9| C0 =?? ; .
    02FA| C1 =?? ; .
    02FB| C2 56 34 RET 3456 ; .V4

    02FE| C3 RET ; .

    02FF| C4 06 22 22 LES [2222] ; ..""
    0303| C5 06 22 22 LDS [2222] ; ..""
    0307| C6 06 11 11 12 MOV BYTE [1111], 12 ; .....
    030C| C6 08 11 11 12 --- BYTE [1111], 12 ; .....
    0311| C6 10 11 11 12 --- BYTE [1111], 12 ; .....
    0316| C6 18 11 11 12 --- BYTE [1111], 12 ; .....
    031B| C6 20 11 11 12 --- BYTE [1111], 12 ; . ...
    0320| C6 28 11 11 12 --- BYTE [1111], 12 ; .(...
    0325| C6 30 11 11 12 --- BYTE [1111], 12 ; .0...
    032A| C6 38 11 11 12 --- BYTE [1111], 12 ; .8...
    032F| C7 06 22 22 56 34 MOV WORD [2222], 3456 ; ..""V4
    0335| C7 08 22 22 56 34 --- WORD [2222], 3456 ; ..""V4
    033B| C7 10 22 22 56 34 --- WORD [2222], 3456 ; ..""V4
    0341| C7 18 22 22 56 34 --- WORD [2222], 3456 ; ..""V4
    0347| C7 20 22 22 56 34 --- WORD [2222], 3456 ; . ""V4
    034D| C7 28 22 22 56 34 --- WORD [2222], 3456 ; .(""V4
    0353| C7 30 22 22 56 34 --- WORD [2222], 3456 ; .0""V4
    0359| C7 38 22 22 56 34 --- WORD [2222], 3456 ; .8""V4
    035F| C8 =?? ; .
    0360| C9 =?? ; .
    0361| CA 56 34 RETF 3456 ; .V4

    0364| CB RETF ; .

    0365| CC INT 3 ; .
    0366| CD 12 INT 12 ; ..
    0368| CE INTO ; .
    0369| CF IRET ; .

    036A| D0 C0 ROL AL, 1 ; ..
    036C| D0 C9 ROR CL, 1 ; ..
    036E| D0 D2 RCL DL, 1 ; ..
    0370| D0 DB RCR BL, 1 ; ..
    0372| D0 E4 SHL AH, 1 ; ..
    0374| D0 E5 SHL CH, 1 ; ..
    0376| D0 EE SHR DH, 1 ; ..
    0378| D0 30 --- AL, 1 ; .0
    037A| D0 FF SAR BH, 1 ; ..
    037C| D1 C0 ROL AX, 1 ; ..
    037E| D1 C9 ROR CX, 1 ; ..
    0380| D1 D2 RCL DX, 1 ; ..
    0382| D1 DB RCR BX, 1 ; ..
    0384| D1 E0 SHL AX, 1 ; ..
    0386| D1 E1 SHL CX, 1 ; ..
    0388| D1 EA SHR DX, 1 ; ..
    038A| D1 30 --- AX, 1 ; .0
    038C| D1 FB SAR BX, 1 ; ..
    038E| D2 C0 ROL AL, CL ; ..
    0390| D2 C9 ROR CL, CL ; ..
    0392| D2 D2 RCL DL, CL ; ..
    0394| D2 DB RCR BL, CL ; ..
    0396| D2 E4 SHL AH, CL ; ..
    0398| D2 E5 SHL CH, CL ; ..
    039A| D2 EE SHR DH, CL ; ..
    039C| D2 30 --- AL, CL ; .0
    039E| D2 FF SAR BH, CL ; ..
    03A0| D3 C0 ROL AX, CL ; ..
    03A2| D3 C9 ROR CX, CL ; ..
    03A4| D3 D2 RCL DX, CL ; ..
    03A6| D3 DB RCR BX, CL ; ..
    03A8| D3 E0 SHL AX, CL ; ..
    03AA| D3 E1 SHL CX, CL ; ..
    03AC| D3 EA SHR DX, CL ; ..
    03AE| D3 30 --- AX, CL ; .0
    03B0| D3 FB SAR BX, CL ; ..
    03B2| D4 0A AAM ; ..
    03B4| D5 0A AAD ; ..
    03B6| D6 =?? ; .
    03B7| D7 XLAT ; .
    03B8| D8 C0 ESC 0, AL ; ..
    03BA| D9 C1 ESC 8, CL ; ..
    03BC| DA C2 ESC 16, DL ; ..
    03BE| DB C3 ESC 24, BL ; ..
    03C0| DC C4 ESC 32, AH ; ..
    03C2| DD C5 ESC 40, CH ; ..
    03C4| DE C6 ESC 48, DH ; ..
    03C6| DF C7 ESC 56, BH ; ..
    03C8| E0 FE LOOPNE 03C8 ; ..
    03CA| E0 FC LOOPNE 03C8 ; ..
    03CC| E1 FA LOOPE 03C8 ; ..
    03CE| E1 F8 LOOPE 03C8 ; ..
    03D0| E2 F6 LOOP 03C8 ; ..
    03D2| E3 F4 JCXZ 03C8 ; ..
    03D4| E4 12 IN AL, 12 ; ..
    03D6| E5 12 IN AX, 12 ; ..
    03D8| E6 12 OUT 12, AL ; ..
    03DA| E7 12 OUT 12, AX ; ..
    03DC| E8 A1 FC CALL FCA1 ; ...
    03DF| E9 9E FC JMP FC9E ; ...

    03E2| EA 00 00 00 00 JMPF 0000:0000 ; .....

    03E7| EB DF JMPS 03C8 ; ..

    03E9| EC IN AL, DX ; .
    03EA| ED IN AX, DX ; .
    03EB| EE OUT DX, AL ; .
    03EC| EF OUT DX, AX ; .
    03ED| F0 90 LOCK 90 ; ..
    03EF| F1 =?? ; .
    03F0| F2 90 REPNE 90 ; ..
    03F2| F2 90 REPNE 90 ; ..
    03F4| F3 90 REP 90 ; ..
    03F6| F3 90 REP 90 ; ..
    03F8| F3 90 REP 90 ; ..
    03FA| F4 HLT ; .
    03FB| F5 CMC ; .
    03FC| F6 06 11 11 12 TEST BYTE [1111], 12 ; ....
    0401| F6 08 11 11 --- BYTE [1111] ; ....
    0405| F6 16 11 11 NOT BYTE [1111] ; ....
    0409| F6 1E 11 11 NEG BYTE [1111] ; ....
    040D| F6 26 11 11 MUL BYTE [1111] ; .&..
    0411| F6 2E 11 11 IMUL BYTE [1111] ; ....
    0415| F6 36 11 11 DIV BYTE [1111] ; .6..
    0419| F6 3E 11 11 IDIV BYTE [1111] ; .>..
    041D| F7 06 22 22 56 34 TEST WORD [2222], 3456 ; ..""
    0423| F7 08 22 22 --- WORD [2222] ; ..""
    0427| F7 16 22 22 NOT WORD [2222] ; ..""
    042B| F7 1E 22 22 NEG WORD [2222] ; ..""
    042F| F7 26 22 22 MUL WORD [2222] ; .&""
    0433| F7 2E 22 22 IMUL WORD [2222] ; ..""
    0437| F7 36 22 22 DIV WORD [2222] ; .6""
    043B| F7 3E 22 22 IDIV WORD [2222] ; .>""
    043F| F8 CLC ; .
    0440| F9 STC ; .
    0441| FA CLI ; .
    0442| FB STI ; .
    0443| FC CLD ; .
    0444| FD STD ; .
    0445| FE 06 11 11 INC BYTE [1111] ; ....
    0449| FE 0E 11 11 DEC BYTE [1111] ; ....
    044D| FE 10 11 11 --- BYTE [1111] ; ....
    0451| FE 18 11 11 --- BYTE [1111] ; ....
    0455| FE 20 11 11 --- BYTE [1111] ; . ..
    0459| FE 28 11 11 --- BYTE [1111] ; .(..
    045D| FE 30 11 11 --- BYTE [1111] ; .0..
    0461| FE 38 11 11 --- BYTE [1111] ; .8..
    0465| FF 06 22 22 INC WORD [2222] ; ..""
    0469| FF 0E 22 22 DEC WORD [2222] ; ..""
    046D| FF D0 22 22 CALL WORD [2222] ; ..""
    0471| FF 16 22 22 CALL WORD [2222] ; ..""
    0475| FF E0 22 22 JMP WORD [2222] ; ..""
    0479| FF 26 22 22 JMP WORD [2222] ; .&""
    047D| FF 36 22 22 PUSH WORD [2222] ; .6""
    0481| FF 38 22 22 --- WORD [2222] ; .8""


    EOF



  19. Re: Intel 8086 opcodes

    *roche182* wrote on Mon, 07-09-17 10:54:
    >(I never had so much trouble understanding the opcodes of a
    >computer. Intel really goofed mightily when they designed the 8086
    >CPU instruction set.)


    Intel x86 was never known to be particularly good but still:

    How many processors do you know, really? There is one in which you are
    incredibly experienced for decades and one that is new to you, while
    you are, like most here, rather elderly now and don't find learning new
    stuff as easy as it used to be (or as you remeber it now, which need
    not be the same thing).

    I notice much the same problems myself.


  20. Re: Intel 8086 opcodes

    - "The 8086 CPU Instruction Set: The FF Opcode"

    Ok. We have tested all the opcodes of the 8086 CPU instruction
    set. The
    biggest problem happens with the last one: FF. So, let us spend one
    article
    discussing it specifically.

    Back home, I re-(etc.)read everything that I have on the 8086. Could
    not find
    anything special about the FF opcode.

    The author of the 8086 CPU, thinking in binary, lists the
    "Unconditional
    Transfer Instructions":

    +-----------------+ +----------+ +-----------+
    | 1 1 1 0 1 0 0 1 | | diff-low | | diff-high |
    +-----------------+ +----------+ +-----------+
    JMP: jump direct intrasegment

    +-----------------+ +------+
    | 1 1 1 0 1 0 1 1 | | diff |
    +-----------------+ +------+
    JMP: jump direct intrasegment (short)

    +-----------------+ +-----+-------+-----+
    | 1 1 1 1 1 1 1 1 | | mod | 1 0 0 | r/m |
    +-----------------+ +-----+-------+-----+
    JMP: jump indirect intrasegment

    +-----------------+ +---------+ +----------+ +---------+
    +----------+
    | 1 1 1 0 1 0 1 0 | | off-low | | off-high | | seg-low | |
    seg-high |
    +-----------------+ +---------+ +----------+ +---------+
    +----------+
    JMP: jump direct intersegment

    +-----------------+ +-----+-------+-----+
    | 1 1 1 1 1 1 1 1 | | mod | 1 0 1 | r/m |
    +-----------------+ +-----+-------+-----+
    JMP: jump indirect intersegment

    +-----------------+ +----------+ +-----------+
    | 1 1 1 0 1 0 0 0 | | diff-low | | diff-high |
    +-----------------+ +----------+ +-----------+
    CALL: call direct intrasegment

    +-----------------+ +-----+-------+-----+
    | 1 1 1 1 1 1 1 1 | | mod | 0 1 0 | r/m |
    +-----------------+ +-----+-------+-----+
    CALL: call indirect intrasegment

    +-----------------+ +---------+ +----------+ +---------+
    +----------+
    | 1 0 0 1 1 0 1 0 | | off-low | | off-high | | seg-low | |
    seg-high |
    +-----------------+ +---------+ +----------+ +---------+
    +----------+
    CALL: call direct intersegment

    +-----------------+ +-----+-------+-----+
    | 1 1 1 1 1 1 1 1 | | mod | 0 1 1 | r/m |
    +-----------------+ +-----+-------+-----+
    CALL: call indirect intersegment

    +-----------------+
    | 1 1 0 0 0 0 1 1 |
    +-----------------+
    RET: return intrasegment

    +-----------------+ +----------+ +-----------+
    | 1 1 0 0 0 0 1 0 | | data-low | | data-high |
    +-----------------+ +----------+ +-----------+
    RET: return intrasegment, adding immediate to SP

    +-----------------+
    | 1 1 0 0 1 0 1 1 |
    +-----------------+
    RET: return intersegment

    +-----------------+ +----------+ +-----------+
    | 1 1 0 0 1 0 1 0 | | data-low | | data-high |
    +-----------------+ +----------+ +-----------+
    RET: return intersegment, adding immediate to SP

    Figure 3.40 Formats of unconditional jump, calls, and returns

    Today, we are just interested in the CALL and JMP instructions.
    Since I
    usually think in hexadecimal when programming (remember, I used to
    program IBM
    Mainframes, for which IBM created the hexadecimal notation for
    its S/360
    line. Before, everybody was using octal.) (As some old Unix freaks
    still do.),
    I have added them in front of the "boxes":

    +-----------------+ +----------+ +-----------+
    E9 | 1 1 1 0 1 0 0 1 | | diff-low | | diff-high |
    +-----------------+ +----------+ +-----------+
    JMP: jump direct intrasegment

    +-----------------+ +------+
    EB | 1 1 1 0 1 0 1 1 | | diff |
    +-----------------+ +------+
    JMP: jump direct intrasegment (short)

    +-----------------+ +-----+-------+-----+
    FF | 1 1 1 1 1 1 1 1 | | mod | 1 0 0 | r/m |
    +-----------------+ +-----+-------+-----+
    JMP: jump indirect intrasegment

    +-----------------+ +---------+ +----------+ +---------+
    +----------+
    EA | 1 1 1 0 1 0 1 0 | | off-low | | off-high | | seg-low | |
    seg-high |
    +-----------------+ +---------+ +----------+ +---------+
    +----------+
    JMP: jump direct intersegment

    +-----------------+ +-----+-------+-----+
    FF | 1 1 1 1 1 1 1 1 | | mod | 1 0 1 | r/m |
    +-----------------+ +-----+-------+-----+
    JMP: jump indirect intersegment

    +-----------------+ +----------+ +-----------+
    E8 | 1 1 1 0 1 0 0 0 | | diff-low | | diff-high |
    +-----------------+ +----------+ +-----------+
    CALL: call direct intrasegment

    +-----------------+ +-----+-------+-----+
    FF | 1 1 1 1 1 1 1 1 | | mod | 0 1 0 | r/m |
    +-----------------+ +-----+-------+-----+
    CALL: call indirect intrasegment

    +-----------------+ +---------+ +----------+ +---------+
    +----------+
    9A | 1 0 0 1 1 0 1 0 | | off-low | | off-high | | seg-low | |
    seg-high |
    +-----------------+ +---------+ +----------+ +---------+
    +----------+
    CALL: call direct intersegment

    +-----------------+ +-----+-------+-----+
    FF | 1 1 1 1 1 1 1 1 | | mod | 0 1 1 | r/m |
    +-----------------+ +-----+-------+-----+
    CALL: call indirect intersegment

    So, since today we are only interested in the FF opcodes, let us
    concentrate
    upon them:

    +-----------------+ +-----+-------+-----+
    FF | 1 1 1 1 1 1 1 1 | | mod | 1 0 0 | r/m |
    +-----------------+ +-----+-------+-----+
    JMP: jump indirect intrasegment

    +-----------------+ +-----+-------+-----+
    FF | 1 1 1 1 1 1 1 1 | | mod | 1 0 1 | r/m |
    +-----------------+ +-----+-------+-----+
    JMP: jump indirect intersegment

    +-----------------+ +-----+-------+-----+
    FF | 1 1 1 1 1 1 1 1 | | mod | 0 1 0 | r/m |
    +-----------------+ +-----+-------+-----+
    CALL: call indirect intrasegment

    +-----------------+ +-----+-------+-----+
    FF | 1 1 1 1 1 1 1 1 | | mod | 0 1 1 | r/m |
    +-----------------+ +-----+-------+-----+
    CALL: call indirect intersegment

    First thing to notice: according to its author, those opcodes are
    2 bytes
    long, while the Intel doc says that they are 4 bytes long...

    Second, the un-named field between the MOD and R/M fields
    (sometimes named
    "REG(ister)", sometimes "OPC(ode)". Visibly, Intel could not decide to
    call it
    "R/O" for "Register/Opcode"... Since I am too kind, I will solve
    Intel's
    problem. The problem was that Intel did not remember that this field
    is not
    inside the opcode, BUT INSIDE THE SECONDARY OPCODE... And one
    acronym for
    Secondary Opcode could be "SO", in which case R/SO could be shortened
    to RSO
    (or "R/S"). That it to say: another 3-letter acronym, fitting nicely
    in tables
    and programs dealing with the 8086 CPU instruction set...) has
    the values
    corresponding to the one in the "Grp 2" "Secondary Opcode Space"
    table. No
    problem, here.

    Third, all of them have "indirect" in their description.

    Time to do a little programming. I created a file to test what
    would SID-86
    says. The MOD field, as you should know by now, only has 2 bits, so
    4 lines
    will contain all its possible values. The R/M (Register/Memory)
    field has 3
    bits, so 8 lines will contain all its possibles values. Total: 4 *
    8 = 32
    lines will be enough! (When you are lucky enough to have so few
    cases to
    check, it woud be totally crazy not to test them systematically.) For
    safety,
    each line will be padded to 4 bytes with NOPs.

    I first typed a line, then used WordStar to copy it 8 times, then
    changed all
    the R/M fields, then used WS4 to copy another 3 times the result,
    then used
    WS4 to patch all the MOD fields. Ha, the joy of word-processing!

    Back to SID-86. Here is what it displays:

    18E8:0080 CALL [BX+SI]
    18E8:0082 NOP
    18E8:0083 NOP
    18E8:0084 CALL [BX+DI]
    18E8:0086 NOP
    18E8:0087 NOP
    18E8:0088 CALL [BP+SI]
    18E8:008A NOP
    18E8:008B NOP
    18E8:008C CALL [BP+DI]
    18E8:008E NOP
    18E8:008F NOP
    18E8:0090 CALL [SI]
    18E8:0092 NOP
    18E8:0093 NOP
    18E8:0094 CALL [DI]
    18E8:0096 NOP
    18E8:0097 NOP
    18E8:0098 CALL [9090]
    18E8:009C CALL [BX]
    18E8:009E NOP
    18E8:009F NOP
    18E8:00A0 CALLF [BX+SI]
    18E8:00A2 NOP
    18E8:00A3 NOP
    18E8:00A4 CALLF [BX+DI]
    18E8:00A6 NOP
    18E8:00A7 NOP
    18E8:00A8 CALLF [BP+SI]
    18E8:00AA NOP
    18E8:00AB NOP
    18E8:00AC CALLF [BP+DI]
    18E8:00AE NOP
    18E8:00AF NOP
    18E8:00B0 CALLF [SI]
    18E8:00B2 NOP
    18E8:00B3 NOP
    18E8:00B4 CALLF [DI]
    18E8:00B6 NOP
    18E8:00B7 NOP
    18E8:00B8 CALLF [9090]
    18E8:00BC CALLF [BX]
    18E8:00BE NOP
    18E8:00BF NOP
    18E8:00C0 JMP [BX+SI]
    18E8:00C2 NOP
    18E8:00C3 NOP
    18E8:00C4 JMP [BX+DI]
    18E8:00C6 NOP
    18E8:00C7 NOP
    18E8:00C8 JMP [BP+SI]
    18E8:00CA NOP
    18E8:00CB NOP
    18E8:00CC JMP [BP+DI]
    18E8:00CE NOP
    18E8:00CF NOP
    18E8:00D0 JMP [SI]
    18E8:00D2 NOP
    18E8:00D3 NOP
    18E8:00D4 JMP [DI]
    18E8:00D6 NOP
    18E8:00D7 NOP
    18E8:00D8 JMP [9090]
    18E8:00DC JMP [BX]
    18E8:00DE NOP
    18E8:00DF NOP
    18E8:00E0 JMPF [BX+SI]
    18E8:00E2 NOP
    18E8:00E3 NOP
    18E8:00E4 JMPF [BX+DI]
    18E8:00E6 NOP
    18E8:00E7 NOP
    18E8:00E8 JMPF [BP+SI]
    18E8:00EA NOP
    18E8:00EB NOP
    18E8:00EC JMPF [BP+DI]
    18E8:00EE NOP
    18E8:00EF NOP
    18E8:00F0 JMPF [SI]
    18E8:00F2 NOP
    18E8:00F3 NOP
    18E8:00F4 JMPF [DI]
    18E8:00F6 NOP
    18E8:00F7 NOP
    18E8:00F8 JMPF [9090]
    18E8:00FC JMPF [BX]
    18E8:00FE NOP
    18E8:00FF NOP
    18E8:0100 ADD [BX+SI],AL

    (The last ADD is a 00h byte, as you probably know. For some unknown
    reason,
    the newbies who designed the 8086 CPU decided not to use 00h for NOP.)

    Removing the NOPs, we get (thanks to WS4 "column mode"):

    18E8:0080 FF109090 CALL [BX+SI]
    18E8:0084 FF119090 CALL [BX+DI]
    18E8:0088 FF129090 CALL [BP+SI]
    18E8:008C FF139090 CALL [BP+DI]
    18E8:0090 FF149090 CALL [SI]
    18E8:0094 FF159090 CALL [DI]
    18E8:0098 FF169090 CALL [9090]
    18E8:009C FF179090 CALL [BX]

    18E8:00A0 FF189090 CALLF [BX+SI]
    18E8:00A4 FF199090 CALLF [BX+DI]
    18E8:00A8 FF1A9090 CALLF [BP+SI]
    18E8:00AC FF1B9090 CALLF [BP+DI]
    18E8:00B0 FF1C9090 CALLF [SI]
    18E8:00B4 FF1D9090 CALLF [DI]
    18E8:00B8 FF1E9090 CALLF [9090]
    18E8:00BC FF1F9090 CALLF [BX]

    18E8:00C0 FF209090 JMP [BX+SI]
    18E8:00C4 FF219090 JMP [BX+DI]
    18E8:00C8 FF229090 JMP [BP+SI]
    18E8:00CC FF239090 JMP [BP+DI]
    18E8:00D0 FF249090 JMP [SI]
    18E8:00D4 FF259090 JMP [DI]
    18E8:00D8 FF269090 JMP [9090]
    18E8:00DC FF279090 JMP [BX]

    18E8:00E0 FF289090 JMPF [BX+SI]
    18E8:00E4 FF299090 JMPF [BX+DI]
    18E8:00E8 FF2A9090 JMPF [BP+SI]
    18E8:00EC FF2B9090 JMPF [BP+DI]
    18E8:00F0 FF2C9090 JMPF [SI]
    18E8:00F4 FF2D9090 JMPF [DI]
    18E8:00F8 FF2E9090 JMPF [9090]
    18E8:00FC FF2F9090 JMPF [BX]

    First thing to notice: following all the available 8086
    documentation, SID-86
    displays CALLF and JMPF for "indirect intersegment" opcodes. At
    least, there
    is no contradiction with the name of the mnemonics. The problem is
    that the
    official Intel doc for Grp 2 is:

    RSO | 000 | 001 | 010 | 011 | 100 | 101 | 110 | 111
    -----+-----+-----+-----+-----+-----+-----+-----+-----
    Grp2 | INC | DEC | CALL| CALL| JMP | JMP | PUSH| ---
    | | | id | L,id| id | L,id| |
    -----+-----+-----+-----+-----+-----+-----+-----+-----

    However, upon reading the little characters, we learn that
    "id" means
    "indirect", and "L" means "intersegment". In Digital Research
    syntax, that
    means CALL, CALLF, JMP, and JMPF. One thing to patch in my program.

    Second, all opcodes are 2 bytes long, except the 7th line of each
    group, which
    is 4 bytes long. Now, the problem is that, as explained, each group
    start with
    one of the 4 values possible for the MOD field and, according to the
    official
    Intel doc, only MOD=00 (that is to say: the first group) commands the
    8086 CPU
    to use "Memory Mode". Here, we have four times the MOD=00 column, as
    found in
    Table 4-10, "R/M Field Encoding". This is obviously what Intel had
    in mind
    when talking about "indirect" instructions.

    Searching for a "coding sample", I had the idea to have a look to
    my sample
    file. For this discussion, I erased everything not CALL or JMP.

    022C 9A00000000 R callf label

    035C E8A1FC 0000 call label
    035F E99EFC 0000 jmp label
    0362 EA00000000 R jmpf label
    0367 EBDF 0348 jmps short_label2

    03ED FFD02222 call ax! db 22h, 22h
    03F1 FF162222 R call mem_16
    03F5 FFE02222 jmp ax! db 22h, 22h
    03F9 FF262222 R jmp mem_16

    There is no obvious problem with the first CALLs and JMPs, so let us
    turn our
    attention to the last 4 lines.

    According to "The 8086 Family User's Manual", Page 4-35,

    RSO=2 CALL reg16/mem16
    RSO=3 CALL FAR mem16
    RSO=4 JMP reg16/mem16
    RSO=5 JMP FAR mem16

    Now, what does it means by "reg16"? When writing my sample file, I
    used "AX"
    since, for me, it is a 16-bit register. However, according to
    SID-86, it is
    more appropriately designed as the various indirect addressing modes
    found in
    the MOD=00 column of Table 4-10, "R/M Field Encoding".

    For instance,

    03ED FFD02222 call ax! db 22h, 22h

    happens to be totally outside the "legal" values for the RSO (shown to
    be 10h
    to 2Fh by SID-86). So, is it another bug inside ASM-86?

    However, the second line from my sample file,

    03F1 FF162222 R call mem_16

    clearly fit inside

    18E8:0094 FF159090 CALL [DI]
    18E8:0098 FF169090 CALL [9090]
    18E8:009C FF179090 CALL [BX]

    so is a leg... Wait! How is it possible that ASM-86 generated this
    value?

    Re-examining the above portion, we notice that

    035C E8A1FC 0000 call label

    03F1 FF162222 R call mem_16

    That is to say: in the first case, ASM-86 generates an E8 opcode,
    and an FF
    opcode in the second! How is it possible?

    Using WS4, I jumped to the place where "label" and "mem_16" are
    defined:

    ;--------------------------------
    CSEG $
    ;--------------------------------
    label:

    ;--------------------------------
    DSEG
    ;--------------------------------
    ORG 2222h
    mem_16 dw 6789h

    Haaaaa! ASM-86 generate a different call opcode whether the called
    label is
    defined in a Code Segment (E8) or inside a Data Segment (FF 16)! That
    was the
    trick! That is what the Intel doc calls "mem16"... (In truth, the
    other label
    is named "near_label". Since ASM-86 does not use NEAR blah-
    blah, I had
    disregarded this... How tricky this instruction set is! There are
    so many
    cases that the mnemonics are not able to cover all of them (at
    least 17
    MOVs!), hence the assembler is obliged to keep track of all the
    details of the
    variables, just to generate the appropriate code.)

    Ok, so this explains clearly what a "CALLF mem_16"
    instruction should
    generate. For the "CALL reg16", I will follow SID-86. So, 2 things
    to check
    inside ASM-86.

    (For the JMP instructions, the 8086 CPU instruction set being so
    regular, I
    have no doubt that it follows the CALL FF opcodes. Or, this
    instruction set
    would be really damned!)

    So, The FF opcode should be decoded like this:

    FF MOD 000 R/M INC WORD [2222]
    FF MOD 001 R/M DEC WORD [2222]
    FF MOD 010 R/M CALL reg16
    FF MOD 011 R/M CALLF mem16
    FF MOD 100 R/M JMP reg16
    FF MOD 101 R/M JMPF mem16
    FF MOD 110 R/M PUSH [2222]
    FF MOD 111 R/M --- [2222]

    That is to say: 4 cases are 2 bytes long (but 4 bytes long when R/
    M=110), and
    4 cases are 4 bytes long... This opcode is really not easy to decode!
    I will
    have to write a subroutine specially for it.

    Haaaaa! After a few hours, here is what I get:

    0080| FF 06 22 22 INC WORD [2222] ; ..""
    0084| FF 0E 22 22 DEC WORD [2222] ; ..""
    0088| FF 10 CALL [BX+SI] ; ..
    008A| FF 11 CALL [BX+DI] ; ..
    008C| FF 12 CALL [BP+SI] ; ..
    008E| FF 13 CALL [BP+DI] ; ..
    0090| FF 14 CALL [SI] ; ..
    0092| FF 15 CALL [DI] ; ..
    0094| FF 16 22 22 CALL [2222] ; ..""
    0098| FF 17 CALL [BX] ; ..
    009A| FF 18 CALLF [BX+SI] ; ..
    009C| FF 19 CALLF [BX+DI] ; ..
    009E| FF 1A CALLF [BP+SI] ; ..
    00A0| FF 1B CALLF [BP+DI] ; ..
    00A2| FF 1C CALLF [SI] ; ..
    00A4| FF 1D CALLF [DI] ; ..
    00A6| FF 1E 22 22 CALLF [2222] ; ..""
    00AA| FF 1F CALLF [BX] ; ..
    00AC| FF 20 JMP [BX+SI] ; .
    00AE| FF 21 JMP [BX+DI] ; .!
    00B0| FF 22 JMP [BP+SI] ; ."
    00B2| FF 23 JMP [BP+DI] ; .#
    00B4| FF 24 JMP [SI] ; .$
    00B6| FF 25 JMP [DI] ; .%
    00B8| FF 26 22 22 JMP [2222] ; .&""
    00BC| FF 27 JMP [BX] ; .'
    00BE| FF 28 JMPF [BX+SI] ; .(
    00C0| FF 29 JMPF [BX+DI] ; .)
    00C2| FF 2A JMPF [BP+SI] ; .*
    00C4| FF 2B JMPF [BP+DI] ; .+
    00C6| FF 2C JMPF [SI] ; .,
    00C8| FF 2D JMPF [DI] ; .-
    00CA| FF 2E 22 22 JMPF [2222] ; ..""
    00CE| FF 2F JMPF [BX] ; ./
    00D0| FF 36 22 22 PUSH [2222] ; .6""
    00D4| FF 38 22 22 --- [2222] ; .8""

    Trivial, isn't it?


    Yours Sincerely,
    Mr Emmanuel Roche


    EOF



+ Reply to Thread
Page 3 of 4 FirstFirst 1 2 3 4 LastLast