previous | toc


The Assembly Process

Creating and running an executable file involves four steps:
 

1. Assembling the source code into an object file

2. Linking the object file with other modules or libraries into an executable program

3. Loading the program into memory

4. Running the program

Once you have written your assembly-language program, MASM provides several options for assembling it. The OPTION directive has several different arguments that let you control the way MASM assembles your programs.

Conditional assembly allows you to create one source file that can generate a variety of programs, depending on the status of various conditional-assembly statements.

Generating and Running Executable Programs

This section briefly lists all the actions that take place during each of the assembly steps. You can change the behavior of some of these actions in various ways, such as using macros instead of procedures, or using the OPTION directive or conditional assembly. The other chapters in this book include specific programming methods; this section simply gives you an overview.

Assembling

The ML.EXE program does two things to create an executable program. First, it assembles the source code into an intermediate object file. Second, it calls the linker, LINK.EXE, which links the object files and libraries into an executable program.

At assembly time, the assembler:

Evaluates conditional-assembly directives, assembling if the conditions are true.

Expands macros and macro functions.

Evaluates constant expressions such as MYFLAG AND 80H, substituting the calculated value for the expression.

Encodes instructions and nonaddress operands. For example, mov cx, 13 can be encoded at assembly time because the instruction does not access memory.

Saves memory offsets as offsets from their segments.

Places segments and segment attributes in the object file.

Saves placeholders for offsets and segments (relocatable addresses).

Outputs a listing if requested.

Passes messages (such as INCLUDELIB and .DOSSEG) directly to the linker. 

For information about conditional assembly, see "Conditional Directives" in this chapter; for macros, see Chapter 9. Further details about segments and offsets are included in Chapters 2 and 3. Assembly listings are explained in Appendix C.

Linking

Once your source code is assembled, the resulting object file is passed to the linker. At this point, the linker may combine several object files into an executable program. The linker:

Combines segments according to the instructions in the object files, rearranging the positions of segments that share the same class or group.

Fills in placeholders for offsets (relocatable addresses).

Writes relocations for segments into the header of .EXE files (but not .COM files).

Writes the result as an executable program file.

Classes and groups are defined in "Defining Segment Groups" in Chapter 2. Segments and offsets are explained in Chapter 3, "Using Addresses and Pointers."

Loading

After loading the executable file into memory, the operating system:

Creates the program segment prefix (PSP) header in memory.

Allocates memory for the program, based on the values in the PSP.

Loads the program.

Calculates the correct values for absolute addresses from the relocation table.

Loads the segment registers SS, CS, DS, and ES with values that point to the proper areas of memory.

For information about segment registers, the instruction pointer (IP), and the stack pointer (SP), see "Registers" earlier in this chapter. For more information on the PSP see Help or an MS-DOS reference.

Running

To run your program, MS-DOS jumps to the program’s first instruction. Some program operations, such as resolving indirect memory operands, cannot be handled until the program runs. For a description of indirect references, see "Indirect Operands" in Chapter 7.

Using the OPTION Directive

The OPTION directive lets you modify global aspects of the assembly process. With OPTION, you can change command-line options and default arguments. These changes affect only statements that follow the OPTION keyword.

For example, you may have MASM code in which the first character of a variable, macro, structure, or field name is a dot (.). Since a leading dot causes MASM 6.1 to generate an error, you can use this statement in your program:

OPTION DOTNAME

This enables the use of the dot for the first character.

Changes made with OPTION override any corresponding command-line option. For example, suppose you compile a module with this command line (which enables M510 compatibility):

ML /Zm TEST.ASM

The assembler disables M510 compatibility options for all code following this statement:

OPTION NOM510

The following lists explain each of the arguments for the OPTION directive. Where appropriate, an underline identifies the default argument. If you wish to place more than one OPTION statement on a line, separate them by commas.
Options for M510 compatibility include:
Argument Description

