This section contains an overview of how DPMI hosts switch between protected and real mode and handle stack switching. It is important to understand the host maintains the state of the client to prevent overwriting stack data or modifying segment registers.
Every DPMI task runs on four different stacks: An application ring protected mode stack, a locked protected mode stack, a real mode stack, and a DPMI host ring 0 stack.
The protected mode stack is the one the DPMI client was running on when it switched into protected mode by calling the protected mode entry point (although the client can switch to another protected mode stack if desired). The locked protected mode stack is provided by the DPMI server and is used for simulating hardware interrupts and processing real mode call-backs. The DPMI host provides the real mode stack, which is usually located in the data area provided by the client. The ring 0 stack is only accessible by the DPMI host. However, this stack may contain state information about the currently running program.
This is the stack that the client uses for normal execution in protected mode. The protected mode stack of a DPMI client can be unlocked if desired. Software interrupts executed in protected mode will be reflected on this stack.
During hardware interrupts, Int 1Ch, Int 23h, Int 24h, exceptions, and real mode call-back handling in protected mode, the DPMI will host automatically switch to a locked protected mode stack. When the interrupt or call returns, the host will return to the original protected mode stack. Note that there is only one, 4K, locked stack provided by the host. The stack will be switched onto the first time an interrupt or call is reflected to protected mode, and will be switched away from when the client returns. Subsequent nested interrupts or calls will not cause a stack switch. Software interrupts do not automatically switch stacks.
The DPMI host will provide the client with a real mode stack that is at least 200h bytes in size and will always be locked. Interrupts that are reflected into real mode, as well as calls made using the translation services, will be reflected on this stack. DPMI hosts will not automatically switch stacks for hardware interrupt processing in real mode since DOS performs this function automatically.
DPMI hosts will normally have a stack associated with each DPMI task. The DPMI client will not be able to access this stack in any way -- it is used by the host for execution at ring 0 to handle interrupts and exceptions. This stack will sometimes be used to store state information while switching modes. For example, the original SS:ESP of the protected mode program could be saved on the ring 0 stack while the DPMI host switches onto the locked protected mode stack.
DPMI hosts provide interrupt vectors for all 100h (256 decimal) interrupts for protected mode clients. When the DPMI client initializes, all interrupt vectors will point to code that will automatically reflect the interrupt to real mode (except for Int 31h and Int 21h, AH=4Ch). When a default interrupt reflection handler is executed it will switch to real mode, preserving the EAX, EBX, ECX, EDX, ESI, EDI, and EBP registers and flags, and reflect the interrupt in real mode. When the real mode interrupt returns, the default interrupt reflection code will switch back to protected mode and return with the modified values of EAX, EBX, ECX, EDX, ESI, EDI, EBP, and flags. Segment registers and the stack pointer will not be passed between modes. Therefore, any API that passes pointers or information in segment registers will need to be translated by a DOS extender.
There are three different ways a client can force a mode switch between protected and real mode:
Because DPMI hosts switch stacks automatically across mode switches, it is sometimes necessary to use the state save/restore functions while using the raw mode switch services. The host will maintain information on the "other" mode's current state. This information will include the CS:(E)IP, SS:(E)SP, and segment register values. Since the DPMI client has no way to directly access these values, it will need to call the state saving functions when performing nested mode switches.
For example, during hardware interrupts, the DPMI host will preserve the real mode's segment registers, CS:EIP, and SS:ESP on the ring 0 stack. However, they are not pushed on any stack in the VM -- They are only visible at ring 0. When the raw mode switch functions are called they will overwrite the information saved by the host. At this point, the program would return to the wrong address when the interrupt returned. For more information on state saving, refer to the documentation in section 11.6.