Interesting compatibility mode behavior
Posted: Mon Jun 10, 2013 1:22 pm
Hello.
My OS runs in long mode, I also make use of 32 and 16 bit compatibility modes for some older programs of mine. There is some interesting behavior that takes place on my test machine (AMD A8 quad core) that i'd like to document and see if this is normal behavior.. based on my assumptions and what I know, it isn't.
Here is a scenario:
from 32 bit compatibility mode (im using a flat memory model with these sub modes) I do a far transfer to a 16 bit code segment. The d/b flag of this executable segment is obviously clear. The far transfer is done at the same privilege level thus no stack switch takes place. The stack my 32 bit code uses prior to the far transfer is 0x14400, I do this purposely because I have my page tables set up in such a way that since 16 bit SP will use 4400, it's valid.
However interestingly enough, I use an operand size prefix on the far transfer to the 16 bit segment (thus converting it to a 16 bit operand size since we are still in a 32 bit segment) the old EIP and selector are pushed and aligned properly however they are pushed onto the 0x14400 stack, and the 16 bit code segment continues to use the full bit width of ESP instead of (0x4400) SP. It does this with no override prefixes. Pushes are normal though at 2 bytes. I don't understand why this happens.
I also got a little bored and tested it a bit more. If from a 32 bit code segment, I do a far transfer to a 16 bit segment, but use a 32 bit operand size in the far transfer, the 16 bit code segment will run using the full EIP instead of IP.
I guess i'm just wondering if this is by design, or if I should change my stack implementation.
Thanks
My OS runs in long mode, I also make use of 32 and 16 bit compatibility modes for some older programs of mine. There is some interesting behavior that takes place on my test machine (AMD A8 quad core) that i'd like to document and see if this is normal behavior.. based on my assumptions and what I know, it isn't.
Here is a scenario:
from 32 bit compatibility mode (im using a flat memory model with these sub modes) I do a far transfer to a 16 bit code segment. The d/b flag of this executable segment is obviously clear. The far transfer is done at the same privilege level thus no stack switch takes place. The stack my 32 bit code uses prior to the far transfer is 0x14400, I do this purposely because I have my page tables set up in such a way that since 16 bit SP will use 4400, it's valid.
However interestingly enough, I use an operand size prefix on the far transfer to the 16 bit segment (thus converting it to a 16 bit operand size since we are still in a 32 bit segment) the old EIP and selector are pushed and aligned properly however they are pushed onto the 0x14400 stack, and the 16 bit code segment continues to use the full bit width of ESP instead of (0x4400) SP. It does this with no override prefixes. Pushes are normal though at 2 bytes. I don't understand why this happens.
I also got a little bored and tested it a bit more. If from a 32 bit code segment, I do a far transfer to a 16 bit segment, but use a 32 bit operand size in the far transfer, the 16 bit code segment will run using the full EIP instead of IP.
I guess i'm just wondering if this is by design, or if I should change my stack implementation.
Thanks