The easiest way to begin and end a program is to use the .STARTUP and .EXIT directives in the main module. The main module contains the starting point and usually the termination point. You do not need these directives in a module called by another module.
Summary: .STARTUP generates the start-up code required by either DOS or OS/2.
These directives make programs easy to maintain. They automatically generate code appropriate to the operating system and stack types specified with .MODEL. Thus, you can specify the program is for a different operating system or stack type by altering keywords in the .MODEL directive.
To start a program, place the .STARTUP directive where you want execution to begin. Usually, this location immediately follows the .CODE directive:
.CODE
.STARTUP
.
. ; Place executable code here
.
.EXIT
END
Note that .EXIT generates executable code, while END does not. The END directive informs the assembler that it has reached the end of the module. All modules must end with the END directive whether you use simplified or full segments.
If you do not use .STARTUP, you must give the starting address as an argument to the END directive. When .STARTUP is present, the assembler ignores any argument to END.
The code generated by .STARTUP depends on the operating system specified after .MODEL.
If your program uses DOS for its operating system (the default), the initialization code sets DS to DGROUP, and adjusts SS:SP so that it is relative to the group for near data, DGROUP. To initialize a DOS program with the default NEARSTACK attribute, .STARTUP generates the following code:
@Startup:
mov dx, DGROUP
mov ds, dx
mov bx, ss
sub bx, dx
shl bx, 1 ; If .286 or higher, this is
shl bx, 1 ; shortened to shl bx, 4
shl bx, 1
shl bx, 1
cli ; Not necessary in .286 or higher
mov ss, dx
add sp, bx
sti ; Not necessary in .286 or higher
.
.
.
END @Startup
A DOS program with the FARSTACK attribute does not need to adjust SS:SP, so it just initializes DS:
@Startup:
mov dx, DGROUP
mov ds, dx
.
.
.
END @Startup
OS/2 initializes DS so that it points to DGROUP and sets SS:SP as desired. Thus, when the OS_OS2 attribute is given, .STARTUP generates only a starting address. This does not show up in the listing file, however, since the /Sg option for listing files shows only the generated instructions.
When the program terminates, you can return an exit code to the operating system. Applications that check exit codes usually assume that an exit code of 0 means no problem occurred and that 1 means an error terminated the program. The .EXIT directive accepts the exit code as its one optional argument:
.EXIT 1 ; Return exit code 1
This directive generates a DOS interrupt or OS/2 system call, depending on the operating system specified in .MODEL. The code generated under DOS depends on the argument provided to .EXIT. One example is
mov al, value
mov ah, 04Ch
int 21h
if a return value is specified. The return value can be a constant, a memory reference, or a register that can be moved into the AL register. If no return value is specified, the first line in the example code above is not generated.
For OS/2, .EXIT invokes DosExit if you provide a prototype for DosExit and if you include OS2.LIB. The listing file shows the statements generated by INVOKE if the /Sg command-line option is specified. If you specify a return value as an expression, the code generated passes the expression instead of the register contents to the DosExit function. See Chapter 17 for information on writing programs for OS/2.