The Windows prolog used with exported far functions, such as dialog box and enumeration procedures, ensures that the DS register receives the data segment address for the application when Windows or an application calls the exported function. In Windows version 3.0 and earlier, the prolog and epilog for exported far functions have the following form:
push ds ; put DS in AX, take 3 bytes to do it,
pop ax ; so the code can be rewritten as
nop ; MOV AX, IMM when appropriate
inc bp ; push odd BP to indicate this stack
push bp ; frame corresponds to a far CALL
mov bp, sp ; set up BP to access arguments and
; local variables
push ds ; save DS
mov ds, ax ; set DS to proper data segment
sub sp, const ; allocate local storage (optional)
...
sub bp, 2 ; restore registers
mov sp, bp
pop ds
pop bp
dec bp
retf
Because Windows 3.1 does not support real mode, the inc bp and dec bp instructions are not required. Also, a variety of other changes can be made to the prolog and epilog to improve speed and reduce the size of the code. If a far function is part of an application (not part of a DLL), the SS register is already the proper value for the DS register, so calling the MakeProcInstance function is not necessary. The prolog and epilog can be modified as follows:
push bp ; set up stack frame (optional)
mov bp, sp
push ds ; save calling function's DS
push ss ; move SS to DS
pop ds
...
pop ds ; restore registers
pop bp
retf
An alternative form of the prolog and epilog for far functions follows:
push bp ; set up stack frame (optional)
mov bp, sp
push ds ; save calling function's DS
mov ax, ss ; move SS to DS
mov ds, ax
sub sp, const ; (optional) allocate local storage
...
mov ds, [bp-2] ; restore registers
leave
retf
Each of the variations of prolog and epilog code discussed previously works whether or not a far function is exported. The code can be called by an application or DLL as well as by the system.
If an application copies the contents of the SS register to the DS register, it doesn't need to call the MakeProcInstance function to obtain a procedure-instance address before calling an exported far function. Similarly, if a DLL moves the DGROUP data segment to the DS register through the AX register, the DLL doesn't need to call MakeProcInstance before calling an exported far function.
Although window procedures for an application require this same prolog, Windows loads the AX register before calling these procedures. An application, therefore, never needs to create a procedure-instance address for its window procedures.