22.2 Example of a Startup Routine

A startup routine initializes and exits a Windows application. The routine in the following example, the __astart function, shows the code needed for startup, which includes Cmacros defined in the CMACROS.INC header file. When assembled, this code is suitable for small-model Windows applications that do not use run-time libraries:

.xlist
memS = 1    ; small memory model
?DF = 1     ; Do not generate default segment definitions.
?PLM = 1;
?WIN = 1;
include cmacros.inc
.list

STACKSLOP = 256

createSeg   _TEXT,CODE,PARA,PUBLIC,CODE
createSeg NULL, NULL, PARA,PUBLIC,BEGDATA,DGROUP
createSeg _DATA,DATA, PARA,PUBLIC,DATA,   DGROUP
defGrp      DGROUP,DATA

assumes DS,DATA

sBegin      NULL
            DD  0
labelW      <PUBLIC,rsrvptrs>
maxRsrvPtrs = 5
            DW  maxRsrvPtrs
            DW  maxRsrvPtrs DUP (0)
sEnd        NULL

sBegin  DATA
staticW hPrev,0             ; Save WinMain parameters.
staticW hInstance,0
staticD lpszCmdline,0
staticW cmdShow,0
sEnd    DATA

externFP   <INITTASK>
externFP   <WAITEVENT>
externFP   <INITAPP>
externFP   <DOS3CALL>
externP    <WINMAIN>

sBegin  CODE
assumes CS,CODE

labelNP <PUBLIC,__astart>

        xor     bp,bp                   ; zero bp
        push    bp

        cCall   INITTASK                ; Initialize the task.
        or      ax,ax
        jz      noinit

        add     cx,STACKSLOP            ; Add in stack slop space.
        jc      noinit                  ; If overflow, return error.

        mov     hPrev,si
        mov     hInstance,di
        mov     word ptr lpszCmdline,bx
        mov     word ptr lpszCmdline+2,es
        mov     cmdShow,dx

        xor     ax,ax                   ; Clear initial event that
        cCall   WAITEVENT,<ax>          ;   started this task.
        cCall   INITAPP,<hInstance>     ; Initialize the queue.
        or      ax,ax
        jz      noinit

        cCall   WINMAIN,<hInstance,hPrev,lpszCmdline,cmdShow>
ix:
        mov     ah,4Ch
        cCall   DOS3CALL                ; Exit with return code from app.
noinit:
        mov     al,0FFh                 ; Exit with error code.
        jmp short ix
sEnd     CODE

        end __astart                    ; start address

Windows requires the null segment (containing the rsrvptrs array), which is
defined at the beginning of this sample. The InitTask function copies the top,
minimum, and bottom address offsets of the stack into the third, fourth, and fifth elements of the rsrvptrs array. Applications can use these offsets to check the

amount of space available on the stack. The debugging version of Windows also uses these offsets to check the stack. Applications must, therefore, not change these offsets, since doing so can cause a system debugging error (RIP).