Assembly: why some x86 opcodes are invalid in x64?

Why in x64 some of the opcodes are invalid (06, 07 for example), whereas in x86 are used for fairly basic instructions (06 and 07 being push and pop)? I thought that those simplest instructions would do nicely in both architectures.

Why they disabled some of those simple instructions in x64? Why wouldn't they work? Why they disabled some opcodes, creating holes in opcode list, when they could instead assign them to x64 versions of instructions?



  • The 06 and 07 opcodes in 32-bit mode are the instructions PUSH ES and POP ES. In 64-bit mode, the segment registers CS, DS, ES, and SS are no longer used to determine memory addresses: the processor assumes a base address of 0 and no size limits. As there's now usually no reason for applications (other than the operating system itself) to access these registers, the push/pop opcodes for changing and accessing them were removed, leaving only mov to/from Sreg (which is just 2 total opcodes; the register number goes in the ModRM byte instead of part of the 1-byte opcode). That's totally sufficient for something that's almost never needed.

    The FS and GS segment registers can still set the base address in 64-bit mode, so push and pop opcodes related to them have not been removed. (These 2-byte 0F xx opcodes were added in 386, and are a less valuable part of opcode space than the old 1-byte opcodes for 8086 segment registers).

    Push/pop or mov of segment registers is not how OSes would typically set FS or GS segment bases, though: that would require a GDT or LDT entry, and could only set a base within the low 32 bits. 64-bit OSes would use the associated MSRs to read and write the bases directly, not the architectural registers. (Modern 32-bit OSes do that, too, unless running on old hardware that doesn't support the segment base MSRs.)