Skeleton Analysis
LOCAL directive
The original code contained "sub sp, 46" to move the stack further down in the stack segment, allowing a free area in which to store local data. Once again, we can eliminate the need to explicitly code this. Declare all local data using the LOCAL directive, with a syntax as shown above. Incidentally the default type is WORD, so if the data is of type WORD you don’t have to declare it.
Note that you cannot initialise this data, since it is only created at execution entry to the procedure, not at assemble time.
Note also a particular problem due to the temporary nature of local data, with regard to getting its address within the program see page 60.
This local data can be referred to by name, and the assembler will do the job of equating the labels to A most useful side-effect of local labels is that the names are only recognized within the current procedure, not even inside nested procedures. This means that you can use labels elsewhere with the same names (this is a highly qualified statement: refer to page 120).
The syntax is (not part of program listing):
LOCAL label type type . STRUC
directive
Notice the data types WNDCLASS and MSGSTRUCT above. Structures are introduced back on page 65. Structures used by Windows are defined in the Include file.
WNDCLASS and MSGSTRUCT are the names of structures, and they can also be used in data declarations as the data-type, as has been done with our LOCAL declarations sl and sl is merely an instance of structure WNDCLASS, while is an instance of MSGSTRUCT.
For your reference, extracting the definition of WNDCLASS from Borland’s (not part of program listing):
MSGSTRUCT STRUC DW ? DW DW ? DD ? DD ? DD ? MSGSTRUCT ENDS
And here is the other: STRUC DW ? DD ? DW ? DW ? DW ? DW ? ? ? D D ? DD ? WNDCLASS ENDS cmp je yes: jmp cre yeslst: -Setup the mov sl. mov sl. mov sl. mov sl. mov sl. mov ax, mov sl. call LOE mov sl. call mov sl. mov sl. mov ax, mov sl. mov sl. mov sl. mov sl. Registering a window NOTE:
For 32-bit programming, all of these fields become 32 bits. The Companion Disk has
different Include files. For 16-bit Windows applications there is
and
and for 32-bit applications there is
High-level CALL
There is also an extended window class, with a structure called WNDCLASSEX, that has an extra field. It is used with
REGISTERCLASSEX(). lea ax,
call or ax, jne
cmp if no previous instance. je yeslst
jmp createwin yeslst:
-Setup the window class structure for . . . mov mov WinasmlProc mov mov mov sl.clsCbWndExtra,O mov ax,hInstance mov sl.clsHInstance,ax call O,IDI_APPLICATION mov
call LOADCURSOR O,IDC_ARROW mov mov s 1. COLOR_BACKGROUND mov ax,OFFSET mov PTR clsLpszMenuname,ax mov PTR mov PTR mov PTR
The above block of code is setting up the data structure prior to a window calling REGISTERCLASSO. Compare that with the previous program, page 99. You will see there that we had to explicitly access the stack segment between [bp] and in which the instance of the structure was kept. (Locations greater than contain the return address and passed parameters, while addresses below is the new working area for the stack.)
WORD PTR override is introduced on page 63.
High-level Now we have another high-level feature, the high-level CALL.
CALL only requires one parameter, the FAR
address of the sl data structure.
Refer back to how it was done before: after everything was loaded into the structure in the stack segment, was passed as
the FAR address required by See page 99
onwards.
Below, we do the same thing but use the name of the structure instead:
l e a
call REGISTERCLASS PASCAL,ss,ax or ax,ax
jne createwin jmp quitwinmain
The time has come to create the window on-screen. The high-level CALL has various qualifiers and can take multiple parameters.
Note that if the parameters have no defined size, they default to WORD.
Notice the qualifier PASCAL:
createwin:
call CREATEWINDOW PASCAL,ds,OFFSET ds,OFFSET szwintitle,
300, 0 400 mov hWnd,ax
call SHOWWINDOW PASCAL,ax,nCmdShow call UPDATEWINDOW PASCAL,hWnd
jmp SHORT messageloop ;go to main message loop.
You may have noticed that I have not used the FAR PTR override for the call instructions: the assembler is smart enough to know
from the FAR” declarations that the call
should be FAR. The override could be put in, but for the programmer’s information only.
P A S C A L , So, what about the PASCAL qualifier? The choices here are
B A S I C , nothing, PASCAL, C, BASIC, FORTRAN STDCALL, or PROLOG. The qualifiers available vary with different assemblers.
P R O L O G Normally, a CALL instruction just pushes the return address on tothe stack, and the RET at the end of the called procedure pops it
qualifiers off.
The PASCAL will cause the parameters to push on in the correct order and will also remove them, assembling a “RET number at the end of the procedure, as discussed above and on page 107. We require the PASCAL qualifier to call Windows functions.
We would use the C qualifier to call C functions, perhaps some third-party C library we want to use. The effect is the same, but the parameters are pushed on in the reverse order and not removed by the called routine: they are removed from the stack after execution returns from the procedure.
Whatever language we are calling, the result is that the high-level CALL instruction assembles with all of the pushes, pops, and other stack manipulations generated automatically unassemble such code and you will see something like the program of the previous chapter.
*This is the main message loop . . . lea call lea a call message1 lea a call or a. jne ;GetMess here mov a quitwinm ret
call TRANSLATEMESSAGE lea
call DISPATCHMESSAGE messageloop:
lea
call PASCAL, ss,ax, null, null, null ax,ax
jne
returns FALSE if a message... here we are quiting....
mov return wparam to windows OS. quitwinmain:
ret
WINMAINENDP
Figure 5.1: Stack upon entry to callback.
Stack Pointer SP
An instance of