8086, 80386 and x86-64 compatible instructions

Programming, for all ages and all languages.
Antti
Member
Member
Posts: 923
Joined: Thu Jul 05, 2012 5:12 am
Location: Finland

8086, 80386 and x86-64 compatible instructions

Post by Antti »

I was just wondering whether it is possible to write code that is compatible with Real Mode, Protected Mode, and Long Mode. I do not mean using few instructions to test the mode and then branching to the correct mode-specific code. Here are few things I wrote down:

Code: Select all

Instructions using ModR/M byte (between registers) are very useful. This is the way to clear registers and moving values. Of course, we are restricted to use only lowest 16 bits.

        16-bit                  32-bit                  64-bit
        MOV AX, BX              MOV EAX, EBX            MOV EAX, EBX
        XOR AX, AX              XOR EAX, EAX            XOR EAX, EAX


Immediate values need to be 8-bit. This makes code a little bit longer.

        16-bit                  32-bit                  64-bit
        MOV AL, 8               MOV AL, 8               MOV AL, 8
        MOV AH, 8               MOV AH, 8               MOV AH, 8


To access a memory location, we could use "BX == EDI == RDI". It means that the memory location should have two bytes (actual value) and two zero bytes if using AX/EAX.

        16-bit                  32-bit                  64-bit
        MOV [BX], AX            MOV [EDI], EAX          MOV [RDI], EAX
        MOV AX, [BX]            MOV EAX, [EDI]          MOV EAX, [RDI]


Relative calls can not be used so we must use indirect addresses.

        16-bit                  32-bit                  64-bit
        CALL AX                 CALL EAX                CALL RAX
        RET                     RET                     RET


Short jumps and indirect jumps can be used.

        16-bit                  32-bit                  64-bit
        JMP rel8                JMP rel8                JMP rel8
        JMP AX                  JMP EAX                 JMP RAX


Short conditional jumps can be used.

        16-bit                  32-bit                  64-bit
        JC rel8                 JC rel8                 JC rel8
This is not a comprehensive list. However, did I forget something that makes this impossible?
User avatar
mathematician
Member
Member
Posts: 437
Joined: Fri Dec 15, 2006 5:26 pm
Location: Church Stretton Uk

Re: 8086, 80386 and x86-64 compatible instructions

Post by mathematician »

Well, in real mode you would have to make explicit use of the segment registers, unless you wanted to be limited to 64kb of memory, and since 32 bit or 64 bit code would probably assume a flat address space, that could be a problem.

In any case, what would be the point of having a computer with (say) 8192mb of memory inside it, but only using 0.01% of that?
The continuous image of a connected set is connected.
User avatar
wichtounet
Member
Member
Posts: 90
Joined: Fri Nov 01, 2013 4:05 pm
Location: Fribourg, Switzerland
Contact:

Re: 8086, 80386 and x86-64 compatible instructions

Post by wichtounet »

If I'm not mistaken, you can use 32 bits register in real mode, which means you can expand a bit the code that is available.
Thor Operating System: C++ 64 bits OS: https://github.com/wichtounet/thor-os
Good osdeving!
User avatar
xenos
Member
Member
Posts: 1118
Joined: Thu Aug 11, 2005 11:00 pm
Libera.chat IRC: xenos1984
Location: Tartu, Estonia
Contact:

Re: 8086, 80386 and x86-64 compatible instructions

Post by xenos »

wichtounet wrote:If I'm not mistaken, you can use 32 bits register in real mode, which means you can expand a bit the code that is available.
Yes, but for that you need an operand size prefix, and if you run the same code with that prefix on 32 bit, it will use only 16 bit registers.
Programmers' Hardware Database // GitHub user: xenos1984; OS project: NOS
User avatar
wichtounet
Member
Member
Posts: 90
Joined: Fri Nov 01, 2013 4:05 pm
Location: Fribourg, Switzerland
Contact:

Re: 8086, 80386 and x86-64 compatible instructions

Post by wichtounet »

XenOS wrote:
wichtounet wrote:If I'm not mistaken, you can use 32 bits register in real mode, which means you can expand a bit the code that is available.
Yes, but for that you need an operand size prefix, and if you run the same code with that prefix on 32 bit, it will use only 16 bit registers.
Right, didn't thought about the reverse situation :oops:
Thor Operating System: C++ 64 bits OS: https://github.com/wichtounet/thor-os
Good osdeving!
Antti
Member
Member
Posts: 923
Joined: Thu Jul 05, 2012 5:12 am
Location: Finland

Re: 8086, 80386 and x86-64 compatible instructions

Post by Antti »

mathematician wrote:In any case, what would be the point of having a computer with (say) 8192mb of memory inside it, but only using 0.01% of that?
I was thinking some small modules that could run on all modes. The limit is 64 KiB and it is not a problem.
XenOS wrote:if you run the same code with that prefix on 32 bit, it will use only 16 bit registers.
Absolutely yes but there is more than that. If operand size prefixes are used, it would not be 8086 compatible code.
Gigasoft
Member
Member
Posts: 855
Joined: Sat Nov 21, 2009 5:11 pm

Re: 8086, 80386 and x86-64 compatible instructions

Post by Gigasoft »