CASEMAP: maptype CASEMAP:NONE (or /Cx) causes internal symbol recognition to be case sensitive and causes the case of identifiers in the .OBJ file to be the same as specified in the EXTERNDEF, PUBLIC, or COMM statement. The default is CASEMAP:NOTPUBLIC (or /Cp). It specifies case insensitivity for internal symbol recognition and the same behavior as CASEMAP:NONE for case of identifiers in .OBJ files. CASEMAP:ALL (/Cu) specifies case insensitivity for identifiers and converts all identifier names to uppercase.
DOTNAME | NODOTNAME Enables the use of the dot (.) as the leading character in variable, macro, structure, union, and member names.
M510 | NOM510 Sets all features to be compatible with MASM version 5.1, disabling the SCOPED argument and enabling OLDMACROS, DOTNAME, and, OLDSTRUCTS. OPTION M510 conditionally sets other arguments for the OPTION directive. For more information on using OPTION M510, see Appendix A.
Argument Description

OLDMACROS |  NOOLDMACROS Enables the version 5.1 treatment of macros. MASM 6.1 treats macros differently.
OLDSTRUCTS  |  NOOLDSTRUCTS Enables compatibility with MASM 5.1 for treatment of structure members. See Chapter 5 for information on structures.
SCOPED | NOSCOPED Guarantees that all labels inside procedures are local to the procedure when SCOPED (the default) is enabled.
SETIF2: TRUE | FALSE If TRUE, .ERR2 statements and IF2 and ELSEIF2 conditional blocks are evaluated on every pass. If FALSE, they are not evaluated. If SETIF2 is not specified (or implied), .ERR2, IF2, and ELSEIF2 expressions cause an error. Both the /Zm command-line argument and OPTION M510 imply SETIF2:TRUE.
Options for procedure use include:
Argument Description

LANGUAGE: langtype Specifies the default language type (C, PASCAL, FORTRAN, BASIC, SYSCALL, or STDCALL) to be used with PROC, EXTERN, and PUBLIC. This use of the OPTION directive overrides the .MODEL directive but is normally used when .MODEL is not given.
EPILOGUE: macroname Instructs the assembler to call the macroname to generate a user-defined epilogue instead of the standard epilogue code when a RET instruction is encountered. See Chapter 7.
PROLOGUE: macroname Instructs the assembler to call macroname to generate a user-defined prologue instead of generating the standard prologue code. See Chapter 7.
PROC: visibility Lets you explicitly set the default visibility as PUBLIC, EXPORT, or PRIVATE.
Other options include:
Argument Description

EXPR16 | EXPR32 Sets the expression word size to 16 or 32 bits. The default is 32 bits. The M510 argument to the OPTION directive sets the word size to 16 bits. Once set with the OPTION directive, the expression word size cannot be changed.
Argument Description

EMULATOR | NOEMULATOR Controls the generation of floating-point instructions.The NOEMULATOR option generates the coprocessor instructions directly. The EMULATOR option generates instructions with special fixup records for the linker so that the Microsoft floating-point emulator, supplied with other Microsoft languages, can be used. It produces the same result as setting the /Fpi command-line option. You can set this option only once per module.
LJMP | NOLJMP Enables automatic conditional-jump lengthening. For information about conditional-jump lengthening, see Chapter 7.
NOKEYWORD:<keywordlist> Disables the specified reserved words. For an example of the syntax for this argument, see "Reserved Words" in this chapter.
NOSIGNEXTEND Overrides the default sign-extended opcodes for the AND, OR, and XOR instructions and generates the larger non-sign-extended forms of these instructions. Provided for compatibility with NEC V25 and NEC V35 controllers.
OFFSET: offsettype Determines the result of OFFSET operator fixups. SEGMENT sets the defaults for fixups to be segment-relative (compatible with MASM 5.1). GROUP, the default, generates fixups relative to the group (if the label is in a group). FLAT causes fixups to be relative to a flat frame. (The .386 mode must be enabled to use FLAT.) See Appendix A.
READONLY | NOREADONLY Enables checking for instructions that modify code segments, thereby guaranteeing that read-only code segments are not modified. Same as the /p command-line option of MASM 5.1, except that it affects only segments with at least one assembly instruction, not all segments. The argument is useful for protected mode programs, where code segments must remain read-only.
SEGMENT: segSize Allows global default segment size to be set. Also determines the default address size for external symbols defined outside any segment. The segSize can be USE16, USE32, or FLAT.

Conditional Directives

