At one point in its execution or another, every DPMI client runs on four different stacks: an application stack, a locked protected mode stack, a real mode stack, and a DPMI host stack. It is important to understand how the host maintains these stacks to fully understand the protected mode environment.
The application stack is the primary stack that the DPMI client executes on. It is initially the real mode stack that the client was on when it switched into protected mode, although nothing prevents the client from switching protected mode stacks at any point after the initial mode switch. Th application stack can be unlocked if desired. Software interrupts executed in protected mode are reflected on this stack.
The locked protected mode stack is provided by the DPMI host. The host automatically switches to this stack during servicing of hardware interrupts, software interrupts 1CH, 23H, and 24H, all exceptions, and during the execution of real mode callbacks. Subsequent nested interrupts or calls will not cause a stack switch. If the client switches off this stack, the new stack must also be locked and will become the protected mode stack until it switches back. When the interrupt or call returns, the host switches back to the original protected mode stack. Note that the host must provide a minimum of one 4 KB locked stack, and that software interrupts other than 1CH, 23H, and 24H do not use this stack. (Refer Appendix D for descriptor usage rule of locked stack.)
The real mode stack is also provided by the DPMI host, and is usually located in the DPMI host data area allocated by the client prior to its initial switch into protected mode. The real mode stack is at least 200H bytes in size and is always located in locked memory. Interrupts that are reflected to real mode, as well as calls to real mode interrupt handlers or procedures via Int 31H Functions 0300H, 0301H, or 0302H, will use this stack.
A DPMI host stack is only accessible to the DPMI host; it is used by the host to handle interrupts and exceptions that occur while the host is executing on behalf of the client. For example, when the client requests a mode switch, the original SS:(E)SP of the protected mode program can be saved on the host stack while the DPMI host switches onto the locked protected mode stack.
There are four different ways that a client can force a mode switch between protected and real mode:
Clients that use the raw mode switch services and perform nested mode switches must use the DPMI state save/restore functions (whose addresses may be obtained with Int 31H Function 0305H), causing the host to maintain information on the "other" mode's current state. This information includes the CS:(E)IP, SS:(E)SP, and other segment register contents; values that the client has no way to access directly. For example, during the service of a hardware interrupt that occurs in real mode, the DPMI host may preserve the real mode CS:(E)IP, SS:(E)SP, and segment registers on the host stack, causing a return to the wrong address when the handler finally executes the IRET.
Example: This example illustrates code that saves the state of the real mode registers using the DPMI save/restore function, switches to real mode using the raw mode switch service, issues a DOS call to open a file, switches back to protected mode using the raw mode switch service, and restores the state of the real mode registers using the save/restore function. The protected mode registers are saved by pushing them on the stack in the usual fashion. The example is intended only to show the logical sequence of execution; in a real program, the real mode and protection mode variables and functions would likely reside in separate segments.
savsiz dw 0 ; size of state information realsrs dd 0 ; far pointer to real mode ; save/restore state entry point protsrs dd 0 ; far pointer to protected mode ; save/restore state entry point realrms dd 0 ; far pointer to real mode ; raw mode switch entry point protrms dd 0 ; far pointer to protected mode ; raw mode switch entry point protdw dw 0 ; placeholder for protected mode DS protip dw 0 ; placeholder for protected mode IP protcs dw 0 ; placeholder for protected mode CS protsp dw 0 ; placeholder for protected mode SP protss dw 0 ; placeholder for protected mode SS . . . ; this code is executed during ; application initialization mov ax,305h ; get addresses of DPMI host's int 31h ; state save/restore entry points mov savsiz,ax ; save state info buffer size mov word ptr realsrs,cx ; BX:CX = state save/restore mov word ptr realsrs+2,bx ; entry point for real mode mov word ptr protsrs,di ; SI:DI = state save/restore mov word ptr protsrs+2,si ; entry point for protected mode mov ax,306h ; get address of DPMI host's int 31h ; raw mode switch entry points mov savsiz,ax ; save state info buffer size mov word ptr realrms,cx ; BX:CX = raw mode switch mov word ptr realrms+2,bx ; entry piont for real mode mov word ptr protrms,di ; SI:DI = raw mode switch mov word ptr protrms+2,si ; entry point for protected mode ; must also initialize the ; sp and realss variables . . . ; this code is executed during ; program execution callopenfile proc pusha ; save protected mode registers push es sub sp,savsiz ; allocate space on current stack mov di,sp ; to save real mode state mov ax,ss ; set ES:DI = address of buffer mov es,ax ; to receive state information xor al,al ; AL=0 for save state request call protsrs ; call state save/restore routine mov protds,ds ; save current DS for switch back mov protss,ss ; save current SS mov protsp,sp ; save current SP mov protip,offset returnfromreal ; save return IP mov protcs,cs ; save return CS mov ax,seg filename ; load real mode DS mov ds,realss ; load real mode SS mov bx,realsp ; load real mode SP mov si,seg openfile ; load real mode CS mov di,offset openfile ; load real mode IP jmp protrms ; go to openfile returnfromreal: mov ax,ss ; let ES:DI = address of buffer mov es,ax ; holding state information mov di,sp mov al,1 ; AL=1 to restore state call protsrs ; call state restore routine add sp,savsiz ; discard state info buffer pop es popa ; restore protected mode registers ret callopenfile endp . . . ; this code is executed in real mode openfile proc mov dx,offset filename mov ah,3dh ; issue Open File DOS call int 21h jc openerr ; check for error (not shown here) mov filehandle,bx ; save file handle mov ax,protds ; load protected mode DS mov dx,protss ; load protected mode SS mov bx,protsp ; load protected mode SP mov si,protcs ; load protected mode CS mov di,protip ; load protected mode IP jmp realrms openfile endp