You can also access memory with LODSB and STOSB. One trick you could do is make sure that your data is at virtual address 0 for 16 bit mode, 6f700000h for 32 bit mode and 0ffffffff6f700000h for 64 bit mode. Then, you can load a 16 bit immediate value into a register by adding two nops at the end, and use the resulting value as an address, or by adding two nops at the end of the instructions A0 through A3. Near jumps and calls are possible by having two nops at the destination of such jumps and calls.
Antti
Member
Member
Posts: 923
Joined: Thu Jul 05, 2012 5:12 am
Location: Finland

Re: 8086, 80386 and x86-64 compatible instructions

Post by Antti »

Actually, this is more interesting than I first thought. Segmentation could be used in 16-bit mode and the module loader would set them before code is run. Flat memory model is used in 32-bit or 64-bit mode and the module loader give the base address in higher bits. For example, if EDI is 0x8A000000, the code must not wipe out it (e.g. "XOR DI, DI").

I was planning to write a toy compiler that outputs this kind of code. I am not going to write it manually.

EDIT: I was too tired! Of course, it is the paging that solves this.
Antti
Member
Member
Posts: 923
Joined: Thu Jul 05, 2012 5:12 am
Location: Finland

Re: 8086, 80386 and x86-64 compatible instructions

Post by Antti »

I have another question that goes offtopic slightly but I do not dare to create a new thread for it. For alignment purposes, I have sometimes replaced one-byte "PUSH REG" instructions with two-byte "PUSH R/M" instructions. POP instructions are also used like this. E.g.

Code: Select all

50      PUSH AX         ; One byte
FFF0    PUSH AX         ; Two bytes
I try to be cautious so I am a little bit afraid of using longer versions. It is clear that probably no one else uses them. Could it be that there are even CPU bugs that cause troubles? The old 8086 manual says that the ModR/M version is "PUSH MEM16". I can imagine that they had thought that no one is going to use it for general purpose registers. However, there are programmers like Antti trying to use it like this. Will this lead to Halt and Catch Fire? It is quite cold here so perhaps it is not so bad. XenOS: is it cold in Tartu?
User avatar
xenos
Member
Member
Posts: 1118
Joined: Thu Aug 11, 2005 11:00 pm
Libera.chat IRC: xenos1984
Location: Tartu, Estonia
Contact:

Re: 8086, 80386 and x86-64 compatible instructions

Post by xenos »

Antti wrote:Absolutely yes but there is more than that. If operand size prefixes are used, it would not be 8086 compatible code.
Oh, right, forgot about that.
Antti wrote:It is quite cold here so perhaps it is not so bad. XenOS: is it cold in Tartu?
Well, this morning it was -24°C and my car didn't start, so some kind of heating would be nice. What's the temperature in your area?
Programmers' Hardware Database // GitHub user: xenos1984; OS project: NOS
Antti
Member
Member
Posts: 923
Joined: Thu Jul 05, 2012 5:12 am
Location: Finland

Re: 8086, 80386 and x86-64 compatible instructions

Post by Antti »

XenOS wrote:Well, this morning it was -24°C and my car didn't start, so some kind of heating would be nice. What's the temperature in your area?
About the same temperature. It should not be bad but it still tried to freeze my fingers when I went to work. Perhaps I am not used to it. My fourth generation Golf cart starts up well if the battery is alive (it is the weakest link).
Octocontrabass
Member
Member
Posts: 5513
Joined: Mon Mar 25, 2013 7:01 pm

Re: 8086, 80386 and x86-64 compatible instructions

Post by Octocontrabass »

Antti wrote:Could it be that there are even CPU bugs that cause troubles? The old 8086 manual says that the ModR/M version is "PUSH MEM16".
It's more like undefined behavior than a bug, but using the "long" pop won't work on a NEC V20. I don't know if any other CPUs have issues with those instructions.
Antti
Member
Member
Posts: 923
Joined: Thu Jul 05, 2012 5:12 am
Location: Finland

Re: 8086, 80386 and x86-64 compatible instructions

Post by Antti »

Octocontrabass wrote:It's more like undefined behavior than a bug, but using the "long" pop won't work on a NEC V20. I don't know if any other CPUs have issues with those instructions.
This is a good reason to stop using them. This is also a good example of being cautious. I felt that using uncommon instructions might be unsafe and soon after that you pointed out that there were, a surprise a surprise, CPUs that can not handle them. Of course, I should not have used murky instructions in the first place.
Antti
Member
Member
Posts: 923
Joined: Thu Jul 05, 2012 5:12 am
Location: Finland

Re: 8086, 80386 and x86-64 compatible instructions

Post by Antti »

Perhaps NASM uses instructions that are not available on 8086 and 80286 processors. It is the "AND r/m16, imm8". Hopefully I am wrong.

Code: Select all

[BITS 16]
[CPU 8086]

start:
	and ax, 0x01
Generated instructions:

Code: Select all

83 E0 01
User avatar
qw
Member
Member
Posts: 792
Joined: Mon Jan 26, 2009 2:48 am

Re: 8086, 80386 and x86-64 compatible instructions

Post by qw »

It is correct. AND r/m16, imm8 has been supported since the 8086.
Post Reply