MASM 6.1 provides conditional-assembly directives and conditional-error directives. Conditional-assembly directives let you test for a specified condition and assemble a block of statements if the condition is true. Conditional-error directives allow you to test for a specified condition and generate an assembly error if the condition is true.

Both kinds of conditional directives test assembly-time conditions, not run-time conditions. You can test only expressions that evaluate to constants during assembly. For a list of the predefined symbols often used in conditional assembly, see "Predefined Symbols," earlier in this chapter.

Conditional-Assembly Directives

The IF and ENDIF directives enclose the conditional statements. The optional ELSEIF and ELSE blocks follow the IF directive. There are many forms of the IF and ELSE directives. Help provides a complete list.

The following statements show the syntax for the IF directives. The syntax for other condition-assembly directives follow the same form.

IF expression1
ifstatements
[[ELSEIF expression2
elseifstatements]]
[[ELSE
elsestatements]]
ENDIF

The statements within an IF block can be any valid instructions, including other conditional blocks, which in turn can contain any number of ELSEIF blocks. ENDIF ends the block.

MASM assembles the statements following the IF directive only if the corresponding condition is true. If the condition is not true and the block contains an ELSEIF directive, the assembler checks to see if the corresponding condition is true. If so, it assembles the statements following the ELSEIF directive. If no IF or ELSEIF conditions are satisfied, the assembler processes only the statements following the ELSE directive.

For example, you may want to assemble a line of code only if your program defines a particular variable. In this example,

IFDEF buffer
buff BYTE buffer DUP(?)
ENDIF

the assembler allocates buff only if buffer has been previously defined.

MASM 6.1 provides the directives IF1, IF2, ELSEIF1, and ELSIF2 to grant assembly only on pass one or pass two. To use these directives, you must either enable 5.1 compatibility (with the /Zm command-line switch or OPTION M510) or set OPTION SETIF2:TRUE, as described in the previous section.

The following list summarizes the conditional-assembly directives:

The Directive Grants Assembly If

IF expression expression is true (nonzero)

IFE expressionexpression is false (zero)

IFDEF name name has been previously defined

IFNDEF namename has not been previously defined

IFB argument* argument is blank

IFNB argument*argument is not blank

IFIDN[I] arg1, arg2* arg1 equals arg2

IFDIF[I] arg1, arg2* arg1 does not equal arg2 The optional I suffix (IFIDNI and IFDIFI) makes comparisons insensitive to differences in case.

* Used only in macros.

Conditional-Error Directives

You can use conditional-error directives to debug programs and check for assembly-time errors. By inserting a conditional-error directive at a key point in your code, you can test assembly-time conditions at that point. You can also use conditional-error directives to test for boundary conditions in macros.

Like other severe errors, those generated by conditional-error directives cause the assembler to return a nonzero exit code. If MASM encounters a severe error during assembly, it does not generate the object module.

For example, the .ERRNDEF directive produces an error if the program has not defined a given label. In the following example, .ERRNDEF makes sure a label called publevel actually exists.

.ERRNDEF publevel
IF publevel LE 2
PUBLIC var1, var2
ELSE
PUBLIC var1, var2, var3
ENDIF

The conditional-error directives use the syntax given in the previous section. The following list summarizes the conditional-error directives. Note their close correspondence with the previous list of conditional-assembly directives.

The Directive Generates an Error

.ERR Unconditionally where it occurs in the source file. Usually placed within a conditional-assembly block.

.ERRE expression If expression is false (zero).

.ERRNZ expressionIf expression is true (nonzero).

.ERRDEF name If name has been defined.

.ERRNDEF nameIf name has not been defined.

.ERRB argument* If argument is blank.

.ERRNB argument*If argument is not blank.

.ERRIDN[I] arg1, arg2* If arg1 equals arg2.

.ERRDIF[I] arg1, arg2* If arg1 does not equal arg2. The optional I suffix (.ERRIDNI and .ERRDIFI) makes comparisons insensitive to case.

* Used only in macros

Two special conditional-error directives, .ERR1 and .ERR2, generate an error only on pass one or pass two. To use these directives, you must either enable 5.1 compatibility (with the /Zm command-line switch or OPTION M510) or set OPTION SETIF2:TRUE, as described in the previous section.



previous | toc