Although not required, nonexported far functions can also include prolog code that initializes the DS register. In this case, it is assumed that the function is never called by Windows or an application and that the DS register contains the correct segment address when the function is called. The prolog for a nonexported function has the following form:
mov ax, ds ; copy DS to AX
nop
push bp ; set up stack frame (optional)
mov bp, sp
push ds ; save calling function's DS
mov ds, ax ; move same value back to DS
...
pop ds ; pop same value back to DS
pop bp
retf
An alternative form of the prolog for a nonexported function follows:
push ds ; copy DS to AX
pop ax
nop
push bp ; set up stack frame (optional)
mov bp, sp
push ds ; save calling function's DS
mov ds, ax ; move same value back to DS
...
pop ds ; pop same value back to DS
pop bp
retf
A compiler should not generate the preceding code by default because it reloads the DS register with the same value two times per far call. Loading segment registers is a slow operation in protected mode and should be avoided as much as possible.