I am trying to figure out how to encode the instruction MOV DS, AX, but I am confused from the opcode table as follows:

enter image description here

  1. Is MOV DS all one byte, or is MOV one byte, DS the second, and the AX the third?

  2. Is the table implying that the binary value of the source register prefix DS is 011? If so, how would I encode it as part of the whole instruction?

I can not understand how the tables make sense by the way they're listed; they should be more specific! Can anyone straighten this out?

I just want to move the value from the AX register to the data segment, DS. No sites perfectly explains how encoding of registers within opcodes work exactly, or relocation.

All the tables come from http://ref.x86asm.net, and it's very vague, unclear, unspecific, and undetailed.

I would like to know if there's any 100% detailed, perfectly explained tutorials on how encoding of each byte, values for each register, address truncation, offset, etc. works in binary, and how to encode it all the correct way.


That site is good if you're familiar with how the encoding works but if you're just starting I'd skip it for now.

The best starting point is probably the Intel's Architectures Software Developer Manuals. Have a look at CHAPTER 2 INSTRUCTION FORMAT in the Volume 2, and also the appendices, particularly APPENDIX B INSTRUCTION FORMATS AND ENCODINGS and APPENDIX A OPCODE MAP. They describe how to decode instructions in great detail.

Once you're a little familiar with parts of the instruction encodings, the notations in the instruction listing pages will start to make sense. For example, let's check the one you need.

On the page for MOV, find the variant you need. This one looks like it:

Hex     Mnemonic          Encoding   Description
8E /r   MOV Sreg,r/m16**  RM         Move r/m16 to segment register.

Looking up 'RM' in the following table, we get:

Op/En Operand 1     Operand 2     Operand 3 Operand 4
RM    ModRM:reg (w) ModRM:r/m (r) NA        NA

And so we can start assembling the opcode.

The first byte is fixed to be 8E.

The second byte is the ModRM byte. It consists of three fields: mod, reg and r/m. Let's assemble it with the help of this nice table from Sandpile.

First up is the mod field. Since our second operand is a register and not a memory reference, this corresponds to mod=11.

From the RM encoding line we see that reg encodes the first operand, in our case DS. Looking it up in the table, we can see that DS is encoded as 011.

And finally is the r/m field encoding operand 2, i.e. AX. It is encoded as 000.

So our ModRM byte is 11:011:000, or D8. This makes the full opcode to be 8E D8. You can check it with your favorite disassembler, e.g. XED:

>xed.exe -d 8E D8
SHORT: mov ds, ax

(BTW, the /r notation in the encoding line tells us that the reg field of the ModRM byte encodes a register and is not an opcode extension. In the latter case the notation would have a /<digit> notation where is the value of the reg field).

| improve this answer | |
  • I want to learn encoding ,not decoding! Could you be a little more specific? I'm sorry, but I only learn with great details well explained! – Jonas' River Feb 12 '14 at 22:25
  • 6
    Encoding and decoding are very closely connected. You won't figure out how to encode instructions if you don't know how the processor decodes them. – Igor Skochinsky Feb 12 '14 at 22:29
  • @Jonas'River the decoding was presented as proof of correctness. Igor, great explanation! It might be easier to explain that we look up the byte value in the lower section of the table with the row corresponding to AX under "effective address" and the column under DS in the upper half of the table. Or did I read it wrong? – Codebling Feb 23 '14 at 5:07

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.