VOGONS


First post, by vladstamate

User metadata
Rank Oldbie
Rank
Oldbie

What effect does the operand size overide (66) have on JMP FAR instruction?

Normally it is like this (2x 16bit values one for segment one for offset)
66 EA xx xx xx xx

This is in 16bit segment (not yet in Protected Mode). Does it read 2 32bit values instead of 2 16bit values? Or 16bit for segment and 32bit for offset? Or...?

66 EA xx xx xx xx xx xx xx xx

Or does not have any effect at all?

YouTube channel: https://www.youtube.com/channel/UC7HbC_nq8t1S9l7qGYL0mTA
Collection: http://www.digiloguemuseum.com/index.html
Emulator: https://sites.google.com/site/capex86/
Raytracer: https://sites.google.com/site/opaqueraytracer/

Reply 1 of 7, by vladstamate

User metadata
Rank Oldbie
Rank
Oldbie

To answer my own question it seems that the operand size override in this case change the immediate address, specifically the offset to be 32bit (the segment is still 16bit). So in a 16bit segment it would look like this:

66 EA of of of of se se

where of = offset and se = segment

YouTube channel: https://www.youtube.com/channel/UC7HbC_nq8t1S9l7qGYL0mTA
Collection: http://www.digiloguemuseum.com/index.html
Emulator: https://sites.google.com/site/capex86/
Raytracer: https://sites.google.com/site/opaqueraytracer/

Reply 2 of 7, by superfury

User metadata
Rank l33t++
Rank
l33t++

That's correct. And of course it's reversed when the CS segment descriptor's D-bit is set(also reverses address size override). I've found out one odd thing, though: EMM386's V86 monitor seems to run in 16-bit protected mode? Although the TSS is 32-bit, as required for Virtual 8086 mode to work, CS is a 16-bit segment(D-bit is cleared)?

Last edited by superfury on 2018-04-02, 20:11. Edited 1 time in total.

Author of the UniPCemu emulator.
UniPCemu Git repository
UniPCemu for Android, Windows, PSP, Vita and Switch on itch.io

Reply 3 of 7, by vladstamate

User metadata
Rank Oldbie
Rank
Oldbie

However there is a complication here.

On a 386 when we execute that instruction in a 16bit segment, the EIP's 32bit value will be changed to whatever the jump points to. We also flush out the prefetch (as it is a jump). Now, where are we prefetching, executing from next? This is a 16bit segment so do I use IP (16bit) or EIP (32bit) ?

YouTube channel: https://www.youtube.com/channel/UC7HbC_nq8t1S9l7qGYL0mTA
Collection: http://www.digiloguemuseum.com/index.html
Emulator: https://sites.google.com/site/capex86/
Raytracer: https://sites.google.com/site/opaqueraytracer/

Reply 4 of 7, by superfury

User metadata
Rank l33t++
Rank
l33t++

Afaik you should always use EIP on 80386+. It's just that EIP's high 16 bits are truncated when loading it with 16-bit jumps(operand size is 16-bits). That's one of the issues of 32-bit huge real mode(unreal mode with CS.D being set and limits and base high used with large granularity). Apparently, loading CS in real mode in any way(interrupts, jumps) causes those bits to be reset, which causes an high base/limit program to come crashing down into low memory(<1MB), executing whatever's there(whatever it may be, but not intended). So it will execute e.g. JMP F000:12345678, which will run F000:5678 instead, becoming a 16-bit program until reentering protected mode or LOADALL.

In other words, besides the segment descriptor being updated internally, there are not many other differences(besides interrupts and segmentation loading logic(descriptors loading directly instead of from memory)) between protected(or for a better example simplified virtual 8086 mode looking at segment loads) and real mode. Much of the protection logic(descriptors cached, maybe even V86 bit in flags when using LOADALL(illegal (#GP) when loaded through POPFD) is still in place when using real mode. So basically, protected and V86 mode aren't extensions of real mode: real mode and Virtual 8086 mode are extensions and hacks for protected mode, for easy compatibility with the old CPUs. Hence why things like unreal mode works in the first place. I'm curious though, what V86 mode in real mode would do, when setting it up through LOADALL... Would it use Protected mode or Real mode interrupt handling? And would it load segments like in Virtual 8086 mode(full internal cached descriptor loads/construction) or like in Real mode(only loading fully when loading CS, partly otherwise)?

Author of the UniPCemu emulator.
UniPCemu Git repository
UniPCemu for Android, Windows, PSP, Vita and Switch on itch.io

Reply 5 of 7, by superfury

User metadata
Rank l33t++
Rank
l33t++

In fact, this explains a lot: http://www.os2museum.com/wp/will-the-real-rea … lease-stand-up/

Although some stuff about V86 mode seems incorrect: The V86 mode has to load more than real mode. Real mode only updates the base addresses with all registers, but Virtual 8086 mode(and Real mode loading CS only) needs to reload the entire descriptor (for all segments in Virtual 8086 mode) with real-mode compatible values(CS in real mode is confirmed, Virtual 8086 mode requires it because it needs it for proper functioning of the Virtual 8086 mode(imagine returning from the monitor or a different task with non-compatible values in the limit, access rights and special bits(B/D-bit... It would make the entire Virtual 8086 mode irrelevant mostly(and is be incorrect, as it's known that unreal mode within Virtual 8086 mode(4GB limit) is impossible)).

Edit: Also http://www.rcollins.org/ddj/Aug98/Aug98.html

Author of the UniPCemu emulator.
UniPCemu Git repository
UniPCemu for Android, Windows, PSP, Vita and Switch on itch.io

Reply 6 of 7, by superfury

User metadata
Rank l33t++
Rank
l33t++

There's somerhing I'm wondering about, though: what is the value of the resulting segment selector when loading a segment through a gate. Say a far jump to a call gate is executed. What is the resulting value of the CS register? Is it the value that's stored in the call gate(the selector field)? Or is it the original CS value that was pointing to the call gate? Both would of course have it's own implications on stuff like reloading(push/pop combinations and task switching), as they're dependent on the CPL(of SS) used?

Author of the UniPCemu emulator.
UniPCemu Git repository
UniPCemu for Android, Windows, PSP, Vita and Switch on itch.io

Reply 7 of 7, by Azarien

User metadata
Rank Oldbie
Rank
Oldbie
vladstamate wrote:

Does it read 2 32bit values instead of 2 16bit values?

Segment selectors are always 16-bit, no matter if your code is 16-bit, 32-bit, or 64-bit, and operand size overrides do not change that.
Only the size of the offset is changed.