21.1.1 Exported Far Functions

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.