?? prolog.txt
字號:
Data-Segment Initialization
The Windows prolog and epilog contain instructions that
initialize the DS register, setting the register to the
segment address of the application or DLL. Windows requires
callback functions, such as window, dialog box, and
enumeration procedures, to initialize the DS register
whenever they are called by Windows or an application. This
guarantees that the function accesses its own data segment
rather than the data segment of the caller.
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.
Nonexported Far Functions
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.
Exported Far Functions in a Dynamic-Link Library
Exported far functions in DLLs also require a prolog. The
prolog code in a DLL must generate a reference to the DGROUP
data segment. The SS register cannot be used because
execution occurs on the calling function's stack. Exported
far functions cannot use this method because fixups to DGROUP
are illegal for a multiple instance application.
The prolog and epilog for exported far functions in a DLL has
the following form:
mov ax, DGROUP ; get DGROUP value
push bp ; set up stack frame (optional)
mov bp, sp
push ds ; save calling function's DS
mov ds, ax ; move DGROUP to DS
...
pop ds ; restore registers
pop bp
retf
Following is an alternative form of the prolog for exported
far functions in a DLL:
mov ax, DGROUP ; get DGROUP value
push bp ; set up stack frame (optional)
mov bp, sp
push ds ; save calling function's DS
mov ds, ax ; move DGROUP to DS
sub sp, const ; allocate local storage (optional)
...
mov ds, [bp-2] ; restore registers
leave
Windows inserts the current data segment address as the second
operand (DGROUP) of the initial mov instruction.
Prologs in Real Mode
When Windows 3.0 and earlier is running in real mode, Windows
must walk each application stack whenever it moves or
discards segments. In particular, it must check each stack
for any segment addresses that may have been affected by the
segment operations.
To help Windows locate segment addresses associated with the
stack frames of far functions, the Windows prolog increments
the old frame pointer, contained in the BP register, before
saving it on the stack. Because all stack offsets, including
frame pointers, are expected to be word-aligned, incrementing
the BP register gives Windows a quick way to locate all far
function stack frames.
Windows only walks the stack in real mode. In protected mode,
selector values do not change even though Windows may move
and discard segments. Therefore, functions in protected mode
do not need to increment the BP register when they save it.
Prologs in Protected Mode
Although exported functions in protected-mode,
single-instance applications need to set the DS register,
these functions do not require the exported prolog described
in the previous section. Instead, they can use code similar
to that generated by the _loadds keyword of Borland C++.
The code generated by __loadds copies the data segment
selector to the DS register whenever the function is called.
Because a selector does not change value when the
corresponding segment is moved, there is no need to set the AX
register to the appropriate data segment address before
calling the function (or to mark the stack frame).
Functions
that use the _loadds code can be used as callback functions.
Because no prolog code is required, the functions do not need
to be exported when used in an application. Functions in DLLs
can also use the _loadds code. However, the functions must be
exported to ensure that other applications can link
dynamically to them.
In multiple-instance applications, the Windows prolog is
needed only for far functions called by Windows. For these
functions, procedure-instance addresses are required. The _
_loadds code cannot be used in multiple-instance applications.
Instead, applications should copy the SS register to the DS
register.
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -