|
|
(2 intermediate revisions by the same user not shown) |
Line 2,126: |
Line 2,126: |
| ;Constraints | | ;Constraints |
| The ''Identifier-Operand'' must resolve to a ''Record-TypeName''. | | The ''Identifier-Operand'' must resolve to a ''Record-TypeName''. |
|
| |
| ;Examples | | ;Examples |
| <pre> | | <pre> |
Line 2,197: |
Line 2,196: |
| |- | | |- |
| |LabelName | | |LabelName |
| |The Relative Frame attribute where the label is defined, and the segment offset value of the label. | | |The Relative Frame attribute where the label is defined, and the segment offset value of the label. |
| |} | | |} |
|
| |
|
Line 2,666: |
Line 2,665: |
| |- | | |- |
| |Conditional Assembly | | |Conditional Assembly |
| |Tests for a specified condition and assembles a block of statements if the condition is true. | | |Tests for a specified condition and assembles a block of statements if the condition is true. |
| |IF IFB IFDEF IFDIFI IFE IFIDN IFNB IFNDEF IF1 IF2 ELSE ENDIF | | |IF IFB IFDEF IFDIFI IFE IFIDN IFNB IFNDEF IF1 IF2 ELSE ENDIF |
| |- | | |- |
Line 2,911: |
Line 2,910: |
| The following are examples of ''EndOfLine-Comments:'' | | The following are examples of ''EndOfLine-Comments:'' |
|
| |
|
| ; Comments may be on a line all by themselves. They can be empty ... | | ; Comments may be on a line all by themselves. They can be empty ... |
| ; | | ; |
| ; They don't have to start in the first column | | ; They don't have to start in the first column |
Line 3,163: |
Line 3,162: |
|
| |
|
| '''Syntax''' | | '''Syntax''' |
| | | <pre> |
| <pre class="western">IFxx | | IFxx |
| . | | . |
| . | | . |
| . | | . |
| [ ELSEIFxx ] ( optional ) | | [ ELSEIFxx ] ( optional ) |
| . | | . |
| . | | . |
| . | | . |
| [ ELSE ] ( optional ) | | [ ELSE ] ( optional ) |
| . | | . |
| . | | . |
| . | | . |
Line 3,212: |
Line 3,211: |
|
| |
|
| '''Syntax''' | | '''Syntax''' |
| | | <pre> |
| <pre>IFxx | | IFxx |
| . | | . |
| . | | . |
| . | | . |
| [ ELSEIFxx ] ( optional ) | | [ ELSEIFxx ] ( optional ) |
| . | | . |
| . | | . |
| . | | . |
| [ ELSE ] ( optional ) | | [ ELSE ] ( optional ) |
| . | | . |
| . | | . |
| . | | . |
| ENDIF</pre> | | ENDIF</pre> |
|
| |
|
Line 3,349: |
Line 3,348: |
| <pre> | | <pre> |
| DSEG SEGMENT | | DSEG SEGMENT |
| . | | . |
| . | | . |
| . | | . |
| SYM = 0 | | SYM = 0 |
| REPEAT 16 | | REPEAT 16 |
Line 3,406: |
Line 3,405: |
|
| |
|
| '''Syntax''' | | '''Syntax''' |
| | | <pre> |
| <pre>FORC Parameter , String ( or < String > ) | | FORC Parameter , String ( or < String > ) |
| . | | . |
| . | | . |
| . | | . |
| ENDM </pre> | | ENDM </pre> |
| '''Remarks''' | | '''Remarks''' |
Line 3,508: |
Line 3,507: |
| DB NUMBERS | | DB NUMBERS |
| ENDM | | ENDM |
| . | | . |
| . | | . |
| . | | . |
| STRING <1,2,3,4> | | STRING <1,2,3,4> |
| ; PRODUCE 4 BYTES OF INTEGER NUMBERS | | ; PRODUCE 4 BYTES OF INTEGER NUMBERS |
Line 3,584: |
Line 3,583: |
| IF2 | | IF2 |
| ECHO STARTING SECOND PASS | | ECHO STARTING SECOND PASS |
| . | | . |
| . | | . |
| . | | . |
| ENDIF | | ENDIF |
|
| |
|
Line 3,593: |
Line 3,592: |
| ECHO TEXT VAL | | ECHO TEXT VAL |
| ENDM | | ENDM |
| . | | . |
| . | | . |
| . | | . |
| HERE = $ - CSEG | | HERE = $ - CSEG |
| INNER <CURRENT LOCATION>,%HERE | | INNER <CURRENT LOCATION>,%HERE |
Line 3,637: |
Line 3,636: |
| COMMENT *You can enter as many lines | | COMMENT *You can enter as many lines |
| of text between the delimiters | | of text between the delimiters |
| . | | . |
| . | | . |
| . | | . |
| as you need to describe your program.* | | as you need to describe your program.* |
|
| |
|
| ==Assembler Directives==
| | *[[ALP Programming Guide and Reference/Assembler Directives|Assembler Directives]] |
| This section describes the various types of ALP directives:
| | *[[ALP Programming Guide and Reference/Processor Reference|Processor Reference]] |
| {|class="wikitable"
| | |
| !Type!!Function!!Directives
| | *[[ALP Programming Guide and Reference/Assembler Messages|Assembler Messages]] |
| |-
| | |
| |Conditional error
| | ==Return Codes== |
| |Debugs programs and checks for assembly-time errors.
| | When ALP completes, it passes a return code back to the program that invoked it. This return code shows whether ALP completed successfully or with an error. |
| |.ERR
| | The return codes are: |
| .ERR1
| | * 0 Normal program completion. |
| .ERR2
| | * 1 User-specified file not found. |
| .ERRDEF
| | * 2 Unexpected system error. |
| .ERRNDEF
| | * 3 Terminated by user or operating system. |
| .ERRE
| | * 4 Syntax errors in input file. |
| .ERRNZ
| | * 5 Command line usage error. |
| .ERRB
| | * 6 Internal sanity check failure. |
| .ERRDIF
| |
| .ERRDIFI
| |
| .ERRIDN
| |
| .ERRIDNI
| |
| .ERRNB
| |
| |-
| |
| |Data allocation
| |
| |Allows you to create and initialize variables for use within your program.
| |
| |BYTE
| |
| DB
| |
| DD
| |
| DF
| |
| DQ
| |
| DT
| |
| DW
| |
| DWORD
| |
| FWORD
| |
| QWORD
| |
| REAL4
| |
| REAL8
| |
| REAL10
| |
| SBYTE
| |
| SDWORD
| |
| SWORD
| |
| TBYTE
| |
| WORD
| |
| |-
| |
| |Intermodule linkage
| |
| |Simplifies data sharing and a provides a high-level interface to multiple-module programming.
| |
| |COMM
| |
| END
| |
| EXTERN/EXTRN
| |
| EXTERNDEF
| |
| INCLUDELIB
| |
| NAME
| |
| PUBLIC
| |
| |-
| |
| |Listing control
| |
| |Controls the assembler listing of your source file.
| |
| |%BIN
| |
| .CREF
| |
| .LALL
| |
| .LIST
| |
| .LISTALL
| |
| .LISTIF
| |
| .LISTMACRO
| |
| .LISTMACROALL
| |
| .NOCREF
| |
| .NOLIST
| |
| .NOLISTIF
| |
| .NOLISTMACRO
| |
| PAGE
| |
| .SALL
| |
| .SFCOND
| |
| SUBTITLE
| |
| SUBTTL
| |
| .TFCOND
| |
| TITLE
| |
| .XALL
| |
| .XCREF
| |
| .XLIST
| |
| |-
| |
| |Procedure control
| |
| |Allows you to organize your code into procedures.
| |
| |PROC
| |
| LOCAL
| |
| ENDP
| |
| |-
| |
| |Processor control
| |
| |Selects processors and coprocessors.
| |
| |.186
| |
| .286
| |
| .286P
| |
| .287
| |
| .386
| |
| .386P
| |
| .387
| |
| .486
| |
| .486P
| |
| .586
| |
| .586P
| |
| .686
| |
| .686P
| |
| .8086
| |
| .8087
| |
| .MMX
| |
| .NOMMX
| |
| |-
| |
| |Segments
| |
| |Creates and manages segments.
| |
| |ALIGN
| |
| .ALPHA
| |
| .CODE
| |
| .CONST
| |
| .DATA
| |
| .DATA?
| |
| DOSSEG
| |
| .DOSSEG
| |
| ENDS
| |
| EVEN
| |
| .FARDATA
| |
| .FARDATA?
| |
| GROUP
| |
| .MODEL
| |
| ORG
| |
| SEGMENT
| |
| .SEQ
| |
| .STACK
| |
| |-
| |
| |Type definition
| |
| |Allows the creation of complex user-defined data types.
| |
| |RECORD
| |
| STRUC
| |
| STRUCT
| |
| TYPEDEF
| |
| UNION
| |
| |-
| |
| |Miscellaneous
| |
| |Provides miscellaneous functions.
| |
| |=
| |
| .ABORT
| |
| ASSUME
| |
| EQU
| |
| LABEL
| |
| OPTION
| |
| .RADIX
| |
| |}
| |
| | |
| === Conditional Error Control ===
| |
| Use conditional error control directives to debug programs and check for assembly-time errors. If you insert a conditional assembly directive in your code, you can test assembly-time conditions at that point. You can also test for boundary conditions in macros by using conditional error control directives.
| |
| | |
| Errors generated by conditional error control directives cause ALP to return a nonzero return code. If a severe error is detected during assembly, ALP does not generate the object module.
| |
| | |
| This section describes the following conditional error control directives:
| |
| :.ERR
| |
| :.ERR1
| |
| :.ERR2
| |
| :.ERRB
| |
| :.ERRDEF
| |
| :.ERRDIF
| |
| :.ERRDIFI
| |
| :.ERRE
| |
| :.ERRIDN
| |
| :.ERRIDNI
| |
| :.ERRNB
| |
| :.ERRNDEF
| |
| :.ERRNZ
| |
| | |
| ==== .ERR/.ERR1/.ERR2 (Force Assembly Error Condition) ====
| |
| The '''.ERR''', '''.ERR1''', and '''.ERR2''' directives cause errors at the points at which they occur in the source file.
| |
| | |
| '''Syntax'''
| |
| .ERR
| |
| or
| |
| .ERR1
| |
| or
| |
| .ERR2
| |
| '''Remarks'''
| |
| | |
| The '''.ERR''' directive causes an error regardless of the pass. '''.ERR1''' causes an error on the first pass only. '''.ERR2''' causes an error on the second pass only. If you use the '''-Lp:1'''option to request a first pass listing, the '''. ERR1''' error message appears on the screen and in the listing file. Like other error conditions occurring during pass one, the error generated by '''.ERR1''' does not cause the assembly to fail.
| |
| | |
| '''Example'''
| |
| | |
| This example ensures that you define either the DOS or the OS2 symbol. If you define neither, the assembler assembles the nested '''ELSE''' condition and produces an error message. The '''.ERR''' directive causes an error on each pass.
| |
| <pre>IFDEF DOS
| |
| .
| |
| .
| |
| .
| |
| ELSE
| |
| IFDEF OS2
| |
| .
| |
| .
| |
| .
| |
| ELSE
| |
| . ERR
| |
| ENDIF
| |
| ENDIF</pre>
| |
| | |
| ==== .ERRB/.ERRNB (Error if Argument Blank/Non-Blank) ====
| |
| The '''.ERRB''' and '''.ERRNB''' directives test the given ''[[#Text-Argument|Text-Argument]]''.
| |
| | |
| ;Syntax
| |
| .ERRB Text-Argument
| |
| or
| |
| .ERRNB Text-Argument
| |
| | |
| ;Remarks
| |
| If ''Text-Argument'' is blank, the '''.ERRB''' directive produces an error. If ''Text-Argument'' is not blank, '''.ERRNB''' produces an error.
| |
| | |
| You can test for the existence of parameters by using these directives within macros.
| |
| | |
| ;Example
| |
| In this example, the directives ensure that only one argument is passed to the macro. If no argument is passed to the macro, the '''.ERRB''' directive produces an error. If more than one argument is passed, the '''.ERRNB''' directive produces an error.
| |
| <pre>
| |
| WORK MACRO REALARG,TESTARG
| |
| .ERRB <REALARG> ;; Error if no parameters
| |
| .ERRNB <TESTARG> ;; Error if more than one parameter
| |
| .
| |
| .
| |
| .
| |
| ENDM
| |
| </pre>
| |
| | |
| ==== .ERRDEF/.ERRNDEF (Error if Symbol Defined/Not Defined) ====
| |
| The '''.ERRDEF''' and '''.ERRNDEF''' directives test whether a symbol has been defined.
| |
| | |
| ;Syntax
| |
| .ERRDEF Identifier
| |
| or
| |
| .ERRNDEF Identifier
| |
| | |
| ;Remarks
| |
| If ''[[#Identifier|Identifier]]'' is defined as a label, a variable, or a symbol, the '''.ERRDEF''' directive produces an error. If you have not defined ''Identifier'', '''.ERRNDEF''' produces an error. When ''Identifier'' is a forward reference, the assembler considers it undefined on the first pass and defined on the second pass.
| |
| | |
| ;Example
| |
| In this example, '''.ERRDEF''' ensures that '''SYMBOL''' is not defined before entering the blocks, and '''.ERRNDEF''' ensures that you defined '''SYMBOL''' somewhere within the blocks.
| |
| <pre>
| |
| .ERRDEF SYMBOL
| |
| IFDEF CONFIG1
| |
| .
| |
| . SYMBOL EQU 0
| |
| .
| |
| ENDIF
| |
| IFDEF CONFIG2
| |
| .
| |
| . SYMBOL EQU 1
| |
| .
| |
| ENDIF
| |
| .ERRNDEF SYMBOL</pre>
| |
| | |
| ==== .ERRDIF/.ERRDIFI (Error if Arguments are Different) ====
| |
| The '''.ERRDIF''' and '''.ERRDIFI''' directives generate an assembler error if the two ''[[#Text-Argument]]s'' are different.
| |
| | |
| ;Syntax
| |
| .ERRDIF Text-Argument-1, Text-Argument-2
| |
| or
| |
| .ERRDIFI Text-Argument-1, Text-Argument-2
| |
| | |
| ;Remarks
| |
| The '''.ERRDIF''' directive performs a case-sensitive comparision, and the '''.ERRDIFI''' directive performs a case-insensitive comparision.
| |
| | |
| ;Example
| |
| In this example, a check is made to verify that the currently opened segment is '''_TEXT'''. This helps to insure that the macro is used only from within the default near code segment, and not from a program with a memory model that uses far code pointers (MEDIUM, LARGE, or HUGE).
| |
| RETURN MACRO
| |
| ;; Use the expansion operator (%) to resolve @CurSeg equate
| |
| % .errdif <_TEXT>,<@CurSeg> ;; Must be in near .CODE segment
| |
| RETN ;; Force a near return
| |
| ENDM
| |
| | |
| ==== .ERRE/.ERRNZ (Error if Expression False/True) ====
| |
| The '''.ERRE''' and '''.ERRNZ''' directives test the value of an ''Expression''.
| |
| | |
| '''Syntax'''
| |
| .ERRE Expression
| |
| or
| |
| .ERRNZ Expression
| |
| '''Remarks'''
| |
| | |
| If the ''Expression'' evaluates to be false (zero), the '''.ERRE''' directive produces an error. If the ''Expression'' evaluates to be true (not zero), the '''.ERRNZ'''directive produces an error. The ''Expression'' must evaluate to an absolute value and cannot contain forward references.
| |
| | |
| '''Example'''
| |
| | |
| In this example, '''.ERRE''' checks the boundaries of a parameter that the program passes to the macro '''BUFFER'''. If count is less than or equal to 128, the expression that the directive tests is true (not zero) and the directive produces no error. If '''COUNT''' is greater than 128, the expression is false (zero) and the directive produces an error.
| |
| | |
| <pre>BUFFER MACRO COUNT,BNAME
| |
| .ERRE COUNT LE 128
| |
| BNAME DB COUNT DUP (0) ;; Reserve memory, but no more than 128 bytes
| |
| ENDM
| |
| | |
| BUFFER 128,BUF1 ; Data reserved - no error
| |
| BUFFER 129,BUF2 ; Error produced </pre>
| |
| | |
| ==== .ERRIDN/.ERRIDNI (Error if Arguments are Identical) ====
| |
| The '''.ERRIDN''' and '''.ERRIDNI''' directives generate an assembly error if the two ''[[#Text-Argument]]s'' are identical.
| |
| | |
| '''Syntax'''
| |
| .ERRIDN Text-Argument-1, Text-Argument-2
| |
| or
| |
| .ERRIDNI Text-Argument-1, Text-Argument-2</pre>
| |
| '''Remarks'''
| |
| | |
| The '''.ERRIDN''' directive performs a case-sensitive comparision, and the '''.ERRIDNI''' directive performs a case-insensitive comparision.
| |
| | |
| '''Example'''
| |
| | |
| In this example, '''.ERRIDN''' protects against the passing the AX register as the second parameter, because the macro does not work if this happens. This example uses the '''.ERRIDNI''' directive since the macro needs to check for all possible spellings of the AX register.
| |
| | |
| <pre>
| |
| ADDEM MACRO AD1 , AD2 , SUM
| |
| .ERRIDNI <ax>,<AD2> ;; ERROR IF AD2 is ax
| |
| MOV AX, AD1 ;; Would overwrite if AD2 were AX
| |
| ADD AX, AD2
| |
| MOV SUM, AX ;; SUM must be register or memory
| |
| ENDM</pre>
| |
| | |
| === Data Allocation ===
| |
| Data allocation statements allow you to reserve storage for your program data. To initiate a data allocation statement, an '''''Old-Style-Allocation-Directive''''' may be used, but in modes other than [[#M510]] it is preferable to use a ''Scalar-TypeName'' or ''UserDefined-TypeName'', which the assembler treats as a pseudo-directive. To introduce consistency into the descriptions, all such variations will be referred to as the '''''Allocation-TypeName'''''.
| |
| | |
| The ''Allocation-TypeName'' that you select determines the data-type of the allocated storage. An optional symbolic name may be associated with the storage, and the storage may also be initialized with specific values if so desired.
| |
| | |
| '''Syntax'''
| |
| [Name] Allocation-TypeName Initializer [,Initializer ...]
| |
| | |
| Allocation-TypeName'':''
| |
| :''Old-Style-Allocation-Directive''
| |
| :''Scalar-TypeName''
| |
| :''Record-TypeName''
| |
| :''Structure-TypeName''
| |
| :''Union-TypeName''
| |
| :''Typedef-TypeName''
| |
| | |
| '''''Old-Style-Allocation-Directive:''''' one of
| |
| DB DW DD DF DQ DT
| |
| | |
| '''Remarks'''
| |
| | |
| The various fields of the data allocation statement are described as follows:
| |
| | |
| '''''Name''''' If the ''Name''entry is present, it must be specified as a valid ''Identifier'' unique to the scope in which it appears. If the allocation statement is assembled into an open segment, the assembler converts the identifier to a ''Data-LabelName'' to allow referencing the storage by a symbolic variable name. If the allocation statement is assembled into the body of a [[#STRUCT]] or [[#UNION]] type definition, then the assembler converts the identifier to a ''Structure-FieldName'' or ''Union-FieldName''.
| |
| | |
| '''''Allocation-TypeName''''' If the ''Allocation-TypeName'' is specified as a ''Typedef- TypeName'', the assembler ''resolves'' it to its underlying data type to determine what type of initialization is to be performed.
| |
| | |
| If the ''Allocation-TypeName'' entry resolves to a ''Scalar-TypeName'' or a pointer to some other type, then the ''Initializer'' field must be specified using an expression syntax that can be resolved to a ''Scalar-Initializer-ExpressionType''. See the following section on [[#Initialization of Scalar Types]] for a full description of this topic.
| |
| | |
| If the ''Allocation-TypeName'' entry resolves to a ''Record-TypeName'', ''Structure- TypeName'', or ''Union-TypeName'', then the ''Initializer'' field must be specified using the ''Compound-Initializer'' syntax. See the following section on [[#Initialization of Aggregate Types]] for a full description of this topic.
| |
| | |
| If the ''Allocation-TypeName'' entry resolves to an array of any other type, then the ''Initializer'' field must be specified using the ''Compound-Initializer'' syntax. See the following section on [[#Initialization of Vector Types]] for a full description of this topic.
| |
| | |
| '''''Initializer''''' Each ''Initializer'' entry is an ''Expression'' that must resolve to an ''Initializer-ExpressionType'' appropriate for the type of data described by the ''Allocation-TypeName'' field.
| |
| | |
| Each ''Initializer'' entry may also be duplicated by making it the operand of a ''Duplicative-Expression''. When assembling in [[#ALP]] mode however, the '''DUP''' operator is considered obsolete and its use is discouraged. Instead, a ''Typedef-TypeName'' associated with the declaration of a true array should be used in the ''Allocation-TypeName'' field along with the appropriate compound initializer.
| |
| | |
| ==== Initialization of Scalar Types ====
| |
| A scalar data item represents a numeric quantity that may be increased or decreased in magnitude as a single unit. Thus, an ''Initializer'' expression for a scalar data item must be coded such that it resolves to a single scalar value. See the section on ''Scalar-Initializer-ExpressionType'' for the syntax and semantics of such expressions.
| |
| | |
| The old-style allocation directives (DB, DW, DD, DF, DQ, and DT) are supported in all assembler emulation modes, but for modes other than [[#M510]], the ''Scalar-TypeName'' keywords should be used instead.
| |
| | |
| When the ''Scalar-TypeName'' keywords are used instead of the old-style allocation directives, the assembler has full knowledge of the data types of the variables being created. This allows the assembler to make more intelligent code generation decisions, and it enables the assembler to correctly describe the variable in the symbolic debugging information that it generates for the source level debugger. ''[[#Scalar-TypeName]]s'' may only be used as allocation directives in the [[#ALP]] or [[#M600]] modes.
| |
| | |
| To allocate an uninitialized scalar data item, use the ''Indeterminate-Value-Alias''($) in the ''Initializer'' field.
| |
| {|class="wikitable"
| |
| !Type Name!!Data Type!!Initializer Description
| |
| |-
| |
| |DB, BYTE, or SBYTE
| |
| |Allocates 8-bit (byte) values.
| |
| |Each Initializer must be in the range from 0 to 255 (unsigned) for a DB or BYTE directive, and from -128 to 127 (signed) for a SBYTE directive.
| |
| |-
| |
| |DW, WORD, or SWORD
| |
| |Allocates 16-bit (word) values.
| |
| |Each Initializer must be in the range from 0 to 65535 (unsigned) for a DW or WORD directive, and from -32768 to 32767 (signed) for a SWORD directive.
| |
| |-
| |
| |DD, DWORD, or SDWORD
| |
| |Allocates 32-bit (double-word) values.
| |
| |If the Initializer is an integer, each must be in the range from 0 to 4,294,967,295 (unsigned) for a DD or DWORD directive, and from -2,147,483,648 to 2,147,483,647 (signed) for a SDWORD directive. If the DD directive is being used, an Initializer may also resolve to a 32-bit Floating-Point-Expression Type.
| |
| |-
| |
| |DF or FWORD
| |
| |Allocates 48-bit (6-byte far-word) values.
| |
| |Each Initializer typically specifies the full address of a 32-bit far code or data label, but normal 32-bit integer values may also be used. The processor does not support 48-bit integer operations, thus the assembler does support 48-bit integer precision when initializing such variables. These directives are typically only useful for defining pointer variables for use on 32-bit processors.
| |
| |-
| |
| |DQ or QWORD
| |
| |Allocates 64-bit (quad-word) values.
| |
| |Both DQ and QWORD allow an integer Initializer with 64-bit (8-byte) precision. If the DQ directive is being used, the Initializer field may resolve to a 64-bit Floating-Point-ExpressionType.
| |
| |-
| |
| |DT or TBYTE
| |
| |Allocates 80-bit (10-byte) values
| |
| |Both DT and TBYTE allow an integer Initializer with 80-bit (10-byte) precision. If the DT directive is being used, the Initializer field may resolve to a 80-bit Floating-Point-ExpressionType.
| |
| |-
| |
| |REAL4, REAL8, or REAL10
| |
| |Allocates real (floating-point) values of a specific size (4 bytes, 8 bytes, or 10 bytes).
| |
| |Each Initializer must resolve to a Floating-Point-ExpressionType. The assembler converts the floating-point literal to the IEEE format appropriate for the type of variable being allocated.
| |
| |}
| |
| | |
| '''Examples'''
| |
| | |
| Here are some examples of scalar initialization:
| |
| <pre>
| |
| ; Allocate some integer variables
| |
| uint8 BYTE 0, 255 ; min, max values for unsigned byte
| |
| sint8 SBYTE -128, 127 ; min, max values for signed byte
| |
| USHORT_T TYPEDEF WORD ; Define a typedef alias for WORD
| |
| ushort USHORT_T 0, 0FFFFh ; and use it as allocation type name
| |
| | |
| ; Some things to know about string-literal initializers
| |
| char BYTE "a" ; a single BYTE value (061h)
| |
| is_int WORD "ab" ; a single WORD value (06162h)
| |
| this_too DWORD "abcd" ; a single DWORD value (061626364h)
| |
| too_long WORD "abcd" ; error, expression too big for a word
| |
| string BYTE "string",0 ; but strings can allocate many bytes
| |
| | |
| ; Integers, pointers, and old-style initializations
| |
| PDWORD_T TYPEDEF PTR DWORD ; First, define a pointer type
| |
| ulong DWORD 0, 0FFFFFFFFh ; min, max values for unsigned dword
| |
| pulong PDWORD_T OFFSET ulong ; pointer to the ulong variable
| |
| old_style DD 1.314 ; old style, floats are accepted
| |
| new_int SDWORD 1.314 ; new style, error - must use integers
| |
| new_real REAL4 1314 ; new style, error - must use floats
| |
| | |
| ; Allocate some real numbers using decimal floating-point literals
| |
| float_f REAL4 123.45 ; 4-byte IEEE real
| |
| double_f REAL8 98.7654E1 ; 8-byte IEEE real
| |
| longdbl_f REAL10 1000.0E-2 ; 10-byte IEEE real
| |
| | |
| ; The same values using hexdecimal floating-point literals
| |
| float_h REAL4 42F6E666r ; 4-byte IEEE real
| |
| double_h REAL8 408EDD3B645A1CACr ; 8-byte IEEE real
| |
| longdbl_h REAL10 4002A000000000000000r ; 10-byte IEEE real</pre>
| |
| | |
| ==== Initialization of Aggregate Types ====
| |
| An aggregate data item is a collection of one or more sub-items of possibly dissimilar types that are allocated, initialized, and treated as a single unit. The sub-items usually have unique names, and their positions relative to other sub-items is significant. The assembler provides the ability to define aggregate types through use of the [[#RECORD]], [[#STRUCT]], and [[#UNION]] directives.
| |
| | |
| Initialization of an aggregate data item requires a programming notation that isolates the entire aggregate from surroundings constructs, and denotes the position of each sub-item within the aggregate. The syntax for this construct is as follows:
| |
| | |
| ''Aggregate-Initializer:''
| |
| :'''{'''[''Initializer-List'']'''}'''
| |
| :'''<'''[''Initializer-List'']'''>'''
| |
| | |
| ''Initializer-List:''
| |
| :''Initializer-Item''
| |
| :''Initializer-List'',[''LineBreak''] ''Initializer-Item''
| |
| | |
| ''Initializer-Item:''
| |
| :[''Scalar-Initializer'']
| |
| :[''Aggregate-Initializer'']
| |
| :[''Array-Initializer'']
| |
| | |
| The syntax requires that an ''Aggregate-Initializer'' be enclosed in an outer set of braces or angle brackets, but the ''Initializer-List'' or individual comma-separated ''Initializer-Item''s may be left unspecified, in which case a default initializer value is used. Commas are used to denote the position of each sub-item within the entire aggregate, and nested initializers are allowed to accommodate imbedded occurrences of other aggregates (or vector types, which share the same initializer syntax).
| |
| | |
| When initializing an instance of a union, the assembler only allows an initializer to be specified for the first field defined in the union type.
| |
| | |
| '''Examples'''
| |
| | |
| Here are some examples of aggregate initialization:
| |
| <pre>
| |
| YES equ 1
| |
| NO equ 0
| |
| MAYBE equ -1
| |
| | |
| BOOL_T typedef sbyte
| |
| | |
| IDEAS_T struct
| |
| sanctum BOOL_T ? ; For scalar data, use the ? operator
| |
| peace BOOL_T ? ; to request an uninitialized value.
| |
| pilzner BOOL_T ?
| |
| IDEAS_T ends
| |
| | |
| PROBLEM_T struct
| |
| work BOOL_T YES ; Establish default initial values that
| |
| car BOOL_T NO ; can be inherited when an instance of
| |
| house BOOL_T MAYBE ; the structure is allocated
| |
| PROBLEM_T ends
| |
| | |
| SOLUTION_T struct
| |
| fixing PROBLEM_T {} ; Outermost set of braces required even
| |
| IDEAS_T {} ; with unspecified (default) initializers
| |
| SOLUTION_T ends
| |
| | |
| DATA segment
| |
| ProblemWith PROBLEM_T { NO , , MAYBE } ; First-level structure
| |
| ThinkOf SOLUTION_T { { YES , YES , YES }, ; Intializer syntax for
| |
| { NO , NO , NO } } ; imbedded structures
| |
| DATA ends
| |
| | |
| CODE segment
| |
| assume ds : DATA
| |
| mov al, NO
| |
| or al, ProblemWith.work
| |
| or al, ProblemWith.car
| |
| or al, ProblemWith.house
| |
| jz exit
| |
| mov ThinkOf.fixing.work, NO ; References to named fields in
| |
| mov ThinkOf.fixing.car, NO ; imbedded structures must be
| |
| mov ThinkOf.fixing.house, NO ; fully qualified.
| |
| exit: mov ThinkOf.pilzner, YES ; Reference to "promoted" field
| |
| ret
| |
| CODE ends
| |
| end</pre>
| |
| | |
| ==== Initialization of Vector Types ====
| |
| A vector data item is a linear collection of one or more sub-items of identical type that are allocated, initialized, and treated as a single unit. A vector (more commonly referred to as an '''''array''''') is defined to have a specific number of items '''''n''''', which are numbered from '''''0''''' to '''''n - 1''''' and occupy a contiguous area of allocated storage. The items in the vector may be of any type, possibly even other vectors (commonly known as a '''''multi-dimensional array'''''). The assembler provides the ability to define vector types through the use of the standard ''Type-Declaration'' syntax.
| |
| | |
| The syntax required to initialize a vector is similar to that used for an aggregate data type, and is as follows:
| |
| | |
| ''Array-Initializer:''
| |
| :'''{'''[''Initializer-List''] '''}'''
| |
| :'''<'''[''Initializer-List''] '''>'''
| |
| | |
| ''Initializer-List:''
| |
| :''Initializer-Item''
| |
| :''Initializer-List'', [''LineBreak''] ''Initializer-Item''
| |
| | |
| ''Initializer-Item:''
| |
| :[''Scalar-Initializer'']
| |
| :[''Aggregate-Initializer'']
| |
| :[''Array-Initializer'']
| |
| | |
| The syntax requires that an ''Array-Initializer'' be enclosed in an outer set of braces or angle brackets, but the ''Initializer-List'' or individual comma-separated ''Initializer-Item''s may be left unspecified, in which case a default initializer value is used. Commas are used to denote the position of each sub-item within the entire array, and nested initializers are allowed to accommodate imbedded occurrences of other arrays (or aggregate types, which share the same initializer syntax).
| |
| | |
| '''Examples'''
| |
| | |
| Here are some examples of vector initialization:
| |
| <pre>
| |
| ; Data structures to define a "computer" data type
| |
| | |
| TRUE equ 1
| |
| FALSE equ 0
| |
| MB equ 1024 ; Megabytes
| |
| | |
| BOOL_T typedef BYTE ; true or false value
| |
| INCHES_T typedef BYTE ; number of inches
| |
| MONITOR_T typedef INCHES_T ; size of monitor in inches
| |
| KEYBOARD_T typedef BOOL_T ; is a keyboard installed?
| |
| MOUSE_T typedef BOOL_T ; is a mouse installed?
| |
| KBYTES_T typedef WORD ; number of kilobytes
| |
| MBYTES_T typedef WORD ; number of megabytes
| |
| FPRESENT_T typedef BOOL_T [2] ; up to two floppies installed
| |
| FSIZE_T typedef KBYTES_T [2] ; how big they are
| |
| DPRESENT_T typedef BOOL_T [4] ; up to four hardfiles installed
| |
| DSIZE_T typedef MBYTES_T [4] ; how big they are
| |
| RAM_T typedef DWORD ; how much memory we have
| |
| NAME_T typedef BYTE [64] ; what we call the system
| |
| | |
| FLOPPIES_T struct
| |
| DriveCount FPRESENT_T { TRUE, FALSE } ; assume one floppy installed
| |
| DriveSize FSIZE_T { 360, 0 } ; assume 360KB in size :-)
| |
| FLOPPIES_T ends
| |
| | |
| DRIVES_T struct
| |
| DriveCount DPRESENT_T { TRUE, FALSE, FALSE, FALSE } ; one drive installed
| |
| DriveSize DSIZE_T { 20, 0, 0, 0 } ; 20MB in size (!)
| |
| DRIVES_T ends
| |
| | |
| COMPUTER_T struct
| |
| Monitor MONITOR_T 14 ; Assume a 14 inch monitor
| |
| Keyboard BOOL_T TRUE ; We have a keyboard
| |
| Mouse BOOL_T FALSE ; but no mouse
| |
| Memory RAM_T 640 ; Assume 640KB
| |
| Floppies FLOPPIES_T {} ; Go with the defaults
| |
| HardFiles DRIVES_T {} ; Go with the defaults
| |
| ModelName NAME_T {} ; No default name
| |
| COMPUTER_T ends
| |
| | |
| DATA segment
| |
| Circa1997 COMPUTER_T \ ; initializer begins on next line
| |
| { 17, ; of course, we have a 17 " monitor
| |
| TRUE, TRUE, ; a keyboard and a mouse
| |
| 32 * MB, ; 32 Megabytes of ram
| |
| { { }, ; still one floppy
| |
| { 1440 } }, ; but it has a 1.2 MB capacity
| |
| { { , TRUE, TRUE }, ; also have second and third hardfiles
| |
| { 512, 1024, 4096 } }, ; 512MB, 1 GIG, and 4 GIG
| |
| { "Spiffatron 9000", 10, 13, ; with a fancy system name
| |
| "Acme Computers", 10, 13, 0 } }
| |
| DATA ends
| |
| end
| |
| </pre>
| |
| | |
| === Intermodule Linkage ===
| |
| To use symbols and procedures in more than one module, ALP must recognize shared data as global to all modules. ALP provides directives to simplify data sharing and a high-level interface to multiple-module programming. With these directives, you can define shared symbols and refer to them from other modules.
| |
| | |
| This section describes the following intermodule linkage directives:
| |
| :COMM
| |
| :END
| |
| :EXTERN/EXTRN
| |
| :EXTERNDEF
| |
| :INCLUDELIB
| |
| :NAME
| |
| :PUBLIC
| |
| | |
| ==== COMM (Declare Communal Variable) ====
| |
| Declares an uninitialized '''''common''''' or '''''communal''''' variable that is allocated by the linker.
| |
| | |
| '''Syntax'''
| |
| COMM [Language-Name] [Distance] Name [''[Count]'']:''TypeName''['':Size''] [, ...]
| |
| '''Remarks'''
| |
| | |
| The arguments to the '''COMM''' directive are as follows:
| |
| | |
| ''Language-Name'' Optional parameter that determines how ''Name'' is spelled when written to the object file. Used when interfacing with routines written in high-level languages. If not specified, the language defaults to the value set by [[#.MODEL]] or [[#OPTION LANGUAGE]].
| |
| | |
| '''''Distance''''' One of '''NEAR''' or '''FAR'''; determines the distance of allocated variable. If not specified, the current memory model determines the distance. The default is '''NEAR''' if no memory model is active.
| |
| | |
| '''''Name''''' The name of the variable to be allocated by the linker. This field is required.
| |
| | |
| '''''[Count]''''' Optional; if specified, this parameter must be surrounded by square brackets. The ''Count'' parameter can be thought of as a major (row) array dimension. It defaults to 1 if not specified.
| |
| | |
| '''''TypeName''''' Required parameter that specifies the type of the variable being allocated. It must be a single keyword or identifier that specifies a ''Distance-TypeName'', ''Scalar-TypeName'', or ''UserDefined-TypeName''.
| |
| | |
| '''''Size''''' ''Size'' is an optional parameter that can be thought of as a minor (column) array dimension. It defaults to 1 if not specified.
| |
| | |
| Communal variables are allocated by the linker. When the linker combines object modules together, all instances of an identically-named communal variable are merged into a single instance (union), and are uninitialized.
| |
| | |
| The allocated size of a communal variable is the largest size requested by all encountered references.
| |
| | |
| The allocation order with respect to the addresses of other global symbols is undefined; an application must not depend on the address of a communal variable being less than or greater than that of another global symbol.
| |
| | |
| A variable allocated with the '''COMM''' directive need not be declared in all referencing modules as communal; the linker matches all [[#EXTERN/EXTRN]] references with that of the communal variable. Similarly, a variable allocated in one module with the [[#PUBLIC]] directive may be declared in other modules as communal.
| |
| | |
| Since communal variables cannot be initialized and their address positions cannot be compared, use of the '''COMM''' directive is discouraged. The [[#EXTERNDEF]] directive should be used instead.
| |
| | |
| ==== END (Define End of Module and Entry Point) ====
| |
| The '''END'''directive has two functions:
| |
| *Identifies the end of the source program.
| |
| *Identifies the symbol that is the name of the entry point (through the ''Expression'' on the '''END''' directive)
| |
| | |
| '''Syntax'''
| |
| END [Expression]
| |
| '''Remarks'''
| |
| | |
| All source files must have the '''END''' directive as the last statement. Any lines following the '''END''' statement are ignored by the assembler.
| |
| | |
| When the linker builds an application program from one or more object modules, it needs to know where the entry point is for the operating system to pass initial control. If you do not specify an entry point, none is assumed. Only one module can identify a label as the entry point by specifying that label on its '''END''' statement. Any module not defining an operating system entry point must not have an entry point identified on its '''END''' statement. If you fail to define an entry point for the main module, your program may not be able to initialize correctly. It will assemble and link without error, but it cannot run.
| |
| | |
| '''Example'''
| |
| | |
| The following example is the '''END''' statement for the section of code that starts with the name '''BEGIN'''.
| |
| END BEGIN
| |
| | |
| ==== EXTERN/EXTRN (Declare External Identifier) ====
| |
| The '''EXTERN''' directive specifies a declaration for the external symbol ''Name'' so that it may be referred to within this module. The actual definition for the symbol occurs in some other module, and the linker resolves all such external declarations to a single definition for ''Name''.
| |
| | |
| '''Syntax'''
| |
| EXTERN [Language-Name] Name [(Default-Resolution)]:Type [, ...]
| |
| Where ''Type''is one of:
| |
| *'''ABS'''
| |
| *''Type-Declaration''
| |
| | |
| '''Remarks'''
| |
| | |
| The obsolete spelling for the '''EXTERN''' directive is '''EXTRN'''.
| |
| | |
| The external source module that defines the symbol must give it public visibility in the corresponding object module, which is accomplished in assembler language by declaring it with the [[#COMM]] directive, defining the symbol in association with an [[#EXTERNDEF]] or [[#PUBLIC]] directive, or by specifying the '''PUBLIC''' or '''EXPORT''' attributes in a [[#PROC]] directive.
| |
| | |
| If the '''EXTERN''' directive is given within a segment, the assembler assumes that the symbol is located within that segment. If the segment is not known, place the '''EXTERN''' directive outside all segments and either use an explicit segment prefix or an '''ASSUME''' directive.
| |
| | |
| A ''Type'' value of '''ABS''' indicates that ''Name'' is an externally-defined constant value. Local references to ''Name''are treated as immediate values having an ''Operand Size'' equal to the ''Address Size'' of the segment containing the reference.
| |
| | |
| '''Note:''' If the ''Type'' of '''EXTERN''' is '''ABS''', it may not be used anywhere in this module where conversion to an immediate value of type '''BYTE''' is required. Additionally, the defining module must define the value as a constant symbol.
| |
| | |
| '''For example:'''
| |
| FOO EQU 5
| |
| PUBLIC FOO
| |
| Use of the ''(default_resolution)'' syntax declares the external symbol ''Name'' to be a "weak" symbol, in which case the linker will pair all such declarations with the symbol ''default_resolution'' unless a standard "strong" public definition for ''Name'' is encountered during the link.
| |
| | |
| '''Example'''
| |
| {|class="wikitable"
| |
| !IN THE SAME SEGMENT||IN ANOTHER SEGMENT
| |
| |-
| |
| |IN MODULE 1:
| |
| cseg segment
| |
| public tagn
| |
| .
| |
| .
| |
| .
| |
| tagn:
| |
| .
| |
| .
| |
| .
| |
| cseg ends
| |
| IN MODULE 2:
| |
| cseg segment
| |
| extern tagn:near
| |
| .
| |
| .
| |
| .
| |
| jmp tagn
| |
| cseg ends
| |
| |IN MODULE 1:
| |
| csega segment
| |
| public tagf
| |
| .
| |
| .
| |
| .
| |
| tagf:
| |
| .
| |
| .
| |
| .
| |
| csega ends
| |
| IN MODULE 2:
| |
| extern tagf:far
| |
| csegb segment
| |
| .
| |
| .
| |
| .
| |
| jmp tagf
| |
| csegb ends
| |
| |}
| |
| | |
| ==== EXTERNDEF (Declare Global Identifier) ====
| |
| The '''EXTERNDEF''' directive combines the functionality of the [[#EXTERN/EXTRN]] and [[#PUBLIC]] directives. It provides a uniform way to declare global symbols that are to be shared across multiple modules.
| |
| | |
| '''Syntax'''
| |
| EXTERNDEF [Language-Name] Name:Type [, ...]
| |
| Where ''Type''is one of:
| |
| *'''ABS'''
| |
| *''Type-Declaration''
| |
| | |
| '''Remarks'''
| |
| | |
| A symbol declared with '''EXTERNDEF''' is treated as [[#PUBLIC]] if a definition for the symbol is encountered during the assembly, otherwise the symbol is assumed to be defined in another module and is treated as if it were declared with the [[#EXTERN/EXTRN]] directive.
| |
| | |
| '''Example'''
| |
| | |
| The following example shows how a declaration for the '''ReturnCode''' symbol can be shared between two modules (Main.asm and FileErr.asm) by way of a common header file (ErrNum.inc):
| |
| <pre>
| |
| ; ----------------------------------------------------------------------
| |
| ; ErrNum.inc
| |
| | |
| RETCODE_T typedef DWORD
| |
| | |
| RC_NoError equ 0
| |
| RC_FileNotFound equ 1
| |
| RC_SystemError equ 3
| |
| | |
| EXTERNDEF ReturnCode:RETCODE_T ; declaration
| |
| | |
| ; ----------------------------------------------------------------------
| |
| ; FileErr.asm
| |
| .386
| |
| .MODEL FLAT
| |
| INCLUDE ErrNum.inc ; bring in error number definitions
| |
| ; and declaration for ReturnCode
| |
| | |
| .CODE
| |
| ; Tell the user about the file error,
| |
| ; then make sure the program has a non-zero exit status
| |
| FileError proc
| |
| . . .
| |
| mov ReturnCode, RC_FileNotFound
| |
| ret
| |
| FileError endp
| |
| end
| |
| | |
| ; ----------------------------------------------------------------------
| |
| ; Main.asm
| |
| .386
| |
| .MODEL FLAT
| |
| INCLUDE ErrNum.inc ; bring in error number definitions
| |
| ; and declaration for ReturnCode
| |
| EXTERNDEF FileError:PROC ; This could be in a common header too
| |
| | |
| .DATA
| |
| ReturnCode RETCODE_T RC_NoError ; actual definition of ReturnCode
| |
| | |
| .CODE
| |
| Main proc
| |
| . . .
| |
| . . .
| |
| call FileError ; hypothetical error condition
| |
| . . .
| |
| . . .
| |
| mov eax, ReturnCode ; load the exit status
| |
| call Exit ; and shutdown the program
| |
| Main endp
| |
| end Main</pre>
| |
| | |
| ==== INCLUDELIB (Pass Library Name to Linker through Object File) ====
| |
| The '''INCLUDELIB''' directive is used to inform the linker that a library file of a given name is to be used when attempting to resolve external references declared by this module.
| |
| | |
| '''Syntax'''
| |
| INCLUDELIB FileName
| |
| '''Remarks'''
| |
| | |
| The ''FileName'' argument is parsed as a contiguous string of arbitrary characters, and should constitute a file name that is valid in the context where it will be used. The ''FileName'' should be coded as a <''text-literal''> if it is to contain embedded spaces or other special characters.
| |
| | |
| The assembler emits a special record into the object file which contains the string of characters given by the ''FileName'' entry. This record instructs the linker to include the named library file in its list of libraries to be searched during the process of resolving external references. The assembler attaches no other meaning to the object file record, and it is up to the linker to interpret the file name for any special meaning (such as search path information, file name extension, and so on).
| |
| | |
| Use of this directive avoids the need to explicitly reference the library name in a linker invocation parameter, and helps to avoid the problems that can arise when such parameters are specified incorrectly.
| |
| | |
| '''Example'''
| |
| INCLUDELIB OS2386.LIB
| |
| | |
| ==== NAME (Specify Module Name) ====
| |
| The '''NAME''' directive assigns a module a name.
| |
| | |
| '''Syntax'''
| |
| NAME module-name
| |
| '''Remarks'''
| |
| | |
| The '''NAME''' directive is ignored; it is provided for backward compatibility with other assemblers.
| |
| | |
| ==== PUBLIC (Make Symbol Visible to Other Modules) ====
| |
| The '''PUBLIC''' directive makes defined symbols available to other programs that are to be linked. The information referred to by the '''PUBLIC''' directive is passed to the linker.
| |
| | |
| '''Syntax'''
| |
| PUBLIC [Language-Name] Identifier[, ...]
| |
| '''Remarks'''
| |
| | |
| ''Identifier'' can be a variable or a label (including '''PROC''' labels). Register names and any symbols defined by '''EQU''' or = to floating-point numbers or integers larger than 4 bytes are incorrect entries.
| |
| | |
| '''Example'''
| |
| <pre>
| |
| PUBLIC GETINFO ; Make GETINFO visible to linker
| |
| GETINFO PROC FAR
| |
| PUSH BP ; Save caller's register
| |
| MOV BP,SP ; Get address of parameters
| |
| ; BODY OF SUBROUTINE
| |
| POP BP ; restore caller's register
| |
| RET ; return to caller
| |
| GETINFO ENDP</pre>
| |
| | |
| === Listing Control ===
| |
| ALP creates an assembler listing of your source file whenever you use a related source code directive or specify the [[#+Fl]] option on the ALP command line.
| |
| | |
| The assembler listing contains:
| |
| *Cumulative Listing Line Number
| |
| *Individual Source File Line Number
| |
| *Macro Expansion Line Number
| |
| *Macro Definition Line Number
| |
| *Macro Expansion Indentation Level
| |
| *Macro Expansion Nesting Level
| |
| *Include File Nesting Level
| |
| *Conditional Assembly Nesting Level
| |
| *True or False Conditional Flag
| |
| *Location Counter Offset Value
| |
| *Generated Machine Code Data
| |
| *Source Line Data | |
| | |
| If requested (via the [[#+Ls] ]command line option) a symbol table listing is produced that shows the names and values of all of the user-defined identifiers created during the assembly. The values of certain predefined identifiers are also show in the symbol table listing.
| |
| | |
| The symbol table listing is divided into the following categories:
| |
| *Macro Names
| |
| *Text Equate Names
| |
| *Structures/Union Type Names
| |
| *Orphaned Structure Fields
| |
| *Record Type Names
| |
| *Typedef Type Names
| |
| *Group Names
| |
| *Segment Names
| |
| *Numeric Equate Names
| |
| *Code Label Names
| |
| *Procedure Names
| |
| *Variable Names
| |
| | |
| ALP places the symbol table listing at the end of the listing output. ALP lists only the types of symbols encountered in the program. For example, if your program does not define any macros, the '''Macro Names''' section is omitted from the listing output.
| |
| | |
| This section describes the following listing control directives:
| |
| :%BIN
| |
| :.CREF
| |
| :.LALL
| |
| :.LFCOND
| |
| :.LIST
| |
| :.LISTALL
| |
| :.LISTIF
| |
| :.LISTMACRO
| |
| :.LISTMACROALL
| |
| :.NOCREF
| |
| :.NOLIST
| |
| :.NOLISTIF
| |
| :.NOLISTMACRO
| |
| :PAGE
| |
| :.SALL
| |
| :.SFCOND
| |
| :SUBTITLE
| |
| :SUBTTL
| |
| :.TFCOND
| |
| :TITLE
| |
| :.XALL
| |
| :.XCREF
| |
| :.XLIST
| |
| | |
| ==== %BIN (Set Listing Width for Object Code Field) ====
| |
| Sets the width of the object code field in the listing file to ''size'' columns.
| |
| | |
| '''Syntax'''
| |
| %BIN size
| |
| | |
| ==== .CREF/.XCREF (Control Symbol Cross Referencing) ====
| |
| The output of the cross-reference information is controlled by these directives. The default condition is the '''.CREF''' directive. When the assembler finds a '''.XCREF''' directive, cross-reference information results in no output until the assembler finds
| |
| | |
| '''Note:''' The assembler does not produce cross-referencing information. These directives are provided for source file compatibility with other assemblers.
| |
| | |
| '''Syntax'''
| |
| .CREF
| |
| or
| |
| <pre>
| |
| .XCREF [[operand[, ...]]</pre>
| |
| '''Remarks'''
| |
| | |
| The '''.XCREF''' directive can have an optional operand consisting of a list of one or more variable names suppressed in the cross-reference listing.
| |
| | |
| ==== .LFCOND (List False Conditionals) ====
| |
| You use the '''.LFCOND''' (List False Conditionals) directive to list conditional blocks that are evaluated as false.
| |
| | |
| '''Syntax'''
| |
| .LFCOND
| |
| '''Remarks'''
| |
| | |
| Equivalent to the '''.LISTIF''' directive.
| |
| | |
| '''.LFCOND''' does not have an operand. You can end this state either by issuing '''.TFCOND''', which reverts to the default state concerning listing of false conditionals (but with the default state redefined as being in the opposite state,) or by issuing the '''.SFCOND''', which suppresses the listing of false conditionals.
| |
| | |
| The assembler does not print false conditionals within macros when '''.LALL''' is set.
| |
| | |
| ==== .LIST/.XLIST (Control Listing File Output) ====
| |
| These two directives control output to the listing file.
| |
| | |
| '''Syntax'''
| |
| .LIST
| |
| or
| |
| .XLIST
| |
| '''Remarks'''
| |
| | |
| If a listing is not being created, these directives have no effect. The '''.LIST''' is the default condition. When the assembler finds an '''.XLIST''', the assembler does not list the source and the object code until it finds a '''.LIST''' directive.
| |
| | |
| ==== .LISTALL (List All Statements) ====
| |
| Starts the listing of all statements.
| |
| | |
| '''Syntax'''
| |
| .LISTALL
| |
| '''Remarks'''
| |
| | |
| Equivalent to the combination of '''.LIST''', '''.LISTIF''', and '''.LISTMACROALL'''.
| |
| | |
| ==== .LISTIF (List False Conditionals) ====
| |
| Starts the listing of all statements, including those in false conditional blocks.
| |
| | |
| '''Syntax'''
| |
| .LISTIF
| |
| '''Remarks'''
| |
| | |
| Equivalent to the combination of '''.LIST''', '''.LISTIF''', and '''.LISTMACROALL'''.
| |
| | |
| ==== .LISTMACRO/.XALL (List Code and Data Statements in Macros) ====
| |
| Starts listing of only those statements that generate code or data when processing macro expansions.
| |
| | |
| '''Syntax'''
| |
| .LISTMACRO
| |
| or
| |
| .XALL
| |
| '''Remarks'''
| |
| | |
| ALP does not support this mode; it is provided for compatibility with other assemblers.
| |
| | |
| ==== .LISTMACROALL/.LALL (List All Statements in Macros) ====
| |
| Starts listing of all statements when processing macros expansions.
| |
| | |
| '''Syntax'''
| |
| .LISTMACROALL
| |
| or
| |
| .LALL
| |
| | |
| ==== .NOCREF (Suppress Symbol Cross Referencing) ====
| |
| Suppresses the listing of symbols in the symbol table and cross-referencing output.
| |
| | |
| '''Note:''' The assembler does not produce cross-referencing information. This directive is provided for source file compatibility with other assemblers.
| |
| | |
| '''Syntax'''
| |
| .NOCREF [name[,name]...]
| |
| '''Remarks'''
| |
| | |
| If names are specified, only the given names are suppressed. Same as '''.XCREF'''.
| |
| | |
| ==== .NOLIST (Suppress List Output) ====
| |
| Suppresses program listing.
| |
| | |
| '''Syntax'''
| |
| .NOLIST
| |
| '''Remarks'''
| |
| | |
| Same as '''.XLIST'''.
| |
| | |
| ==== .NOLISTIF (Do Not List False Conditionals) ====
| |
| Suppresses listing of conditional blocks whose condition evaluates to false (0).
| |
| | |
| '''Syntax'''
| |
| .NOLISTIF
| |
| '''Remarks'''
| |
| | |
| This is the default. Same as '''.SFCOND'''.
| |
| | |
| ==== .NOLISTMACRO (Do Not List Macro Expansions) ====
| |
| Suppresses listing of macro expansion.
| |
| | |
| '''Syntax'''
| |
| .NOLISTMACRO
| |
| '''Remarks'''
| |
| | |
| Same as '''.SALL'''.
| |
| | |
| This is the default setting for ALP.
| |
| | |
| ==== PAGE (Control Listing Page Length and Width) ====
| |
| The '''PAGE''' directive controls the length and width of each listing page. Place the '''PAGE''' directive in the source file to control the format of the listing file produced during assembly.
| |
| | |
| '''Syntax'''
| |
| PAGE [operand-1][,operand-2]
| |
| or
| |
| PAGE +
| |
| '''Remarks'''
| |
| | |
| Using '''PAGE +''' or the '''PAGE''' directive without an operand entries causes the printer to go to the top of the page and increases the page number by 1. The assembler normally takes this action only when a page is full.
| |
| | |
| The ''operand-1'' entry specifies the actual number of lines that can be physically printed on the page; the default value is 66.
| |
| | |
| Use the ''operand-2'' entry to control the width of the page. The page width without a specified number is 132.
| |
| | |
| '''Note:''' The '''PAGE''' directive does not set the printer to the desired line width. For proper formatting of the listing, initialize the printer to operate at a corresponding line width before printing the listing file.
| |
| | |
| ==== SUBTITLE/SUBTTL (Specify Listing Page Subtitle) ====
| |
| Defines the subtitle displayed in the user area of each page in the listing output.
| |
| | |
| '''Syntax'''
| |
| SUBTITLE text
| |
| or
| |
| SUBTTL text
| |
| | |
| ==== .TFCOND (Toggle Listing of False Conditionals) ====
| |
| Toggles listing of false conditional blocks.
| |
| | |
| '''Syntax'''
| |
| .TFCOND
| |
| | |
| ==== TITLE (Specify Listing Page Title) ====
| |
| Defines the title displayed in the user area of each page in the listing output.
| |
| | |
| '''Syntax'''
| |
| TITLE text
| |
| | |
| === Procedure Control ===
| |
| Procedure control directives allow you to organize your code into procedures. The '''PROC''' and '''ENDP''' directives mark the beginning and end of a procedure. Also, '''PROC''' can automatically:
| |
| *Preserve higher register values that should not change but that the procedure might otherwise alter
| |
| *Set up a local stack pointer, so that you can access parameters and local variables placed on the stack
| |
| *Adjust the stack when the procedure ends
| |
| | |
| This section describes the following procedure control directives:
| |
| :'''PROC'''
| |
| :'''LOCAL'''
| |
| :'''ENDP'''
| |
| | |
| ==== PROC (Identify Code Procedure) ====
| |
| The '''PROC''' directive identifies a block of code. By dividing the code into blocks, each of which performs a distinct function, you can clarify the overall function of the complete module.
| |
| | |
| The '''PROC''' directive also identifies the procedure ''distance'' to help insure that the assembler generates the appropriate instructions for calling and returning from the procedure while maintaining the integrity of the run-time stack.
| |
| | |
| '''Syntax'''
| |
| Procedure-Name PROC [Attributes] [Register-List] [Parameter-List]
| |
| .
| |
| .
| |
| .
| |
| RET [Constant]
| |
| .
| |
| .
| |
| .
| |
| Procedure-Name ENDP
| |
| Refer to the following sections for descriptions of the optional arguments to the '''PROC''' directive:
| |
| *''Attributes''
| |
| *''Register-List''
| |
| *''Parameter-List''
| |
| | |
| '''Remarks'''
| |
| | |
| You can execute the block of code identified by the '''PROC''' directive in-line, jump to it, or start it with a '''CALL''' instruction. If the '''PROC''' is called from code that has another '''ASSUME CS''' value, you must use the appropriate '''FAR''', '''FAR16''', or '''FAR32''' ''distance attribute''.
| |
| | |
| The '''NEAR''' attribute causes any '''RET''' instruction coded within the procedure to be an intra-segment return that pops a return '''''offset''''' from the stack. You can call a '''NEAR''' subroutine only from the same segment. However, the '''FAR''' attribute causes '''RET''' to be an inter-segment return that pops both a return '''''offset''''' and a '''''segment base''''' from the stack. You can call a '''FAR''' subroutine from any segment; a '''FAR''' subroutine is usually called from a segment other than the one containing the subroutine.
| |
| | |
| '''Example'''
| |
| | |
| In this example, the '''Near_Name''' subroutine is called by the '''Far_Name''' subroutine.
| |
| | |
| <pre>
| |
| PUBLIC Far_Name
| |
| Far_Name PROC FAR
| |
| CALL Near_Name
| |
| RET ; Pops return offset and seg base value
| |
| Far_Name ENDP
| |
| | |
| PUBLIC Near_Name
| |
| Near_Name PROC NEAR
| |
| .
| |
| .
| |
| .
| |
| RET ; pops only return offset
| |
| Near_Name ENDP</pre>
| |
| You can call the '''Near_Name''' subroutine directly from a '''NEAR''' segment by using:
| |
| CALL Near_Name
| |
| A '''FAR''' segment can indirectly call the second subroutine by first calling the '''Far_Name''' subroutine with:
| |
| CALL Far_Name
| |
| A '''CALL''' to a forward-referenced symbol assumes the symbol is '''NEAR'''. If that symbol is '''FAR''', the '''CALL''' must have an override, for example:
| |
| CALL FAR PTR Forward_Reference
| |
| | |
| ===== Attributes =====
| |
| The optional fields in the ''Attributes'' argument control how the procedure is defined.
| |
| | |
| '''Syntax'''
| |
| [Distance] [Language] [Visibility]
| |
| '''Remarks'''
| |
| | |
| The various ''Attribute'' fields are defined as follows:
| |
| | |
| '''''Distance''''' Determines the type of '''CALL''' instruction that should be used to invoke the procedure, and the type of '''RET''' instruction generated by the assembler. The default is '''NEAR''' if no [[#.MODEL]] directive has been specified, or if the model has been set to '''TINY''', '''SMALL''', '''COMPACT''', or '''FLAT'''. The default is '''FAR''' if the model has been set to '''LARGE''', '''MEDIUM''', or '''HUGE'''. If the programmer is using segments with mixed address sizes ('''USE16''' and '''USE32''') on a 32-bit processor, then the '''NEAR16''', '''FAR16''', '''NEAR32''', and '''FAR32''' keywords may also be used.
| |
| | |
| '''''Language''''' Determines the calling convention used by the procedure, and the naming convention used when writing the procedure name to the object file. The calling convention defines the layout of the stack frame upon entry to the procedure and how the stack frame is destroyed upon procedure exit. See the section on ''[[#LabelName]]s'' for more information on language naming conventions.
| |
| | |
| With the '''BASIC''', '''FORTRAN''', and '''PASCAL''' calling conventions, the called procedure expects arguments to be pushed on the stack from left to right, causing the rightmost parameter to be at the lowest stack address and closest in proximity to the ''frame pointer'' (the BP or EBP register). With this arrangement, the called procedure always knows the exact amount of stack space used by the parameters, and is responsible for removing them from the stack with a '''RET''' '''''Constant''''' instruction when the procedure exits. Such procedures are unable to accept a variable number of arguments.
| |
| | |
| With the '''C''', '''STDCALL''', '''SYSCALL''', and '''OPTLINK''' calling conventions, the called procedure expects arguments to be pushed on the stack from right to left, causing the leftmost parameter to be at the lowest stack address and closest in proximity to the ''frame pointer'' (the BP or EBP register). With this arrangement, the calling procedure is free to push additional arguments on the stack, and is responsible for restoring the stack after the called procedure returns ('''STDCALL''' requires the called procedure to restore the stack if a fixed number of arguments is being passed).
| |
| | |
| With the '''OPTLINK''' 32-bit calling convention (as defined by the IBM VisualAge C/C++ Compiler environment), up to three parameters will be passed in machine registers to the called procedure, provided they not larger than a DWORD in size. The EAX, EDX, and ECX registers (respectively) are used for this purpose. Stack space for the parameters is still allocated, but the parameter values are not actually copied onto the stack. Refer to the documentation for the IBM VisualAge C++ compiler for more information on the '''OPTLINK''' calling convention.
| |
| | |
| '''''Visibility''''' Determines if the procedure name is written to the object file as a global identifier, allowing it to be referenced by other modules. The allowable values are '''PRIVATE''', '''PUBLIC''', and '''EXPORT'''. If operating in [[#M510]] mode and no [[#.MODEL]] directive with a ''Language-Name'' has been specified, then the default visibility is '''PRIVATE'''. In all other situations, the default visibility is '''PUBLIC''' unless the default has been overridden by an [[#OPTION LANGUAGE]] directive.
| |
| | |
| When the '''PRIVATE''' keyword is used, the procedure name is visible only within the defining module at assembly-time. When the visibility is '''PUBLIC''', the procedure name is made visible to other modules at link-time. The same is true of '''EXPORT''' visibility, but in this case the assembler emits a special record into the object file that causes the linker to also make the symbol visible as an exported entry point in the executable module, allowing it be called by other modules at program run-time.
| |
| | |
| ===== Register List =====
| |
| The optional ''Register-List'' defines those registers used in the body of the procedure that must be preserved on behalf of the caller. The assembler generates code to save these registers on the stack when the procedure is entered, and to restore them when the procedure exits.
| |
| | |
| '''Syntax'''
| |
| USES Register [Register ...]
| |
| '''''Register:'''''
| |
| :''16-Bit-Register''
| |
| :''32-Bit-Register''
| |
| :''Segment-Register''
| |
| | |
| '''Remarks'''
| |
| | |
| When more than one register is specified, do not use commas to separate the register keywords; use blanks or tabs instead.
| |
| | |
| ===== Parameter List =====
| |
| The optional ''Parameter-List'' defines the parameters that the caller passes to the procedure on the run-time stack.
| |
| | |
| '''Syntax'''
| |
| [,[LineBreak]] Parm-List
| |
| | |
| '''''Parm-List:'''''
| |
| :''Parm-Spec''[,[''LineBreak'']''Parm-Spec''...]
| |
| | |
| '''''Parm-Spec:'''''
| |
| :''Parameter-Name''[:''Type'']
| |
| | |
| The introductory comma in front of the ''Parm-List'' is only required if a ''LineBreak'' is used to put the first ''Parm-Spec'' on the line following the '''PROC''' directive.
| |
| | |
| The optional ''LineBreak'' entry allows you to end a ''Parm-Spec'' entry with a comma, enter an optional ''EndOfLine-Comment'' followed by a physical ''NewLine'' character, then continue the ''Parm-List'' on the next line.
| |
| | |
| '''Remarks'''
| |
| | |
| Each ''Parameter-Name'' is defined as a ''Numeric-EquateName'']] that is visible only from within the body of the procedure. The value assigned to the parameter name is an expression that defines the parameter type and its location on the stack relative to the value of the ''frame pointer'' (the BP or EBP register). The assembler automatically calculates the correct offset value based upon the size of the parameter type.
| |
| | |
| The ''Type'' field is specified as a ''Type-Declaration'' and defines the data type associated with the ''Parameter-Name''. If this field is omitted, the data type defaults to '''WORD''' if the procedure is defined within a '''USE16''' segment, and '''DWORD''' if the procedure is defined within a '''USE32''' segment.
| |
| | |
| The programmer can read from and store into the locations defined by the ''Parm-Spec'' entries as though they were regular named variables, but if the parameter names are to be combined in indexed expressions with other registers, the normal rules for specifying '''BP''' - and '''EBP''' - relative expressions must be followed.
| |
| | |
| '''Example'''
| |
| | |
| This example defines a '''ReadBuffer''' procedure to accept four arguments passed on the stack.
| |
| <pre>
| |
| .386 ; Assemble for 32-bit processors
| |
| .model flat ,syscall ; OS/2 programming model/calling convention
| |
|
| |
| EXTERN DosRead:PROC ; OS/2 DosRead() API
| |
| INCLUDELIB os2386.lib ; This lets us link to the API
| |
|
| |
| .code ; Open the code segment
| |
|
| |
| ;------------------------------------------------------------------------------
| |
| ; Call operating system to read input into a buffer
| |
| ;------------------------------------------------------------------------------
| |
| ReadBuffer PROC, ; need comma to continue the PROC statement
| |
| hFile:dword, ; parm 1: Read handle
| |
| pBuffer: ptr byte, ; parm 2: Address of input buffer
| |
| cbRead: dword, ; parm 3: Size of input buffer
| |
| pulActual:ptr dword ; parm 4: Address of byte count from read
| |
|
| |
| ; set up to call the OS/2 DosRead entry point
| |
|
| |
| PUSH pulActual ; arg 4
| |
| PUSH cbRead ; arg 3
| |
| PUSH pBuffer ; arg 2
| |
| PUSH hFile ; arg 1
| |
| CALL DosRead ; Invoke syscall (SYSTEM) function
| |
| ADD ESP, DWORD*4 ; Remove the four parameters we pushed
| |
| ; onto the stack for the DosRead call RET
| |
| ReadBuffer ENDP
| |
| </pre>
| |
| | |
| ==== LOCAL (Define Local Procedure Variables) ====
| |
| The '''LOCAL''' directive defines local stack variables from within a code procedure.
| |
| | |
| '''Syntax'''
| |
| LOCAL Local-Spec [,[LineBreak] Local-Spec...]
| |
| | |
| '''''Local-Spec:''''
| |
| :''Local-Name''[:''Type-Declaration'']
| |
| :''Local-Name[Count]''[:''Type-Declaration'']
| |
| | |
| The optional ''LineBreak'' entry allows you to end a ''Local-Spec'' entry with a comma, enter an optional ''EndOfLine-Comment'' followed by a physical ''NewLine'' character, then continue with a new ''Local-Spec'' on the next line.
| |
| | |
| '''Remarks'''
| |
| | |
| The '''LOCAL''' assembler directive can only appear within the body of a procedure. If used, the '''LOCAL''' directive(s) must immediately follow the '''PROC''' statement that encloses them, and they must appear before any instructions, code labels, or directives that modify the location counter. Multiple '''LOCAL''' directives may appear in succession.
| |
| | |
| Each ''Local-Name'' is defined as a ''Numeric-EquateName'' that is visible only from within the body of the procedure. The value assigned to the variable name is an expression that defines the type of the variable and its location on the stack relative to the value of the ''frame pointer'' (the BP or EBP register). The assembler reserves space on the stack for each local variable and automatically calculates their locations. After all ''Local-Spec'' entries have been processed, the assembler allocates the space by generating instructions to adjust the stack pointer. The assembler also generates instructions to restore the state of the stack and frame pointers when the procedure exits.
| |
| | |
| The optional ''[Count]'' entry can be used to indicate that the variable is a simple "array" of values, where ''Count'' is a constant expression. If used, the square brackets surrounding the ''Count''must be specified. Use of this notation is discouraged however, because it does not associate a "true array" data type with the variable, and cannot be viewed as such from within a symbolic debugger. ALP allows the variable to be associated with a "true array" data type through use of the native ''Type-Declaration'' syntax.
| |
| | |
| The ''Type-Declaration'' field specifies the data type to be associated with the ''Local-Name''. If this field is omitted, the data type defaults to '''WORD''' if the procedure is defined within a '''USE16''' segment, and '''DWORD''' if the procedure is defined within a '''USE32''' segment.
| |
| | |
| ;Example
| |
| <pre>
| |
| ; bootdrv.asm : Returns value of OS/2 boot drive as exit code
| |
| ; assemble as : alp +Od bootdrv.asm
| |
| ; link as : link386 /de bootdrv;
| |
|
| |
| .386 ; Assemble for 32-bit processors
| |
| .model flat, syscall ; OS/2 flat model/calling convention
| |
| .stack 4096
| |
| | |
| EXTERN DosExit:PROC ; OS/2 DosExit() API
| |
| EXTERN DosQuerySysInfo:PROC ; OS/2 DosQuerySysInfo() API
| |
| INCLUDELIB os2386.lib ; link with these routines
| |
| | |
| ; These are values taken from OS/2 API headers. See the OS/2 Toolkit
| |
| ; Control Program Programming Guide and Reference for more information.
| |
| | |
| EXIT_PROCESS EQU 1 ; for DosExit
| |
| QSV_BOOT_DRIVE EQU 5 ; For DosQuerySysInfo
| |
| | |
| ULONG TYPEDEF DWORD ; use OS/2 type convention
| |
| | |
| .code ; open code segment
| |
| | |
| main PROC
| |
| LOCAL BootDrive:ULONG ; place to put value of boot drive
| |
| | |
| ; Push parameters to DosQuerySysInfo onto the stack
| |
| | |
| PUSH sizeof BootDrive ; arg 4 : size of output buffer
| |
| LEA EAX, BootDrive ; arg 3 : Address of buffer
| |
| PUSH EAX
| |
| PUSH QSV_BOOT_DRIVE ; arg 2 : last ordinal value to return
| |
| PUSH QSV_BOOT_DRIVE ; arg 1 : first ordinal, same as last
| |
| CALL DosQuerySysInfo ; invoke API
| |
| ADD ESP, DWORD*4 ; remove the parameters from the stack
| |
| | |
| CMP EAX,0 ; Did the API succeed?
| |
| MOV EAX,0 ; if not, use zero as a return code
| |
| JNZ SomeKindOfError ; and skip around to the exit logic
| |
| MOV EAX, BootDrive ; else, return the boot drive value
| |
| SomeKindOfError:
| |
| push EAX ; exit code
| |
| push EXIT_PROCESS ; terminates all threads
| |
| call DosExit ; exit to calling process
| |
| RET ; never executed
| |
| main ENDP
| |
| | |
| END main
| |
| </pre>
| |
| | |
| ==== ENDP (Close a Procedure Definition Block) ====
| |
| Every procedure block opened with the '''PROC''' directive must be ended with the '''ENDP''' directive.
| |
| | |
| '''Syntax'''
| |
| procedure-name ENDP
| |
| | |
| '''Remarks'''
| |
| | |
| If the '''ENDP''' directive is not used with the '''PROC''' directive, an error occurs. An unmatched '''ENDP''' also causes an error.
| |
| | |
| '''Note:''' See the '''PROC''' directive in this chapter for more detail and examples of '''ENDP''' use.
| |
| | |
| '''Example'''
| |
| <pre>
| |
| PUSH AX ; Push third parameter
| |
| PUSH BX ; Push second parameter
| |
| PUSH CX ; Push first parameter
| |
| CALL ADDUP ; Call the procedure
| |
| ADD SP,6 ; Bypass the pushed parameters
| |
| .
| |
| .
| |
| .
| |
| ADDUP PROC NEAR ; Return address for near call
| |
| ; takes two bytes
| |
| PUSH BP ; Save base pointer - takes two more
| |
| ; so parameters start at 4th byte
| |
| MOV BP,SP ; Load stack into base pointer
| |
| MOV AX,[BP+4] ; Get first parameter
| |
| ; 4th byte above pointer
| |
| ADD AX,[BP+6] ; Get second parameter
| |
| ; 6th byte above pointer
| |
| ADD AX,[BP+8] ; Get third parameter
| |
| ; 8th byte above pointer
| |
| POP BP ; Restore base
| |
| RET ; Return
| |
| ADDUP ENDP
| |
| </pre>
| |
| In this example, three numbers are passed as parameters for the procedure '''ADDUP'''. Parameters are often passed to procedures by pushing them before the call so that the procedure can read them off the stack.
| |
| | |
| === Processor Control ===
| |
| ALP provides a set of directives for selecting processors and coprocessors. Once you select a processor, you must only use the instruction set available for that processor. The default is the 8086 processor. If you always want your code to run on this processor, you need not add any processor directives.
| |
| | |
| This section describes the following processor control directives:
| |
| : .8086
| |
| : .8087
| |
| : .186
| |
| : .286
| |
| : .286P
| |
| : .287
| |
| : .386
| |
| : .386P
| |
| : .387
| |
| : .486
| |
| : .486P
| |
| : .586
| |
| : .586P
| |
| : .686
| |
| : .686P
| |
| : .MMX
| |
| : .NOMMX
| |
| | |
| ==== .8086 (Select 8086 Processor Instruction Set) ====
| |
| The '''.8086''' directive tells the assembler to recognize and assemble 8086 instructions. This directive assembles only 8086 and 8088 instructions (the 8088 instructions are identical to the 8086 instructions). ALP assembles 8086 instructions by default.
| |
| | |
| '''Syntax'''
| |
| .8086
| |
| | |
| '''Remarks'''
| |
| | |
| The '''.8086'''directive does not have an operand.
| |
| | |
| '''Note:''' The '''.8086''' directive does not end ALP 8087/80287 mode.
| |
| | |
| ==== .8087 (Select 8087 Coprocessor Instruction Set) ====
| |
| The '''.8087''' directive tells the assembler to recognize and assemble 8087 instructions and data formats. ALP assembles 8087 instructions by default.
| |
| | |
| '''Syntax'''
| |
| .8087
| |
| | |
| '''Remarks'''
| |
| | |
| The '''.8087''' directive does not have an operand.
| |
| | |
| ==== .186 (Select 80186 Processor Instruction Set) ====
| |
| The '''.186''' directive tells the assembler to recognize and assemble 8086 or 8088 instructions and the additional instructions for the 80186 microprocessor.
| |
| | |
| '''Syntax'''
| |
| .186
| |
| | |
| '''Remarks'''
| |
| | |
| The '''.186''' directive does not have an operand. Use it only for programs that run on an 80186 microprocessor.
| |
| | |
| ==== .286 (Select 80286 Processor Instruction Set) ====
| |
| Enables assembly of nonprivileged instructions for the 80286 processor. Disables assembly of instructions introduced with later processors. Also enables 80287 instructions.
| |
| | |
| '''Syntax'''
| |
| .286
| |
| | |
| ==== .286P (Select 80286 Processor Protected Mode Instruction Set) ====
| |
| The '''.286P''' directive tells the assembler to recognize and assemble the protected instructions of the 80286 in addition to the 8086, 8088, and nonprotected 80286 instructions.
| |
| | |
| '''Syntax'''
| |
| .286P
| |
| | |
| '''Remarks'''
| |
| | |
| The '''.286P''' directive does not have an operand. Use it only for programs run on an 80286 processor using both protected and nonprotected instructions.
| |
| | |
| ==== .287 (Select 80287 Coprocessor Instruction Set) ====
| |
| The '''.287''' directive tells the assembler to recognize and assemble instructions for the 80287 floating point math coprocessor. The 80287 instruction set consists of all 8087 instructions, plus three additional instructions.
| |
| | |
| '''Syntax'''
| |
| .287
| |
| | |
| '''Remarks'''
| |
| | |
| The '''.287''' directive does not have an operand. Use it only for programs that have 80287 floating point instructions and run on an 80287 math coprocessor.
| |
| | |
| ==== .386 (Select 80386 Processor Instruction Set) ====
| |
| Enables assembly of nonprivileged instructions for the 80386 processor. Disables assembly of instructions introduced with later processors. Also enables 80387 instructions.
| |
| | |
| '''Syntax'''
| |
| .386
| |
| | |
| ==== .386P (Select 80386 Processor Protected Mode Instruction Set) ====
| |
| Enables assembly of all instructions (including privileged) for the 80386P processor. Disables assembly of instructions introduced with later processors. Also enables 80387 instructions.
| |
| | |
| '''Syntax'''
| |
| .386P
| |
| | |
| ==== .387 (Select 80387 Coprocessor Instruction Set) ====
| |
| Enables assembly of instructions for the 80387 coprocessor.
| |
| | |
| '''Syntax'''
| |
| .387
| |
| | |
| ==== .486 (Select 80486 Processor Instruction Set) ====
| |
| Enables assembly of instructions for the 80486 processor. Also enables 80387 (and later) floating point instructions.
| |
| | |
| '''Syntax'''
| |
| .486
| |
| | |
| '''Remarks'''
| |
| | |
| The '''.486''' directive is not available in M510 mode.
| |
| | |
| ==== .486P (Select 80486 Processor Protected Mode Instruction Set) ====
| |
| Enables assembly of all instructions (including privileged) for the 80486 processor. Also enables 80387 (and later) floating point instructions.
| |
| | |
| '''Syntax'''
| |
| .486P
| |
| | |
| '''Remarks'''
| |
| | |
| The '''.486P'''directive is not available in [[#M510]] mode.
| |
| | |
| ==== .586 (Select Pentium/586 Processor Instruction Set) ====
| |
| Enables assembly of instructions for the Pentium processor family. Also enables 80387 (and later) floating point instructions.
| |
| | |
| '''Syntax'''
| |
| .586
| |
| | |
| '''Remarks'''
| |
| | |
| The '''.586'''directive is not available in M510 mode or M600 mode.
| |
| | |
| ==== .586P (Select Pentium/586 Processor Protected Mode Instruction Set) ====
| |
| Enables assembly of all instructions (including privileged) for the Pentium processor family. Also enables 80387 (and later) floating point instructions.
| |
| | |
| '''Syntax'''
| |
| .586P
| |
| | |
| '''Remarks'''
| |
| The '''.586P''' directive is not available in M510 mode or M600 mode.
| |
| | |
| ==== .686 (Select Pentium Pro/686 Processor Instruction Set) ====
| |
| Enables assembly of instructions for the Pentium Pro processor family. Also enables 80387 (and later) floating point instructions.
| |
| | |
| '''Syntax'''
| |
| .686
| |
| | |
| '''Remarks'''
| |
| | |
| The '''.686'''directive is not available in [[#M510]] mode or [[#M600]] mode.
| |
| | |
| ==== .686P (Select Pentium Pro/686 Processor Protected Mode Instruction Set) ====
| |
| Enables assembly of all instructions (including privileged) for the Pentium Pro processor family. Also enables 80387 (and later) floating point instructions.
| |
| | |
| '''Syntax'''
| |
| .686P
| |
| | |
| '''Remarks'''
| |
| | |
| The '''.686P''' directive is not available in [[#M510]] mode or [[#M600]] mode.
| |
| | |
| ==== .MMX (Select MMX Processor Instruction Set Extensions) ====
| |
| Enables recognition of mnenomics for the MMX instruction set extensions.
| |
| | |
| '''Syntax'''
| |
| .MMX
| |
| | |
| '''Remarks'''
| |
| | |
| If 586 mnemonics (or later) are not already being recognized, the '''.MMX''' directive also causes an implicit '''.586''' directive to be executed.
| |
| | |
| Issuing any '''.486''' (or earlier) processor selection directive causes recognition of MMX mnemonics to be disabled.
| |
| | |
| If MMX mnemonics are being recognized, issuing a '''.586''' (or later) processor selection directive does not cause recognition of MMX mnemonics to be disabled. If this behavior is desired, use the '''.NOMMX''' directive.
| |
| | |
| The '''.MMX''' directive is not available in [[#M510]] mode or [[#M600]] mode.
| |
| | |
| ==== .NOMMX (Deselect MMX Processor Instruction Set Extensions) ====
| |
| Disables recognition of mnenomics for the MMX instruction set extensions.
| |
| | |
| '''Syntax'''
| |
| .NOMMX
| |
| | |
| '''Remarks'''
| |
| | |
| Does not affect recognition of instruction mnemonics for the currently selected primary processor; it only disables recognition of the MMX mnemonics.
| |
| | |
| The '''.NOMMX''' directive is not available in [[#M510]] mode or [[#M600]] mode.
| |
| | |
| '''Example'''
| |
| ; Top of file - no processor currently selected
| |
| .MMX ; enables both MMX and 586 mnemonics
| |
| .NOMMX ; 586 mnemonics still enabled
| |
| .686 ; 686 mnemonics now being recognized
| |
| .MMX ; 686 and MMX mnemonics now being recognized
| |
| .NOMMX ; 686 mnemonics still enabled
| |
| | |
| === Segments ===
| |
| A segment is a collection of instructions or data whose addresses are all relative to the same segment register. The code in your assembler language program defines and organizes segments.
| |
| | |
| You can define segments by using segment directives or full segment definitions.
| |
| | |
| This section describes the following directives used to create and manage segments:
| |
| :ALIGN
| |
| :.CODE
| |
| :.CONST
| |
| :.DATA
| |
| :.DATA?
| |
| :DOSSEG
| |
| :.DOSSEG
| |
| :ENDS
| |
| :EVEN
| |
| :.FARDATA
| |
| :.FARDATA?
| |
| :GROUP
| |
| :.MODEL
| |
| :ORG
| |
| :SEGMENT
| |
| :.SEQ
| |
| :.STACK
| |
| | |
| ==== ALIGN (Align Code or Data Item) ====
| |
| Advances the current location counter to the next byte boundary that is a multiple of ''Expression''.
| |
| | |
| '''Syntax'''
| |
| ALIGN Expression
| |
| | |
| '''Example'''
| |
| | |
| To align to a 2-byte boundary:
| |
| ALIGN 2
| |
| To align to a 4-byte boundary:
| |
| ALIGN 4
| |
| | |
| ==== .CODE (Opens Default or Named Code Segment) ====
| |
| Closes the currently opened segment (if any) and opens the default code segment or a segment with the name given by an optional ''SegmentName'' parameter. The '''.CODE''' directive may only be used if previous .MODEL directive has been processed.
| |
| | |
| '''Syntax'''
| |
| .CODE [SegmentName]
| |
| '''Remarks'''
| |
| | |
| When the ''SegmentName'' parameter is omitted from the '''.CODE''' directive, the assembler generates a default code segment whose name is determined by the memory model as follows:
| |
| {|
| |
| !Memory Model!!Value for @code
| |
| |-
| |
| |TINY||_TEXT
| |
| |-
| |
| |SMALL||_TEXT
| |
| |-
| |
| |MEDIUM||''module''_TEXT
| |
| |-
| |
| |COMPACT_TEXT||LARGE ''module''_TEXT
| |
| |-
| |
| |HUGE||''module''_TEXT
| |
| |-
| |
| |FLAT||CODE32
| |
| |}
| |
| | |
| The ''module'' entry is replaced with base file name of the top-level module being assembled.
| |
| | |
| When operating in [[#M510]] mode, the ''SegmentName'' parameter may only be specified for those memory models that allow multiple code segments (MEDIUM , LARGE, and HUGE), and the value of the [[#@code]] symbol is not altered from the default. For other modes of operation, the ''SegmentName'' parameter is allowed for any model other than TINY, and the [[#@code]] symbol is updated to reflect the ''SegmentName'' value.
| |
| | |
| ==== .CONST (Opens Default Constant Data Segment) ====
| |
| When used with '''.MODEL''', starts a constant data segment for initialized read-only data.
| |
| | |
| '''Syntax'''
| |
| .CONST
| |
| | |
| '''Remarks'''
| |
| | |
| The name of the segment is CONST32 in flat model, and CONST for all other models.
| |
| | |
| ==== .DATA (Opens Default Data Segment) ====
| |
| When used with '''.MODEL''', starts a near data segment for initialized data.
| |
| | |
| '''Syntax'''
| |
| .DATA
| |
| | |
| '''Remarks'''
| |
| | |
| The name of the segment is DATA32 in flat model, and _DATA for all other models.
| |
| | |
| ==== .DATA? (Opens Default Uninitialized Data Segment) ====
| |
| When used with '''.MODEL''', starts a near data segment for uninitialized data.
| |
| | |
| '''Syntax'''
| |
| .DATA ?
| |
| | |
| '''Remarks'''
| |
| | |
| The name of the segment is BSS32 in flat model, and _BSS for all other models.
| |
| | |
| ==== .DOSSEG/DOSSEG (Specify Standard DOS Segment Ordering) ====
| |
| Orders the segments according to the DOS segment convention: CODE first, then segments not in DGROUP, and then segments in DGROUP. The segments in DGROUP follow this order:
| |
| #Segments not in BSS or STACK
| |
| #BSS segments
| |
| #STACK segments
| |
| | |
| '''Syntax'''
| |
| .DOSSEG (preferred form) or DOSSEG
| |
| | |
| '''Remarks'''
| |
| | |
| '''.DOSSEG''' is the preferred form.
| |
| | |
| Use of this directive allows the linker to control the segment ordering according to conventions used in many high-level languages.
| |
| | |
| ==== ENDS (Close a Segment, Structure, or Union Declaration) ====
| |
| Closes a program segment opened with '''SEGMENT''' directive, or ends a structure or union definition opened with the '''STRUCT''' or '''UNION''' directives. Every '''SEGMENT''', '''STRUCT''', and '''UNION''' directive must end with a corresponding '''ENDS''' directive.
| |
| | |
| '''Syntax'''
| |
| Segment-Name ENDS or
| |
| Structure-Name ENDS
| |
| or
| |
| Union-Name ENDS
| |
| '''Remarks'''
| |
| | |
| If the '''ENDS''' directive is not used with the corresponding '''SEGMENT''', '''STRUCT''', or '''UNION''' directive, an error occurs. An unmatched '''ENDS''' also causes an error.
| |
| | |
| '''Note:''' See the [[#SEGMENT]], [[#STRUCT]], and [[#UNION]] directives for more details and examples of the use of '''ENDS'''.
| |
| | |
| '''Example'''
| |
| <pre>
| |
| CONST SEGMENT word public 'CONST'
| |
| SEG1 DW ARRAY_DATA
| |
| SEG2 DW MESSAGE_DATA
| |
| CONST ENDS
| |
| </pre>
| |
| | |
| ==== EVEN (Align Code or Data Item on an Even Boundary) ====
| |
| The '''EVEN''' directive causes the program counter to go to an even boundary (an address that begins a word). This ensures that the code or data that follows is aligned on an even boundary.
| |
| | |
| '''Syntax'''
| |
| EVEN
| |
| '''Remarks'''
| |
| | |
| If the program counter is not already at an even boundary, '''EVEN''' causes the assembler to add a '''NOP''' (no operation) instruction so that the counter reaches an even boundary. An error message occurs if '''EVEN''' is used with a byte-aligned segment. If the program counter is already at an even boundary, '''EVEN''' does nothing.
| |
| | |
| '''Example'''
| |
| | |
| Before: PC points to 0019 hex (25 decimal).
| |
| EVEN
| |
| After: PC points to 001A hex (26 decimal).
| |
| | |
| ==== .FARDATA (Opens Default or Named Far Data Segment) ====
| |
| When used with '''.MODEL''', starts a far data segment for initialized data.
| |
| | |
| '''Syntax'''
| |
| .FARDATA [SegmentName]
| |
| '''Remarks'''
| |
| | |
| If the ''SegmentName'' parameter is not specified, the assembler sets it to FAR_DATA.
| |
| | |
| ==== .FARDATA? (Opens Default or Named Uninitialized Far Data Segment) ====
| |
| When used with '''.MODEL''', starts a far data segment for uninitialized data.
| |
| | |
| '''Syntax'''
| |
| .FARDATA? [SegmentName]
| |
| '''Remarks'''
| |
| | |
| If the ''SegmentName'' parameter is not specified, the assembler sets it to FAR_BSS.
| |
| | |
| ==== GROUP (Treat Multiple Segments as a Single Unit) ====
| |
| The '''GROUP''' directive associates a group ''Name'' with one or more segments, and causes all labels and variables defined in the given segments to have addresses relative to the beginning of the group, rather than to the segments where they are defined.
| |
| | |
| '''Syntax'''
| |
| Name GROUP Segment-Name [, ...]
| |
| '''Remarks'''
| |
| | |
| Each ''Segment-Name'' entry must be a unique segment name assigned by the [[#SEGMENT]] directive. A ''Segment-Name'' entry may be a forward reference to a subsequently declared segment name.
| |
| | |
| An additional occurrence of a given group ''Name'' in a subsequent '''GROUP''' directive does not constitute a redefinition, but instead the effect is cumulative. The group ''Name'' itself is declared the first time it appears in a '''GROUP''' directive, but the group definition is not complete until the end of the source module is reached. The final group definition is the cumulative list of all unique segments named in all occurrences of a '''GROUP''' directive for that group ''Name''.
| |
| | |
| Segments in a group need not be contiguous. Segments that do not belong to the group can be loaded between segments that do belong to the group. The only restriction is that for USE16 segments the distance (in bytes) between the first byte in the first segment of the group and the last byte in the last segment must not exceed 65535 bytes.
| |
| | |
| Group names can be used with the [[#ASSUME]] directive and as an operand prefix with the segment override operation (:).
| |
| | |
| '''Example'''
| |
| | |
| The following example shows how to use the '''GROUP''' directive to combine segments:
| |
| | |
| '''In Module A:'''
| |
| <pre>
| |
| CGROUP GROUP XXX,YYY
| |
| XXX SEGMENT
| |
| ASSUME CS:CGROUP
| |
| .
| |
| .
| |
| .
| |
| XXX ENDS
| |
| YYY SEGMENT
| |
| ASSUME CS:CGROUP
| |
| .
| |
| .
| |
| .
| |
| YYY ENDS
| |
| </pre>
| |
| '''In Module B:'''
| |
| <pre>
| |
| CGROUP GROUP ZZZ
| |
| ZZZ SEGMENT
| |
| ASSUME CS:CGROUP
| |
| .
| |
| .
| |
| .
| |
| ZZZ ENDS
| |
| </pre>
| |
| The next example shows how to set '''DS''' with the paragraph number of the group called '''DGROUP'''.
| |
| | |
| '''As immediate:'''
| |
| MOV AX,DGROUP
| |
| MOV DS,AX
| |
| '''In assume:'''
| |
| ASSUME DS:DGROUP
| |
| '''As an operand prefix:'''
| |
| <pre>
| |
| MOV BX,OFFSET DGROUP:FOO
| |
| DW FOO
| |
| DW DGROUP:FOO</pre>
| |
| '''Note:'''
| |
| # '''DW FOO''' returns the offset of the symbol within its segment.
| |
| # '''DW DGROUP:FOO''' returns the offset of the symbol within the group.
| |
| | |
| The next example shows how you can use the '''GROUP''' directive to create a '''.COM''' file type.
| |
| <pre>
| |
| PAGE ,132
| |
| TITLE GRPCOM - Use GROUP to create a DOS.COM file
| |
| ; Use the DOS EXE2BIN utility to convert GRPCOM.EXE to GRPCOM.COM.
| |
| | |
| CG GROUP CSEG,DSEG ; ALL SEGS IN ONE GROUP
| |
| DISPLAY MACRO TEXT
| |
| LOCAL MSG
| |
| DSEG SEGMENT BYTE PUBLIC 'DATA'
| |
| MSG DB TEXT,13,10,"$"
| |
| DSEG ENDS
| |
| ;; Macro produces partly in DSEG,
| |
| ;; partly in CSEG
| |
| MOV AH,9
| |
| MOV DX,OFFSET CG:MSG
| |
| ;; Note use of group name
| |
| ;; in producing offset
| |
| INT 21H
| |
| ENDM
| |
| DSEG SEGMENT BYTE PUBLIC 'DATA'
| |
| ; Insert local constants and work areas here
| |
| DSEG ENDS
| |
| CSEG SEGMENT BYTE PUBLIC 'CODE'
| |
| ASSUME CS:CG, DS:CG, SS:CG, ES:CG ; SET BY LOADER
| |
| ORG 100H ; Skip to end of the PSP
| |
| ENTPT PROC NEAR ; COM file entry at 0100H
| |
| DISPLAY "USING MORE THAN ONE SEGMENT"
| |
| DISPLAY "YET STILL OBEYING .COM RULES"
| |
| RET ; Near return to DOS
| |
| ENTPT ENDP
| |
| CSEG ENDS
| |
| END ENTPT
| |
| </pre>
| |
| | |
| ==== .MODEL (Define Program Memory Segmentation Model) ====
| |
| The '''''.MODEL''''' directive establishes a predefined set of definitions, conventions, and modifications to various default operating behaviors of the assembler. These adjustments are designed to simply certain programming tasks and to allow a more seamless integration with routines written in high level languages.
| |
| | |
| ;Syntax
| |
| .MODEL Memory-Model [,Language-Type][,OS-Type][,Stack-Distance]
| |
| '''''Memory-Model:'''''
| |
| :'''TINY'''
| |
| :'''SMALL'''
| |
| :'''COMPACT'''
| |
| :'''MEDIUM'''
| |
| :'''LARGE'''
| |
| :'''HUGE'''
| |
| :'''FLAT'''
| |
| | |
| '''''Language-Type:'''''
| |
| :'''BASIC'''
| |
| :'''C'''
| |
| :'''FORTRAN'''
| |
| :'''OPTLINK'''
| |
| :'''PASCAL'''
| |
| :'''STDCALL'''
| |
| :'''SYSCALL'''
| |
| | |
| '''''OS-Type:'''''
| |
| :'''OS_DOS'''
| |
| :'''OS_OS2'''
| |
| | |
| '''''Stack-Distance:'''''
| |
| :'''FARSTACK'''
| |
| :'''NEARSTACK'''
| |
| | |
| ;Remarks
| |
| The '''''.MODEL''''' directive should be placed at the top of the file, after any [[#processor control]] directives, but before any of the following simplified segmentation directives are encountered:
| |
| *[[#.CODE]]
| |
| *[[#.CONST]]
| |
| *[[#.DATA]]
| |
| *[[#.DATA?]]
| |
| *[[#.FARDATA]
| |
| *[[#.FARDATA?]]
| |
| *[[#.STACK]]
| |
| | |
| Each of these directives close any segment that is currently opened, then open a different segment whose name and attributes are determined by the ''Memory-Model'' argument.
| |
| | |
| ;Memory-Model
| |
| The fundamental purpose of establishing a programming memory model is to define how the program will be organized within the constraints of the segmented processor architecture. It defines whether there are single or multiple default code and data segments, or whether the default code and data segments are merged into a single segment. The operating system upon which the program will run is a determining factor of which memory models can be used. The following table describes these relationships.
| |
| {| class="wikitable"
| |
| !Memory Model!!Default Code!!Default Data!!Merged? !!Operating Systems
| |
| |-
| |
| |Tiny||Near||Near||Yes||DOS
| |
| |-
| |
| |Small||Near||Near||No||DOS, 16-Bit OS/2, Win16
| |
| |-
| |
| |Medium||Far||Near||No||DOS, 16-Bit OS/2, Win16
| |
| |-
| |
| |Compact||Near||Far||No||DOS, 16-Bit OS/2, Win16
| |
| |-
| |
| |Large||Far||Far||No||DOS, 16-Bit OS/2, Win16
| |
| |-
| |
| |Huge||Far||Far||No||DOS, 16-Bit OS/2, Win16
| |
| |-
| |
| |Flat||Near||Near||Yes||32-Bit OS/2, Win32
| |
| |}
| |
| The assembler creates the default code and data segments, then automatically generates an [[#ASSUME]] CS:[[#@code]] and an [[#ASSUME]] DS:[[#@data]] statement to refer to them.
| |
| | |
| '''Language-Type'''
| |
| | |
| Specifies the default naming convention for all public identifiers written that to the object file, and the method whereby parameters are passed to procedures (the '''''calling convention'''''). See the section on the [[#PROC]] directive for a detailed explanation of the effects of the ''Language-Type'' setting.
| |
| | |
| '''OS-Type'''
| |
| | |
| This parameter identifies the target operating system upon which the program will run, and is provided for compatibility with other assemblers. ALP ignores this parameter.
| |
| | |
| '''Stack-Distance'''
| |
| | |
| The '''NEARSTACK''' parameter causes the assembler to assume that the stack segment and the default data segment are the same, and that the DS register is equal to the SS register. This is the default setting. The assembler performs an automatic [[#ASSUME]] SS:[[#@data]] statement when a near stack is used.
| |
| | |
| The '''FARSTACK''' parameter causes the assembler to assume that the stack is in a different physical segment from that of the default data, and that SS register is not equal to DS. This is typically the case for code in a 16- bit dynamic link library that must use the caller's stack. The assembler performs an automatic [[#ASSUME]] SS:STACK when this keyword is used.
| |
| | |
| ==== ORG (Adjust Segment Location Counter) ====
| |
| The '''ORG''' directive sets the location counter to the value of ''Expression''. Subsequent instructions are generated beginning at this new location.
| |
| | |
| '''Syntax'''
| |
| ORG Expression
| |
| '''Remarks'''
| |
| | |
| The assembler must know all names used in ''Expression'' on pass 1, and the value must be either absolute or in the same segment as the location counter.
| |
| | |
| The numeric value of ''Expression'' must not be a quantity larger than that which is representable by an unsigned integer having the same word size as the current segment.
| |
| | |
| You can use the current address operator ($) to refer to the current value of the location counter.
| |
| | |
| '''Example'''
| |
| <pre>
| |
| ORG 120H
| |
| ORG $+2 ; SKIP NEXT 2 BYTES</pre>
| |
| To conditionally skip to the next 256-byte boundary:
| |
| | |
| <pre>
| |
| CSEG SEGMENT PAGE
| |
| BEGIN = $
| |
| .
| |
| .
| |
| .
| |
| IF ($-BEGIN) MOD 256
| |
| ; IF NOT ALREADY ON 256 BYTE BOUNDARY
| |
| ORG ($-BEGIN)+256-(($-BEGIN) MOD 256)
| |
| ENDIF
| |
| </pre>
| |
| | |
| ==== SEGMENT (Open a Program Information Segment) ====
| |
| Defines or reopens a segment called ''Segment-Name'' which will contain all subsequently emitted code or data.
| |
| | |
| '''Syntax'''
| |
| Segment-Name SEGMENT [align][combine][use]['class']
| |
| '''Remarks'''
| |
| | |
| A segment definition may be followed by zero or more segment attributes, at most one from each of the following selections:
| |
| | |
| '''''align''''' Instructs the linker to align the segment at the next ''align'' boundary. One of:
| |
| ::'''BYTE''' The next 8-bit boundary.
| |
| ::'''DWORD''' The next 32-bit boundary.
| |
| ::'''PAGE''' The next 256-byte boundary (4096 under 32-bit OS/2).
| |
| ::'''PARA''' The next 16-byte boundary (default).
| |
| ::'''WORD''' The next 16-bit boundary.
| |
| | |
| '''''combine''''' Controls how the linker will combine this segment with identically-named segments from other modules. One of:
| |
| ::'''AT''' ''address'' Locates the segment at the absolute paragraph given by ''address''.
| |
| ::'''COMMON''' Unioned with segments from other modules.
| |
| ::'''PRIVATE''' Will not be combined with other segments (default).
| |
| ::'''PUBLIC''' Concatenated to segments from other modules.
| |
| ::'''STACK''' Concatenated to segments from other modules. At load time:
| |
| :::SS=beginning of segment
| |
| :::SS:(E)SP=end of segment
| |
| | |
| '''''use''''' Word size of the segment.
| |
| :'''USE16''' The segment will have a 16-bit word size.
| |
| :'''USE32''' The segment will have a 32-bit word size.
| |
| | |
| ''''''class'''''' Instructs the linker to order segments according to the class name given by '''class'''. Segments will not be combined if their class names differ.
| |
| | |
| ==== .SEQ (Specifies Sequential Segment Ordering) ====
| |
| Orders segments sequentially (the default order).
| |
| | |
| '''Syntax'''
| |
| .SEQ
| |
| | |
| ==== .STACK (Defines Default Stack Segment With Optional Size) ====
| |
| When used with '''.MODEL''', defines a stack segment with the segment name STACK. The optional ''Size'' specifies the number of bytes for the stack (default 1024).
| |
| | |
| '''Syntax'''
| |
| .STACK [Size]
| |
| '''Remarks'''
| |
| | |
| The '''.STACK''' directive does not leave the stack segment open when the statement is completed, since it is not a common practice to emit initialized data into the stack segment.
| |
| | |
| The name of the segment is STACK32 in flat model, and STACK for all other models.
| |
| | |
| === Type Definition ===
| |
| Type definition directives allow the creation of user-defined data types.
| |
| | |
| This section describes the following type definition directives:
| |
| * RECORD
| |
| * STRUCT/STRUC
| |
| * TYPEDEF
| |
| * UNION
| |
| | |
| ==== RECORD (Define a Record Type Name) ====
| |
| A record is a bit pattern you define to format bytes, words, or dwords for bit-packing. The ''RecordName'' becomes a ''Record-TypeName'' that can be used create record variables.
| |
| | |
| ;Syntax
| |
| RecordName RECORD FieldDeclaration [,[LineBreak] FieldDeclaration...]
| |
| Where ''FieldDeclaration'' has the following form:
| |
| FieldName:Width[=InitialValue]
| |
| The optional ''LineBreak'' entry allows you to end a ''FieldDeclaration'' with a comma, enter an optional ''EndOfLine-Comment'' followed by a physical ''NewLine'' character, then continue the record definition on the next line.
| |
| | |
| ;Remarks
| |
| The ''RecordName'' and ''FieldName'' entries are unique globally-scoped ''[[#Identifier]]s'' that must be specified. Upon successful processing of the '''RECORD''' definition, the ''RecordName'' entry is converted to a ''Record-TypeName'', and all ''FieldNames'' are converted to ''[[#Record-FieldName]]s''.
| |
| | |
| Each ''Width'' entry in a ''FieldDeclaration'' is specified as an ''Expression'' which must evaluate to an ''Absolute-ExpressionType''. The cumulative value of all ''Width'' entries becomes the total '''''RecordWidth''''' and must not exceed 32, the size of a DWORD, the maximum size for a ''Record-TypeName''. The ''Operand Size'' of the record becomes 1 (BYTE) if the ''RecordWidth'' is from 1 through 8, 2 (WORD) if the ''RecordWidth'' is from 9 through 16, and 4 (DWORD) if the ''RecordWidth'' is from 17 through 32. Any other value causes an error. If the total number of bits in the ''RecordWidth'' is not evenly divisible by the ''Operand Size'', the assembler right-justifies the fields into the least-significant bit positions of the record.
| |
| | |
| When a ''Record-FieldName'' is referenced in an expression, the value returned is the shift value required to access the field. The [[#WIDTH]] operator is used on the ''Record-FieldName'' to return the width of the field in bits, and the [[#MASK]] operator is used to obtain the value necessary for isolating the field within the record.
| |
| | |
| The ''InitialValue'' entry contains the default value to used for the field when a record variable is allocated. If the field is at least 7 bits wide, you can initialize it to an ASCII character (for example, FIELD:7='Z').
| |
| | |
| To initialize a record, use the form:
| |
| [Identifier] Record-TypeName Expression[,Expression...]
| |
| The ''Identifier'' entry is an optional name for the first byte, word, or dword of the reserved memory. The ''Record-TypeName'' defines the format and default field values, and is the ''RecordName'' you assigned to the record in the '''RECORD''' directive.
| |
| | |
| At least one ''Expression'' entry must be specified; additional entries are optional. The ''Expression'' must resolve to a ''Compound-ExpressionType'', which may also be duplicated by specifying it as a sub-expression of a ''Duplicated-ExpressionType''. Each ''Compound-ExpressionType'' represents a single allocated record entry; each explicit sub-expression of the ''Compound-ExpressionType'' represents a field value which overrides the default ''InitialValue'' for the field given in the record definition.
| |
| | |
| ;Example
| |
| Define the record fields; begin with the most significant fields first:
| |
| <pre>
| |
| MODULE RECORD R:7, ; First field. ",LineBreak" syntax
| |
| E:4, ; may be used to split RECORD
| |
| D:5 ; definition across multiple lines
| |
| </pre>
| |
| Fields are 7 bits, 4 bits, and 5 bits; the assembler gives no default value. Most significant byte first, this looks like:
| |
| RRRR RRRE EEED DDDD
| |
| To reserve its memory:
| |
| STG_FLD MODULE <7,,2> ; Initializer is a Compound-ExpressionType
| |
| This defines R=7 and D=2 and leaves E unknown; it produces 2 bytes, the least significant byte first:
| |
| 02 0E
| |
| Define the record fields:
| |
| AREA RECORD FLA:8='A', FLB:8='B'
| |
| To reserve its memory:
| |
| CHAR_FLD AREA <,'P'>
| |
| This defines FLA='A' (the default) and changes FLB='P'.
| |
| | |
| To use a field in the record:
| |
| <pre>
| |
| DEFFIELD RECORD X:3, Y:4, Z:9
| |
| .
| |
| .
| |
| .
| |
| TABLE DEFFIELD 10 DUP (<0,2,255>)
| |
| .
| |
| .
| |
| .
| |
| MOV DX, TABLE [2]
| |
| ; Move data from record to register
| |
| ; other than segment register
| |
| AND DX, MASK Y
| |
| ; Mask out fields X and Y
| |
| ; to remove unwanted fields
| |
| ; The MASK of Y equals 1E00H
| |
| ; 00011111000000000B (1E00H) Is the value
| |
| MOV CL,Y ; Get shift count
| |
| ; 9 is the value
| |
| SHR DX,CL ; Field to low-order
| |
| ; bits of register, DX is now
| |
| ; equal to the value of field Y
| |
| MOV CL,WIDTH Y ; Get number of bits
| |
| ; in field-4 is the value,
| |
| ; the WIDTH of Y is 4
| |
| </pre>
| |
| | |
| ==== STRUCT/STRUC (Define a Structure Type Name) ====
| |
| Defines a ''Structure-TypeName'' that represents an [[#aggregate]] data type containing one or more fields.
| |
| | |
| '''Syntax'''
| |
| <pre>Structure-Name STRUCT
| |
| FieldDeclaration
| |
| .
| |
| .
| |
| .
| |
| Structure-Name ENDS</pre>
| |
| Where ''FieldDeclaration'' has the following form:
| |
| [FieldName] Allocation-TypeName InitialValue[,InitialValue...]
| |
| '''Remarks'''
| |
| | |
| The obsolete spelling for the '''STRUCT''' directive is '''STRUC'''.
| |
| | |
| The syntax for the ''FieldDeclaration'' is that of a normal data allocation statement. See the section on [[#Data Allocation]] for a full description of this syntax.
| |
| | |
| The various parts of the ''FieldDeclaration'' are described as follows:
| |
| | |
| '''''FieldName''''' Each ''FieldName'' entry is converted to ''Structure-FieldName'' when processing of the structure definition is complete. If this field is omitted and the '''''Allocation-TypeName''''' resolves to a ''Structure-TypeName'' or ''Union-TypeName'', then all of the fields defined within the imbedded structure or union are '''''promoted''''' to be visible at the same level as other ''FieldName'' entries in the current structure given by the ''Structure-Name''.
| |
| | |
| ''Allocation-TypeName'' The allowable values for this field are described in detail in the [[#Data Allocation]] section. In modes other than [[#M510]], the assembler accepts imbedded occurrences of other structures or unions by specifying an identifier that resolves to a ''Structure-TypeName'' or ''Union-TypeName'' in this field.
| |
| | |
| '''''InitialValue''''' The ''InitialValue'' field must be an ''Expression'' that resolves to an ''ExpressionType'' appropriate for the ''Allocation-TypeName'' utilized in the ''FieldDeclaration''. The ''InitialValue'' expressions become part of the structure type definition. These values are used as default initializers when an instance of the structure is allocated and no explict override values are specified for a particular field.
| |
| | |
| '''Example'''
| |
| | |
| Define a ''Structure-TypeName'' called '''Numbers''':
| |
| <pre>
| |
| Numbers STRUCT
| |
| One DB 0
| |
| Two WORD 0
| |
| BYTE 3
| |
| Four DWORD ?
| |
| Numbers ENDS </pre>
| |
| Allocate a structure variable called '''Values''' using the '''Numbers''' ''Structure-TypeName'', overriding the '''One, Two,''' and '''Four''' ''Structure-FieldName'' entries with explicit values, and the third (unnamed) entry is initialized with the default ''InitialValue''inherited from the ''FieldDeclaration'':
| |
| Values Numbers <1, 2, , 4>
| |
| | |
| ==== TYPEDEF (Create a User-Defined Type Name) ====
| |
| Defines a ''Typedef-TypeName'' that is an alias for another type declaration.
| |
| | |
| '''Syntax'''
| |
| TypeName TYPEDEF Type-Declaration
| |
| '''Remarks'''
| |
| | |
| The ''TypeName'' entry is a unique globally-scoped ''Identifier'' that must be specified. Upon successful processing of the '''TYPEDEF''' directive, the ''TypeName'' entry is converted to a ''Typedef-TypeName'' which can then be used in expressions or as a directive in data allocation statements.
| |
| | |
| The '''TYPEDEF''' directive can be used to create a direct alias for another intrinsic type (a ''Scalar-TypeName'', ''Record-TypeName'', ''Structure-TypeName'', ''Union-TypeName'', or other ''Typedef-TypeName''), a pointer to another type, or it can be used to create vector types (arrays).
| |
| | |
| '''Examples'''
| |
| | |
| The following are examples of '''TYPEDEF''' usage:
| |
| <pre>
| |
| CHAR typedef byte ; CHAR is an alias for intrinsic type
| |
| PCHAR typedef ptr CHAR ; PCHAR is a pointer to CHAR
| |
| | |
| BUFFER_T struct
| |
| pLetter PCHAR ? ; current position in buffer
| |
| Letters CHAR "ABCDEF",0 ; array of characters
| |
| BUFFER_T ends
| |
| | |
| BUFFER typedef BUFFER_T ; alias for intrinsic type
| |
| PBUFFER typedef ptr BUFFER_T ; pointer to the BUFFER type
| |
| | |
| DATA SEGMENT
| |
| HexChars BUFFER <> ; allocate structure via typedef
| |
| pHexChars PBUFFER offset HexChars ; point to the allocated structure
| |
| DATA ENDS
| |
| </pre>
| |
| | |
| ==== UNION (Define a Union Type Name) ====
| |
| Defines a ''Union-TypeName'' that represents an [[#aggregate]] data type containing one or more fields. All of the fields occupy the same physical position in storage.
| |
| | |
| '''Syntax'''
| |
| <pre>Union-Name UNION
| |
| FieldDeclaration
| |
| .
| |
| .
| |
| .
| |
| Union-Name ENDS
| |
| </pre>
| |
| Where ''FieldDeclaration'' has the following form:
| |
| [FieldName] Allocation-TypeName InitialValue [, InitialValue ...]
| |
| '''Remarks'''
| |
| | |
| This directive is not available in [[#M510]] mode.
| |
| | |
| The syntax for the ''FieldDeclaration'' is that of a normal data allocation statement. See the section on [[#Data Allocation]] for a full description of this syntax.
| |
| | |
| The various parts of the ''FieldDeclaration'' are described as follows:
| |
| | |
| '''''FieldName''''' Each ''FieldName'' entry is converted to ''Union-FieldName'' when processing of the union definition is complete. If this field is omitted and the '''''Allocation-TypeName''''' resolves to a ''Structure-TypeName'' or ''Union- TypeName'', then all of the fields defined within the imbedded structure or union are '''''promoted''''' to be visible at the same level as other ''FieldName'' entries in the current union given by the ''Union-Name''.
| |
| | |
| ''Allocation-TypeName'' The allowable values for this field are described in detail in the [[#Data Allocation]] section. The assembler accepts imbedded occurrences of other structures or unions by specifying an identifier that resolves to a ''Structure-TypeName'' or ''Union-TypeName'' in this field.
| |
| | |
| '''''InitialValue''''' The ''InitialValue'' field must be an ''Expression'' that resolves to an ''ExpressionType'' appropriate for the ''Allocation-TypeName'' utilized in the ''FieldDeclaration''. Only the ''InitialValue'' expression for the first field becomes part of the union type definition; expressions specified for the remaining fields are ignored. This value is used as the default initializer when an instance of the union is allocated and no explict override value is specified for the field.
| |
| | |
| '''Example'''
| |
| <pre>
| |
| .386
| |
| IS_sint32 equ -4
| |
| IS_sint16 equ -2
| |
| IS_sint8 equ -1
| |
| NO_TYPE equ 0
| |
| IS_uint8 equ 1
| |
| IS_uint16 equ 2
| |
| IS_uint32 equ 4
| |
| | |
| TYPE_T typedef SBYTE
| |
| | |
| DATA_T union
| |
| uint8 BYTE ?
| |
| sint8 SBYTE ?
| |
| uint16 WORD ?
| |
| sint16 SWORD ?
| |
| uint32 DWORD ?
| |
| sint32 SDWORD ?
| |
| DATA_T ends
| |
| | |
| VALUE_T struct
| |
| DataType TYPE_T NO_TYPE
| |
| DataValue DATA_T {}
| |
| VALUE_T ends
| |
| | |
| .data
| |
| Value VALUE_T {IS_uint8 ,{1}} ; unsigned 8-bit value of 1
| |
| | |
| .code
| |
| | |
| ;Procedure: IsNegative
| |
| ; Returns: 1 in EAX if Value. DataValue holds a negative number
| |
| ; 0 in EAX if Value. DataValue holds a positive number
| |
| | |
| IsNegative proc
| |
| cmp Value.DataType, NO_TYPE ; check sign of TYPE_T
| |
| jns short Positive ; if positive, so is value
| |
| | |
| ; check for signed 8-bit integer
| |
| cmp Value.DataType,IS_sint8
| |
| jne short @F ; not 8, check for 16
| |
| movsx EAX, Value.DataValue.sint8 ; convert 8 bits to 32
| |
| jmp short Check ; and check the value
| |
| | |
| ; check for signed 16-bit integer
| |
| @@: cmp Value.DataType, ISuuuuuuu_sint16
| |
| jne short @F ; not 16, check for 32
| |
| movsx EAX, Value.DataValue.sint16 ; convert 16 bits to 32
| |
| jmp short Check ; and check the value
| |
| | |
| ; check for signed 32-bit integer
| |
| @@: cmp Value.DataType, IS_sint32
| |
| jne short Positive ; unknown, assume positive
| |
| mov EAX, Value.DataValue.sint32 ; get full 32 bit number
| |
| | |
| Check: or EAX, EAX ; check for negative value
| |
| jns short Positive ; no sign bit, positive
| |
| mov EAX,1 ; indicate negative
| |
| ret ; and return
| |
| Positive: mov EAX,0 ; indicate positive
| |
| ret ; and return
| |
| IsNegative endp
| |
| end
| |
| </pre>
| |
| | |
| === Miscellaneous ===
| |
| This section describes the following miscellaneous directives:
| |
| :=
| |
| :.ABORT
| |
| :ASSUME
| |
| :EQU
| |
| :LABEL
| |
| :OPTION
| |
| :.RADIX
| |
| | |
| ==== = (Assign an Expression to an Assembler Variable) ====
| |
| The = directive lets you create a symbolic assembler-time variable. Numeric expressions may be assigned to the variable as many times as necessary.
| |
| | |
| '''Syntax'''
| |
| Name = Expression
| |
| '''Remarks'''
| |
| | |
| The '''=''' directive is similar to the [[#EQU]] assembler directive except you can redefine ''Name'' without causing an error condition. However, the = directive is more restrictive about the allowable ''[[#ExpressionType]]s'' that can be utilized in the ''Expression'' field, and it cannot be used to create ''[[#Text-EquateName]]s''.
| |
| | |
| ''Name'' is a globally-scoped ''Identifier''. The ''Expression'' entry must evaluate to an ''Operand-ExpressionType''. If an evaluation error occurs, or if the ''Expression'' references an external identifier, or if the ''Expression'' evaluates to one of the following ''[[#Operand-ExpressionType]]s:''
| |
| *''Indexed-ExpressionType''
| |
| *''Register-ExpressionType''
| |
| *''Floating-Point-ExpressionType''
| |
| *''Compound-ExpressionType''
| |
| *''Duplicated-ExpressionType''
| |
| | |
| then an error message is issued and the assignment does not take place. Otherwise, the ''Identifier'' is converted to a ''Numeric-EquateName''.
| |
| | |
| See also the [[#EQU]] assembler directive and the EQU preprocessor directive.
| |
| | |
| '''Example'''
| |
| <pre>
| |
| EMP = 6 ; Establish as redefineable numeric equate
| |
| EMP EQU 6 ; OK, value is the same, EMP remains redefinable
| |
| EMP EQU 7 ; Error, can't change value with EQU
| |
| EMP = 7 ; OK, EMP is redefineable with =
| |
| EMP = EMP + 1 ; Can refer to its previous definition
| |
| </pre>
| |
| '''Note:''' The ''[[#Expression-Attribute]]s'' inherited from the ''Expression'' during an assignment are not retained in subsequent assignments. For example:
| |
| <pre>
| |
| VECTOR = WORD PTR 4 ; Type-Declaration attribute
| |
| MOV [BX], VECTOR ; Store the 4 as a word
| |
| VECTOR = 6 ; Type-Declaration attribute discarded
| |
| MOV [BX], VECTOR ; Error, no size for operands
| |
| </pre>
| |
| | |
| ==== .ABORT (Terminate the Assembly) ====
| |
| Terminates the assembly at the point where the '''.ABORT''' directive is encountered. The remainder of the input stream is not read.
| |
| | |
| '''Syntax'''
| |
| .ABORT
| |
| '''Remarks'''
| |
| | |
| The '''.ABORT''' directive is only available in [[#ALP]] mode.
| |
| | |
| ==== ASSUME (Inform Assembler of Register Contents) ====
| |
| The '''ASSUME''' directive establishes an assembly-time association between a machine register and a program object or data type. By informing the assembler of the type of information to which a register points, certain programming tasks can be simplified and the assembler can perform some operations automatically.
| |
| | |
| '''Syntax'''
| |
| ASSUME Association [,Association ...]
| |
| '''''Association:'''''
| |
| :''Segment-Register-Assocation''
| |
| :''General-Purpose-Register-Assocation''
| |
| :'''NOTHING'''
| |
| | |
| '''''Segment-Register-Association:'''''
| |
| :''Segment-Register'': ''Expression''
| |
| :''Segment-Register'': '''NOTHING'''
| |
| | |
| '''''General-Purpose-Register-Association:'''''
| |
| :''General-Purpose-Register'': ''Type-Declaration''
| |
| :''General-Purpose-Register'': '''NOTHING'''
| |
| | |
| '''Remarks'''
| |
| | |
| If the '''NOTHING''' keyword is specified for the ''Association'' field, all register associations are cancelled.
| |
| | |
| If the '''NOTHING''' keyword is specified for a particular ''Segment-Register'' or ''General-Purpose-Register'', only the association for that register is cancelled.
| |
| | |
| The following sections describe the two types of register associations:
| |
| *''Segment-Register-Association''
| |
| *''General-Purpose-Register-Association''
| |
| | |
| ===== Segment Register Association =====
| |
| A '''''Segment-Register-Association''''' establishes an assembly-time association between a ''Segment-Register'' and an expression that resolves to a ''GroupName'' or ''SegmentName''. It allows the programmer to describe for the assembler what values are held in the segment registers at program run-time.
| |
| | |
| When the user program executes, all instructions that access memory do so through a particular segment register. To generate the correct encoding for an instruction that accesses a memory location, the assembler must know which segment register will be used in the effective memory address. In general, accessing a memory location from within a user program is done by referencing a named variable defined within a particular named segment.
| |
| | |
| Before accessing a named program variable (in a named memory segment), it is the programmer's responsibility to insure that the desired segment register actually references the correct physical segment at program run-time. Unless the '''ASSUME''' directive is used to describe this association, the assembler has no way of knowing ''which'' segment register (if any) is addressing a named segment when a reference to a named variable contained therein is encountered. In this situation, the programmer is forced to use the [[#Segment Override (: Operator)]] in every instruction to "reach" the desired variable and cause the assembler to generate the proper instruction encoding. The association established by the '''ASSUME''' directive allows the assembler to take over the task of verifying memory references and generating the appropriate instructions.
| |
| | |
| If you temporarily use a segment register to contain a value other than the segment or group identified in the '''ASSUME''' association, then you should reflect the change with a new '''ASSUME''' statement, or cancel the association with an '''ASSUME xS:NOTHING''' construct.
| |
| | |
| When the contents of a segment register are used for addressability, the register value should never contradict the association established for that register.
| |
| | |
| When the [[#Reference]] directive is utilized and the program is designed to follow the conventions that it establishes, the '''ASSUME''' directive is no longer needed in most cases.
| |
| | |
| '''Example'''
| |
| <pre>
| |
| Data SEGMENT
| |
| Stuff WORD 0
| |
| Data ENDS
| |
| | |
| Code SEGMENT
| |
| ASSUME NOTHING ; Cancel all register assumptions
| |
| mov ax, Data ; Load general-purpose register with segment frame,
| |
| mov DS, ax ; then establish addressablity through DS
| |
| mov ES, ax ; and ES. The assembler doesn't "know" this yet
| |
| mov Stuff, 1 ; Error, can't reach Stuff
| |
| ASSUME ES:Data ; Associate ES register with Data segment
| |
| add Stuff, bx ; Now we can reach Stuff, but the assembler needs
| |
| ; to generate an ES override instruction byte
| |
| ASSUME DS:SEG Stuff ; Expression to extract the segment value of Stuff
| |
| ; This has the same effect as ASSUME DS:Data
| |
| ; Now both DS and ES are associated with Data
| |
| add Stuff, cx ; This time, the instruction doesn't need an
| |
| ; override byte because DS is the default
| |
| ; register for normal accesses to memory
| |
| ASSUME DS:NOTHING ; Cancel the association between DS and Data
| |
| add Stuff, dx ; Once again, the ES override is generated
| |
| add DS:Stuff, dx ; Must use "force" if we want the default encoding
| |
| Code ends
| |
| end
| |
| </pre>
| |
| '''Warning''':
| |
| | |
| If an '''ASSUME CS''':''Expression'' is placed before the code segment it is referencing, the assembler will ignore the '''ASSUME'''. The '''ASSUME CS''':''Expression'' statement must follow the '''SEGMENT''' definition statement of the code segment it is referencing.
| |
| | |
| The '''ASSUME''' statement for the '''CS''' register should be placed immediately following the code [[#SEGMENT]] statement, before any labels are defined in that code segment.
| |
| | |
| ===== General-Purpose Register Association =====
| |
| A '''''General-Purpose-Register-Association''''' establishes an assembly-time association between a ''General-Purpose-Register'' and a ''Type-Declaration''. It allows the programmer to describe for the assembler what type of data is being held in the general purpose register at program run-time.
| |
| | |
| This feature can be very useful when the programmer is treating a general- purpose register as a "pointer" to a particular type of storage. If this " pointer" is being utilized many times in the program, (perhaps changing in value but never in the type of data to which it points), the '''ASSUME''' directive can be used to associate the register with the type of data to which it points. This frees the programmer from having to use an explicit [[#Type Conversion (PTR Operator)]] every time the register is used to access memory.
| |
| | |
| A register may only be associated with a data type whose operand size matches that of the register. For instance, the following construct is illegal:
| |
| ASSUME EBX:BYTE ; Error, EBX is a DWORD register
| |
| The most useful situation is for the register to contain a pointer to another data type. In this situation, the [[Indirection ([] Operator)]] may be used store or retrieve data through the register without the need for an explicit conversion operation:
| |
| <pre>
| |
| ASSUME EDI:NOTHING ; This is the assembler default setting
| |
| MOV [EDI],1 ; What is the size supposed to be?
| |
| MOV byte ptr [EDI],1 ; Fixes the problem, but this can get tiring
| |
| ASSUME EDI:PTR BYTE ; EDI is now a pointer to a byte
| |
| MOV [EDI],1 ; assembler knows what to do with this now
| |
| INC [EDI] ; and this too
| |
| </pre>
| |
| The following constructs are legal but not particularly useful since they simply restate what is already known about the registers (the operand size), and the assembler doesn't enforce a strict level of type checking against register operands:
| |
| <pre>
| |
| ASSUME ECX:SDWORD ; Signed double-word matches size of ECX
| |
| ASSUME EBX:DWORD ; Unsigned double-word matches size of EBX
| |
| MOV ECX, 0FFFFEEEEh ; Register type-checking is not strict
| |
| MOV EBX, -1 ; enough to flag these as errors
| |
| </pre>
| |
| In fact, any data type that matches the size of the register may be used; the assembler checks the sizes and reports mismatches, but effectively ignores any settings that are not pointers to other types. Consider the following example:
| |
| <pre>
| |
| STRUCT_T STRUCT
| |
| One BYTE 1
| |
| Two BYTE 2
| |
| Three BYTE 3
| |
| Four BYTE 4
| |
| STRUCT_T ENDS
| |
| | |
| ASSUME EBX:STRUCT_T ; Ok, STRUCT_T is 4 bytes in size
| |
| MOV EBX , - 1 ; Legal, but not very meaningful ...
| |
| | |
| ; A more useful situation (given that EBX is now holding data of type
| |
| ; STRUCT_T) would be for the assembler to allow the following notation:
| |
| | |
| MOV EBX,{ 4 , 3 , 2 , 1 } ; Hypothetical (UNSUPPORTED!) syntax...
| |
| | |
| ; It would also be nice at this point if the symbolic debugger could
| |
| ; show us the value of EBX in the appropriate format, but the assembler
| |
| ; does not support the emitting of context-sensitive symbolic debugging
| |
| ; information.
| |
| </pre>
| |
| | |
| ==== EQU (Assign an Expression to a Symbolic Constant) ====
| |
| The '''EQU''' directive assigns the value of ''Expression'' to ''Name''.
| |
| | |
| ;Syntax
| |
| Name EQU Expression
| |
| | |
| ;Remarks
| |
| If ''Name'' has already been defined as a ''Numeric-EquateName'' and its currently assigned value differs from the value given by ''Expression'', an error message is produced. Unlike symbols created with the = (equal sign) directive, symbols created with the '''EQU''' directive cannot be redefined with different values.
| |
| | |
| The ''Expression'' entry must evaluate to an ''Operand-ExpressionType''. If an evaluation error occurs or if the ''Expression'' evaluates to one of the following ''Operand-ExpressionTypes:''
| |
| *''Indexed-ExpressionType''
| |
| *''Floating-Point-ExpressionType''
| |
| *''Compound-ExpressionType''
| |
| *''Duplicated-ExpressionType''
| |
| | |
| then the ''Identifier'' is converted to a ''Text-EquateName''. Otherwise, the ''Identifier'' is converted to a ''Numeric-EquateName''.
| |
| | |
| See also [[#EQU]] and [[#=]].
| |
| | |
| '''Example'''
| |
| <pre>
| |
| A EQU <BP+> ; explicit text literal, A is a text equate
| |
| B EQU BP+ ; invalid expression - text equate equivalent to A
| |
| B EQU 1+2 ; valid expression - but still a text equate <1+2>
| |
| C EQU 1+2 ; converted to assembler symbolic constant, value=3
| |
| C EQU <3> ; illegal, cannot convert back to text equate
| |
| </pre>
| |
| | |
| ==== LABEL (Associate a Symbolic Name With Current Address) ====
| |
| The '''LABEL''' directive defines the following attributes of ''Name:''
| |
| *Segment: current segment being assembled
| |
| *Offset: current position within this segment
| |
| *Type: the operand of the '''LABEL''' directive
| |
| | |
| '''Syntax'''
| |
| Name LABEL Type-Declaration
| |
| or
| |
| Name:
| |
| or
| |
| Name::
| |
| '''Remarks'''
| |
| | |
| The '''LABEL''' directive provides a method of labeling a memory location and assigning it a type without allocating any storage. It can be used to create multiple labels of differing types that are aliases for the same memory location.
| |
| | |
| The ''Name'' entry is an ''Identifier'' that is converted to a ''LabelName'' according to the value given by ''Type-Declaration''. See the section on [[#label names]] for more information on the details of this conversion.
| |
| | |
| The ''':''' and '''::''' forms of this directive are used for defining code labels. In this case, the ''Name''entry is converted to a ''Target-LabelName''. The double-colon form of the directive is used when the ''Name'' must be visible outside of the procedure block in which it is defined.
| |
| | |
| '''Example'''
| |
| | |
| To refer to a data area but use a length different from the original definition of that area:
| |
| <pre>
| |
| BARRAY LABEL BYTE
| |
| ARRAY DW 100 DUP (0)
| |
| .
| |
| .
| |
| .
| |
| ADD AL, BARRAY [99] ; ADD 100th BYTE TO AL
| |
| ADD AX, ARRAY [98] ; ADD 50th WORD TO AX
| |
| </pre>
| |
| To define multiple entry points within a procedure:
| |
| <pre>
| |
| SUBRT PROC FAR
| |
| .
| |
| .
| |
| .
| |
| SUB2 LABEL FAR ; Should have same attribute as containing PROC
| |
| .
| |
| .
| |
| .
| |
| RET
| |
| SUBRT ENDP
| |
| </pre>
| |
| | |
| ==== OPTION (Modify Default Behaviors) ====
| |
| The '''OPTION''' directive allows the user to alter certain default behaviors of the assembler, normally to provide backward compatibility with older assemblers. The '''OPTION''' directive is not available when assembling in [[#M510]] mode.
| |
| | |
| '''Syntax'''
| |
| OPTION Option-Item [,[LineBreak] Option-Item ...]
| |
| '''Remarks'''
| |
| | |
| The '''''Option-Item''''' arguments are defined as follows (the underlined keywords denote the default values):
| |
| | |
| '''DOTNAME'''| ''NODOTNAME'' Allows user identifiers to begin with an introductory dot (.) character.
| |
| | |
| '''EXPR16'''| ''EXPR32'' Specifies whether expressions are evaluated using 16-bit or 32-bit arithmetic. Some programs may require reverting back to '''EXPR16''' in order to assemble without problems. Once this value has been set it cannot be changed. The use of a processor selection directive to select a 32-bit processor is equivalent to selecting '''OPTION EXPR32''', which prevents any further attempt to select '''OPTION EXPR16'''.
| |
| | |
| '''LANGUAGE''':''Language-Name'' Specifies the default language type for identifiers with '''PUBLIC''' or '''EXPORT''' visibility. This option overrides any setting given in the [[#.MODEL]] directive.
| |
| | |
| '''OFFSET''':''Offset-Type'' Determines how relocatable offset values are written to the object file output, encoded in the form of a linker "fixup" record. The possible values for ''Offset-Type'' are '''SEGMENT''', ''GROUP'', and '''FLAT'''.
| |
| | |
| '''OLDSTRUCTS'''| ''NOOLDSTRUCTS'' The '''OLDSTRUCTS''' keyword causes structure field names to become global identifiers rather than local names private to the structure type. It also prevents the [[#Structure/Union Field Selection (. Operator)]] from performing strict checking on its operands, requiring its left operand to have a structure type and its right operand to be the name of a field contained therein.
| |
| | |
| '''PROC''':''Visibility'' Specifies the default visibility for procedure names. This can be one of '''PRIVATE''', ''PUBLIC'', or '''EXPORT'''.
| |
| | |
| '''SCOPED'''| '''NOSCOPED'''The '''NOSCOPED''' keyword forces all code label names defined within procedures to be visible to the entire module and not just from within the defining procedure.
| |
| | |
| '''SEGMENT''':''Address-Size'' Explicitly sets the default address size value. This is used to control the address size of segments that are opened without explict '''USE16''' or '''USE32''' keywords, and of global identifiers that are declared outside of segment boundaries. The possible values for ''Address-Size'' are '''USE16''', '''USE32''', and '''FLAT'''.
| |
| | |
| ==== .RADIX (Set the Default Base for Numeric Literals) ====
| |
| The '''.RADIX''' directive lets you change the default '''RADIX''' (decimal) to base 2, 8, 10, or 16.
| |
| | |
| '''Syntax'''
| |
| .RADIX Expression
| |
| '''Remarks'''
| |
| | |
| The ''Expression'' entry is in decimal radix regardless of the current radix setting.
| |
| | |
| The '''.RADIX''' directive does not affect real numbers initialized as variables with '''DD''', '''DQ''', or '''DT'''.
| |
| | |
| When using '''.RADIX 16''', be aware that if the hex constant ends in either B or D, the assembler thinks that the B or D is a request to cancel the current radix specification with a base of binary or decimal, respectively. In such cases, add the H base override (just as if '''.RADIX 16''' were not in use).
| |
| | |
| '''Example'''
| |
| | |
| The statement:
| |
| .RADIX 16
| |
| DW 120B
| |
| produces an error because 2 is not a valid binary number. The correct specification is:
| |
| DW 120BH
| |
| The following example:
| |
| .RADIX 16
| |
| DW 89CD
| |
| also produces an error because C is not a valid decimal number. The correct specification is:
| |
| DW 89CDH
| |
| The dangerous case is when no error is produced. For example:
| |
| .RADIX 16
| |
| DW 120D
| |
| produces a constant whose value is 120 decimal, not '120D' hex, which might have been the intended value.
| |
| | |
| The following two move instructions are the same:
| |
| <pre>
| |
| MOV BX, OFFH
| |
| .RADIX 16
| |
| MOV BX , OFF </pre>
| |
| The following example:
| |
| | |
| <pre>.RADIX 8
| |
| DQ 19.0 ; Treated as decimal</pre>
| |
| produces a constant whose value is 19 decimal because 19.0 is a real number. However, if you leave off the decimal point, the following:
| |
| | |
| <pre>
| |
| .RADIX 8
| |
| DQ 19 ; uses current radix</pre>
| |
| produces a syntax error because nine is not a valid number in .RADIX 8.
| |
| | |
| *[[ALP Programming Guide and Reference/Processor Reference|Processor Reference]] | |
| | |
| ==Assembler Messages==
| |
| This section describes all the messages produced by ALP at run time. Messages issued by the assembler have the following format:
| |
| :'''[Coordinates] [Severity Type] [Message Number] [Message Content]'''
| |
| | |
| The following sections describe the various fields common to all assembler messages, and a complete description of each individual message is included.
| |
| | |
| ===Message Coordinates===
| |
| Message coordinates (if present) appear as the first field within a message, and have one of two forms:
| |
| :'''[Path]Filename(LLLL:CCCC):'''
| |
| :'''[Path]Filename(LLLL,Macroname(LLLL,CCCC)):'''
| |
| Coordinates are displayed as part of a message if ALP is parsing an input stream and the event which caused the message to be diplayed is directly related to a specific location in the input. The coordinates show the user exactly where to look if action is required. The fact the ALP is parsing an input stream does not mean that coordinates will appear in a message; some messages may occur during parsing that are not a reference to the input stream.
| |
| | |
| * Filename | |
| : This is the name of the file containing the input token which caused the message to be generated. If this is the root source file whose name was passed on the assembler command line, the file name will be displayed exactly as specified by the user. If this is an '''INCLUDE''' file, it will be displayed exactly as specified in the '''INCLUDE''' directive, and the path name where the file was searched for and found (if any) will be prepended to the beginning. ALP does not query the operating system in an attempt to derive the full path name of a partially qualified file.
| |
| | |
| * Macroname
| |
| : If the assembler is currently parsing tokens within a macro expansion, the name of the macro currently being expanded will appear in the coordinates.
| |
| | |
| * Line Number (LLLL)
| |
| : The first number in parentheses is the line number within the source file where the referenced token is located; this refers to the '''''outer-most point of invocation''''' if a macro name is also given in the message coordinates. A line number value appearing within parentheses following a macro name refers to the '''''innermost point of expansion''''' (since macro expansions may be nested) and references the original definition of the macro.
| |
| | |
| * Column Number (CCCC)
| |
| : The second number in parentheses is the column number of the first character of the referenced token within the source file or macro definition.
| |
| | |
| ===Message Severity Types===
| |
| Every message displayed by ALP is assigned a specific type, and the type of message dictates the severity level. The following is a list of message types produced by ALP showing the type name (as it appears in the actual message), followed by a description of what caused the message, how severe it is, and the action taken by ALP after the message is generated.
| |
| | |
| :Info: Informational message only; processing continues normally.
| |
| | |
| :Warning: Questionable syntax or semantics; input file may be incorrect, but processing continues.
| |
| | |
| :Error: Syntax or semantic error in input; continue processing, object output file is discarded.
| |
| | |
| :Fatal: Unrecoverable user or environment error; terminate assembly prematurely after releasing resources and closing files.
| |
| | |
| :Internal: Internal program logic error, abort immediately.
| |
| | |
| :Usage: Incorrect command line syntax, abort.
| |
| | |
| When the assembler begins processing, the display of all warning messages is enabled; informational messages do not display unless they are requested . The display of both warning and informational messages may be controlled with the command line option M - Control Individual Messages or Groups See Message Control Options for more information on the behavior of assembler messages.
| |
| | |
| ===Message Numbers and Message Content===
| |
| Messages numbers displayed by ALP have the following format:
| |
| :'''ALPnnnn:'''
| |
| Message numbers always have a three-letter prefix that designates the component issuing the message '''(ALP)''', followed by a four digit decimal number given by '''nnnn'''. All messages issued by the assembler are uniquely numbered; however, not all messages displayed by the assembler will be accompanied by a formatted message number (for instance, the assembler banner).
| |
| | |
| Messages issued during assembler initialization, command line processing, or exception handling are numbered from 0 to 999. Other messages occur during input stream processing and are grouped according to their severity type: 1000 through 1999 for fatal errors, 3000 through 3999 for regular errors, 4000 through 4999 for warnings, and 5000 through 5999 for informational messages.
| |
| | |
| It should be noted that messages are numbered for reference only; it is not guaranteed that messages will be numbered identically for each subsequent assembler release, or that individual messages will be retained or remain unmodified in future releases.
| |
| | |
| ===Message Numbers 0-999: Internal, Usage, and Special Case Messages===
| |
| Messages in this section normally occur during assembler initialization, when errors are encountered during command line processing, or when exceptional conditions occur that prevent the assembler from completing initialization or execution.
| |
| | |
| ;ALP0004: <signal> received, <assembler-name> is shutting down
| |
| :ALP has handled a request from the operating system to abort execution. The type of abort request is noted in the text of the message. All open files will be closed and any incomplete output files will be deleted.
| |
| :Recovery: If termination was requested by the user, no further action is necessary. Otherwise, the operating system may have sent an abort signal because of insufficient system resources.
| |
| ;ALP0005: Assertion failure, <reason>
| |
| :This message is displayed when an internal self-check condition has been violated, and indicates an error in the internal programming logic of the assembler. This message should never occur.
| |
| :Recovery: Note the conditions under which the error occurred, and if possible isolate a minimal test case that will reproduce the problem. Contact IBM.
| |
| ;ALP0942: -Lo:xxxxxxxxxxxx must be one each of "XYZLMICFOGDS"
| |
| :This option specifies the sort order for the individual vertical listing file columns. Not all single character tags that uniquely identify each individual column were specified.
| |
| :Recovery: All column tags must be specified in the argument field of this option, even when the display of one or more columns has been disabled.
| |
| ;ALP0981: Invalid or missing include path
| |
| :The list of INCLUDE file directories was incorrectly specified.
| |
| ;ALP0991: Invalid option "<option>"
| |
| :The command line parser encountered a character sequence on the command line that was interpreted as an option, but the option identifier itself was not recognized.
| |
| ;ALP0992: Option "<option>" not valid in global scope
| |
| :An attempt was made to use an option in a situation that would cause ambiguities. As coded by the user, the option is only legal when applied to an individual filename.
| |
| :Recovery: If the option syntax is correct, insure that it follows the filename to which it applies.
| |
| ;ALP0993: Option "<option>" not valid in local scope
| |
| :An attempt was made to apply a global assembler option to an individual file.
| |
| :Recovery: Global options must appear before any filenames; in most cases the usage of global options and filenames is a mutually exclusive operation.
| |
| ;ALP0994: Invalid argument in option "<option>"
| |
| :In the argument field of a parameterized command line option, an argument of a specific type was expected, but an invalid token was encountered instead.
| |
| ;ALP0995: Expecting ":" or "=" in option "<option>"
| |
| :A parameterized option was encountered, but no colon (:) or equal sign (=) followed the option identifier.
| |
| :Recovery: Parameterized options must be immediately followed by a colon or equal sign with no intervening white space characters, followed by the option argument(s).
| |
| ;ALP0996: Invalid message number
| |
| :An explicit message number specified with the '''-M''' option did not identify a message for which switching is enabled.
| |
| :Recovery: Only warning and informational messages may switched on or off.
| |
| ;ALP0997: Invalid keyword "<keyword>" in option "<option>"
| |
| :The referenced identifier was not a valid keyword; a keyword was expected in the context of the referenced option.
| |
| | |
| ===Message Numbers 1000-1999: Fatal Error Messages===
| |
| Fatal errors typically occur when the assembler requests a resource from the operating system, but the request fails. This may or may not be due to user error, but the assembler was unable to correct the problem and execution is terminated after an orderly shutdown is performed.
| |
| | |
| ====ALP1101: Memory allocation error====
| |
| The assembler attempted to dynamically allocate a block of storage, but the request was denied.
| |
| | |
| Recovery:
| |
| * Close any large or memory intensive processes
| |
| * Verify that sufficient paging space exists
| |
| * The host computer may have insufficient hardware resources
| |
| | |
| ====ALP1102: Too many error messages====
| |
| This message is displayed when the assembler has reached the error limit threshold.
| |
| Related Information:
| |
| * Me - Set Number of Errors Before Assembler Aborts
| |
| | |
| ====ALP1103: Error opening message output file "<file>"; <reason>====
| |
| An error occurred while attempting to open the referenced file.
| |
| Recovery: Verify that the file exists and that read permission is allowed. Verify that no other processes are accessing the file, and that the file system is functioning correctly.
| |
| | |
| ====ALP1104: Input and message output filenames are identical====
| |
| The assembler has detected an attempt to create an output file with a name identical to that of an input file; the operation was not allowed.
| |
| | |
| The assembler only detects this condition when the names are an identical match , using a case-sensitive comparison algorithm.
| |
| | |
| Recovery: Ensure that the correct command line options have been used. Internal variables may have been incorrectly initialized using options that affect automatic file name generation, thus causing a filename collision.
| |
| | |
| Related Information:
| |
| * Internal Variables
| |
| * File Control Options
| |
| | |
| ====ALP1401: Error opening listing output file "<file>"; <reason>====
| |
| An error occurred while attempting to open the referenced file.
| |
| Recovery: Verify that the file exists and that read permission is allowed. Verify that no other processes are accessing the file, and that the file system is functioning correctly.
| |
| | |
| ====ALP1402: Error writing listing output file "<file>"; <reason>====
| |
| An error occurred while attempting to write to the referenced file.
| |
| Recovery: Ensure that there is sufficient space on the target file system, and no other processes are accessing or modifying the file. Verify that the file system is functioning correctly.
| |
| | |
| ====ALP1403: Input and listing output filenames are identical====
| |
| The assembler has detected an attempt to create an output file with a name identical to that of an input file; the operation was not allowed. The assembler only detects this condition when the names are an identical match , using a case-sensitive comparison algorithm.
| |
| Recovery: Ensure that the correct command line options have been used. Internal variables may have been incorrectly initialized using options that affect automatic file name generation, thus causing a filename collision.
| |
| Related Information:
| |
| * Internal Variables
| |
| * File Control Options
| |
| | |
| ====ALP1601: Error creating object output file "<file>"; <reason>====
| |
| An error occurred while attempting to create the referenced file.
| |
| Recovery: Verify that the target drive and directory exist and that create and write permission have been granted. Verify that no other processes are accessing the file, and that the file system is functioning correctly.
| |
| | |
| ====ALP1602: Error writing object output file "<file>"; <reason>====
| |
| An error occurred while attempting to write to the referenced file.
| |
| Recovery: Ensure that there is sufficient space on the target file system, and no other processes are accessing or modifying the file. Verify that the file system is functioning correctly.
| |
| | |
| ====ALP1603: Input and object output filenames are identical====
| |
| The assembler has detected an attempt to create an output file with a name identical to that of an input file; the operation was not allowed. The assembler only detects this condition when the names are an identical match , using a case-sensitive comparison algorithm.
| |
| Recovery: Ensure that the correct command line options have been used. Internal variables may have been incorrectly initialized using options that affect automatic file name generation, thus causing a filename collision.
| |
| Related Information:
| |
| * Internal Variables
| |
| * File Control Options
| |
| | |
| ====ALP1801: Error opening source file "<file>"; <reason>====
| |
| An error occurred while attempting to open the referenced file.
| |
| Recovery: Verify that the file exists and that read permission is allowed. Verify that no other processes are accessing the file, and that the file system is functioning correctly.
| |
| | |
| ====ALP1802: Error reading source file "<file>"; <reason>====
| |
| An error occurred while attempting to read from the referenced file.
| |
| Recovery: Ensure that the file exists, that the filelength is non-zero, and that read permission is allowed. Verify that no other processes are accessing the file, and that the file system is functioning correctly.
| |
| | |
| ====ALP1803: Circular text substitution====
| |
| The preprocessor has detected an attempt to perform a recursive text substitution operation, such as an INCLUDE file "including" itself, or a macro expanding itself.
| |
| | |
| ====ALP1804: Internal buffer overflow====
| |
| The preprocessor has overflowed an internal memory buffer while trying to process the referenced token.
| |
| Recovery: Reduce the number of whitespace characters preceding the token or the number of characters in the token itself.
| |
| | |
| ====ALP1901: Unexpected character <character-value> in identifier====
| |
| The command line parser was expecting an identifier but immediately encountered a non-identifier character. Command line parsing was prematurely terminated.
| |
| | |
| ====ALP1902: Unexpected character <character-value> in keyword====
| |
| The command line parser was expecting an keyword but immediately encountered a non-identifier character. Command line parsing was prematurely terminated.
| |
| | |
| ====ALP1903: Error opening response file "<file>"; <reason>====
| |
| An error occurred while attempting to open the referenced file.
| |
| Recovery: Verify that the file exists and that read permission is allowed. Verify that no other processes are accessing the file, and that the file system is functioning correctly.
| |
| | |
| ====ALP1904: Invalid filename in "@" directive====
| |
| The command line parser was processing an @Filename (command line response file) directive, but the token following the "@" character did not constitute a valid filename.
| |
| Recovery: Ensure that only valid filename characters are used.
| |
| | |
| ====ALP1905: Unexpected character or terminator <character-value>====
| |
| The command line parser encountered either an illegal control character or the end of the command line input stream before the current command parameter was completely parsed.
| |
| | |
| ====ALP1906: Numeric constant is invalid; <reason>====
| |
| An error occurred while converting the referenced numeric constant to an internal representation.
| |
| | |
| ===Message Numbers 3000-3999: Error Messages===
| |
| Error messages are typically issued during processing of the input stream and indicate a syntax or semantic error in the user program. The assembler will continue processing after an error has occurred, but since the input stream was incorrect an output object file will not be created.
| |
| | |
| ====ALP3201: Can't <verb> <expr_type> <from/to/by/with> <expr_type>====
| |
| This message appears during expression processing when a binary operation was performed on two primary expressions of incompatible type. The message replacement parameters indicate the attempted operation.
| |
| | |
| ====ALP3202: Overflow or division by zero====
| |
| Either the expression evaluated to a quantity that is not representable in the current expression word size, or an expression contained a binary division (/) or modulus (MOD) operation where the denominator expression was evaluated to be zero.
| |
| | |
| ====ALP3203: Can't take offset of expression====
| |
| The expression to which the OFFSET operator was applied did not contain a constant or relocatable address.
| |
| Recovery: The offset operator may not be applied to register values. If the offset expression is applied to a quoted string, ensure that the string length does not exceed the length of what is representable as a constant value, given the word size of the enclosing segment (2 for USE16 segments, 4 for USE32 segments).
| |
| | |
| ====ALP3204: Expecting relocatable expression====
| |
| An expression was used in a context that required a segment or group relative address, but one was not supplied.
| |
| | |
| ====ALP3205: Expecting primary expression====
| |
| The assembler was expecting a terminal operand (an identifier, register, or constant) or an expression enclosed in parentheses () or square brackets [ ]; instead, an unexpected token was encountered at the referenced location.
| |
| | |
| ====ALP3206: Expecting "]"====
| |
| An opening bracket "[" was encountered and the subsequent expression was fully parsed, but a closing bracket "]" was not encountered.
| |
| | |
| ====ALP3207: Expecting ")"====
| |
| An opening parenthesis "(" was encountered and the subsequent expression was fully parsed, but a closing parenthesis ")" was not encountered.
| |
| | |
| ====ALP3208: Forward reference needs segment override or FAR PTR====
| |
| An expression contained a forward reference to a location that was later determined to be of FAR distance. When forward references are used, the assembler makes default assumptions about the eventual definition of undefined labels used in the expression; such definitions are never assumed to be in a different segment. Use of such an expression can cause differences between the code generated on the first and second passes of the assembler.
| |
| Recovery: Qualify the expression with a distance override (FAR, FAR16, or FAR32) or segment override (:) operator.
| |
| | |
| ====ALP3210: Illegal operation on relocatable value====
| |
| A unary operator was applied to an expression containing a relocatable address or indirect memory expression, but the operator may only be used with constant values.
| |
| | |
| ====ALP3211: Illegal type expression====
| |
| A "<type> PTR" type conversion expression was encountered, but the expression given by <type> was not a valid qualified type.
| |
| | |
| ====ALP3212: Operands must be relative to same segment or group====
| |
| A binary operation was performed on two relocatable expressions, but the expressions were not declared relative to the same segment.
| |
| | |
| ====ALP3213: Illegal digit(s) for current .RADIX====
| |
| A literal integer constant was not qualified with a prefix or suffix (radix override), but was specified using digits that are not valid for the current radix. For instance, use of the literal 1234 is illegal when the current radix value is 2.
| |
| | |
| ====ALP3214: Value cannot be negative====
| |
| A negative-value expression was encountered where only positive numbers are allowed, such as the count-value for the DUP operator, the field-width entry in a RECORD definition, or the shift-value in the SHL or SHR operators.
| |
| | |
| ====ALP3215: Expression cannot be forward-referenced====
| |
| The referenced expression is used in a context where an undefined or forward-referenced value prevents the assembler from completing the operation or generating a reliable construct. This is the case during the declaration of user-defined types or where the value of the location counter will depend on the results of the expression.
| |
| | |
| ====ALP3216: Expression does not have an operand size====
| |
| The SIZE operator was used on an expression for which no operand size exists (a simple number value, for example). The SIZE operator may only be used on expressions that have an operand size attribute, such as a variable name or type name expression.
| |
| | |
| ====ALP3217: Record tag expected====
| |
| A left-hand identifier operand was followed by a right-hand expression list operand enclosed in angle brackets or braces. The construct was parsed as a record constant, but could not be evaluated because the left-hand operand was not a record tag name previously defined with the RECORD directive.
| |
| | |
| ====ALP3218: Numeric constant is invalid; <reason>====
| |
| An error occurred while converting the referenced numeric constant to an internal representation.
| |
| | |
| ====ALP3219: Expression must be a constant value====
| |
| The assembler issues this message whenever a constant expression is required, but the expression supplied contained relocation information or machine register references.
| |
| | |
| ====ALP3220: Undefined symbol "<identifier>"====
| |
| This message appears when an identifier was referenced in an expression or type declaration, and the identifier has no external declaration or definition or is forward-referenced.
| |
| | |
| ====ALP3221: Expecting "," or ")"====
| |
| This message appears when processing a DUP expression list and an unexpected token was encountered. The parser was expecting the list to be continued with a comma or terminated with a closing parentheses.
| |
| Recovery: Check for possible unbalanced parentheses ().
| |
| | |
| ====ALP3222: Expecting "("====
| |
| The DUP operator was encountered but was not followed by an opening parentheses to begin the duplicated expression list.
| |
| Recovery: The duplicated expression list following the DUP operator must be enclosed in parentheses (), even if the expression list only contains a single item.
| |
| | |
| ====ALP3223: Expecting variable name====
| |
| The LENGTH operator may only be applied to data labels (variable names). LENGTH returns the number of items allocated to the data label when the label was defined in a data allocation statement.
| |
| | |
| ====ALP3224: Expecting "," or "<closing brace/bracket>"====
| |
| This message appears within a bracketed expression list where the assembler was expecting a comma to introduce the next initializer expression, or a closing brace or angle bracket to terminate the initializer expression list.
| |
| | |
| ====ALP3225: Register-indirect expression illegal in this context====
| |
| A constant or relocatable address expression was expected but the expression also contained at least one machine register. Such an address may be calculated only at run time, and is illegal in this context.
| |
| | |
| ====ALP3226: Expression must have structure or union type====
| |
| The expression to the left of a structure member selection operator (.) did not have a structure or union type. The assembler cannot evaluate the member expression to the right of the selection operator unless the left hand operand has an associated structure or union type.
| |
| Recovery: If the left hand operand must be something other than an explicit structure or union variable (such as a register-indirect expression like [EBX]), then use the PTR operator to convert the left hand operand to the appropriate type.
| |
| | |
| ====ALP3227: Right operand is not a member of structure or union====
| |
| The expression to the right of a structure member selection operator (.) was not a member of the left-hand structure or union expression.
| |
| Recovery: The right-hand operand must be an identifier named in the type definition for the structure or union.
| |
| | |
| ====ALP3228: Invalid identifier type for this operation====
| |
| The symbol type of the referenced identifier was not valid in this context.
| |
| Recovery: This could happen if a text macro name was used in a context where macro expansions are not performed.
| |
| | |
| ====ALP3229: Expression type not valid in this context====
| |
| The referenced expression evaluated to a type that is not valid for the context in which it was used. An example of this would be the use of a segment name or group name where a data label was expected.
| |
| | |
| Recovery: Review the expression-types allowed by the statement or clause where the referenced expression was used, and modify the construct accordingly.
| |
| | |
| ====ALP3301: Label must be followed by a directive====
| |
| A user identifier appeared in the label field, but the end of line was encountered before an assembler directive was specified to give the label a definition.
| |
| | |
| Recovery: Code labels must be followed by a single colon (:) or double colon (::) on the same line as the label itself. Named assembler directives must appear on the same line as the associated label, or the line continuation (\) character must follow the label to create a single logical line.
| |
| Check for a possible misspelled identifier or keyword. Verify that the identifier was specified using the correct uppercase and lowercase letters if case sensitive assembly is in effect.
| |
| | |
| ====ALP3302: Expecting label, directive, or mnemonic====
| |
| The token referenced in the error message was unexpected. This error occurs when the first token on the line is not a valid label, directive, or mnemonic, or when a valid label has been encountered but was not followed by a valid directive or mnemonic.
| |
| | |
| Recovery: If this message references an identifier, check that it was spelled correctly, or that the identifier was specified using the correct uppercase and lowercase letters if case sensitive assembly is in effect.
| |
| | |
| ====ALP3303: Can't be preceded by data label====
| |
| The referenced token is either an instruction mnemonic or a user identifier that appears after a label.
| |
| If the referenced token is an instruction mnemonic, then the preceding label must be followed by a single colon (:) or double colon (::). Data labels may not be used to refer to instructions. Otherwise, it is invalid to have two labels appearing in succession.
| |
| Recovery: Check for misspellings in either identifier, and that the identifiers were specified using the correct uppercase and lowercase letters if case sensitive assembly is in effect.
| |
| | |
| ====ALP3501: Address size mismatch====
| |
| This message indicates one of the following:
| |
| * An indirect memory expression contained a mixtre of 16-bit or 32-bit base or index registers. This prevents the assembler from determining the address size of the expresson, and is illegal.
| |
| * The instruction performs an unalterable implicit operation which conflicts with the operands supplied.
| |
| | |
| ====ALP3502: Invalid register expression====
| |
| A processor register was specified using indexed notation (i.e., "REG(X)"), but the expression in parentheses was out of range and did not refer to a valid register.
| |
| | |
| ====ALP3503: Can't use this register with scale factor====
| |
| In an indirect memory expression, the scaling operator (*) was applied to a register for which the processor does not support a scaling operation.
| |
| A scaling factor may only be used on 80386 or later processors, and only in 32-bit address expressions. Within this context, only the EAX, EBX, ECX, EDX, EDI, ESI, and EBP registers are valid. A scaling factor may not be applied to the ESP register.
| |
| | |
| ====ALP3504: Illegal target of self relative pointer====
| |
| The SHORT operator was used, but the expression to which it was applied was not a simple self relative displacement. This can occur if the expression is a constant, data label, or indirect memory operand.
| |
| | |
| ====ALP3505: Invalid mnemonic/operand combination====
| |
| This message appears when a valid mnemonic has been recognized and all operand expressions have been correctly parsed, but the assembler was unable to combine the results into a form that it could associate with a valid instruction encoding.
| |
| Recovery: This usually indicates that one or more operand expressions were not correctly specified. Verify such factors as:
| |
| * Correctly specified operand sizes
| |
| * Register combinations allowable for this instruction
| |
| * Labels or identifiers are of the correct type
| |
| * Correct number of operands
| |
| | |
| ====ALP3506: Register combination invalid with <number>-bit expression====
| |
| For 80386 processors or greater, both 16-bit and 32-bit effective addresses are supported, but the two modes differ in the register combinations that are allowed for indirect addressing. The expression used a combination that was invalid for the referenced address size.
| |
| For expressions that refer to 16-bit (USE16) memory locations, only a single base register (BX or BP) and/or a single index register (DI or SI) may be used.
| |
| For expressions that refer to 32-bit (USE32) memory locations, only a single base register (EAX, EBX, ECX, EDX, ESP, EBP, EDI, ESI) and/or a single index register (EAX, EBX, ECX, EDX, EBP, EDI, ESI) may be used; no single register may appear more than once in a given expression.
| |
| | |
| ====ALP3507: Scaling factor must be 1, 2, 4, or 8====
| |
| The processor only supports the scaling factors referenced in the message.
| |
| | |
| ====ALP3508: Invalid use of register====
| |
| One of the following illegal conditions occurred:
| |
| * An attempt was made to use an unsupported register in an indirect memory expression (for example, '''[AH]''').
| |
| * An attempt was made to combine a register with other terms to form an indirect memory expression, and the register was not enclosed in square brackets [ ].
| |
| * A register argument was expected and correctly parsed in an assembler directive, but the referenced register cannot be legally used in this particular context.
| |
| | |
| ====ALP3509: Multiple base registers====
| |
| An indirect memory expression contained a combination of registers that was invalid for the selected addressing mode. More than one register was evaluated as '''a base register''' by the assembler; the processor only supports a single base register within '''register indirect''' addressing mode.
| |
| For expressions that refer to 16-bit (USE16) memory locations, only '''BX''' and '''BP''' are valid base registers.
| |
| For expressions that refer to 32-bit (USE32) memory locations, only '''EAX, EBX, ECX, EDX, ESP, EBP, EDI,''' and '''ESI''' are valid base registers.
| |
| | |
| ====ALP3510: Multiple index registers====
| |
| An indirect memory expression contained a combination of registers that was invalid for the selected addressing mode. More than one register was evaluated as an '''index register''' by the assembler; the processor only supports a single index register within '''register indirect''' addressing mode.
| |
| For expressions that refer to 16-bit (USE16) memory locations, only '''DI''' and '''SI''' are valid index registers.
| |
| For expressions that refer to 32-bit (USE32) memory locations, only '''EAX, EBX, ECX, EDX, EBP, EDI,''' and '''ESI''' are valid index registers.
| |
| | |
| ====ALP3511: Multiple scaling factors====
| |
| In an indirect memory expression, the scaling operator (*) was applied to more than one register term. The processor does not support more that one scaling factor within a single effective address.
| |
| | |
| ====ALP3512: Near target cannot be in different code segment====
| |
| A JMP or CALL instruction specified a near target that was defined in a different segment, but the segments containing the instruction and the target were not named together in a GROUP directive. An instruction and its near target cannot be in different segments (addressed by the CS register) at run time.
| |
| | |
| Recovery: If the instruction was otherwise properly coded, use the GROUP directive to collect the segments together so that they will be accessible at run time with the same CS register value.
| |
| | |
| ====ALP3513: Need size for operand====
| |
| The instruction operand list did not specify a size for the operation, and the assembler is unable to select a default instruction encoding because multiple variations exist.
| |
| | |
| '''Recovery:''' As size may be assigned to one or more of the operands by using the <type> PTR override operator.
| |
| | |
| ====ALP3514: Cannot establish near target without ASSUME CS:====
| |
| When running the under MASM 5.10 emulation, the assembler requires the code segment register (CS) to have an ASSUME setting for the currently opened segment before it will allow the creation of explicit near code labels.
| |
| | |
| '''Recovery:''' Insert an "ASSUME CS:SegName" statement at the beginning of the segment before the appearance of any near code labels.
| |
| | |
| ====ALP3515: Code generation outside of segment boundaries====
| |
| A processor instruction was encountered, but no program segment has been opened.
| |
| | |
| '''Recovery:''' Place all processor instructions within a named program segment.
| |
| | |
| ====ALP3516: Target is out of range by <displacement> bytes(s)====
| |
| The instruction references a code label or address using a self-relative displacement (a signed value relative to the address of the next instruction), but the target address requires a displacement value that is too large to be encoded into the instruction.
| |
| | |
| '''Recovery:''' If the SHORT operator was used in the operand field, remove it. If the instruction is of the "conditional jump" variety, it may be necessary to transform it into a "jump around a jump" by inverting the condition under which the jump is performed, then changing the target so that it references an address immediately following a "direct jump" instruction, which must be inserted and coded so that it references the original target location.
| |
| | |
| ====ALP3517: Selected processor does not support this operand====
| |
| An attempt was made to use an operand (such as a machine register) that does not exist on the processor for which code is being generated.
| |
| | |
| '''Recovery:''' Either use a processor selection directive to select the correct target processor, or modify the referenced operand to one that is supported on the target machine.
| |
| | |
| ====ALP3518: Can't access data, no ASSUME or segment override====
| |
| One of the following conditions occurred:
| |
| * An attempt was made to reference a named memory location that exists in a segment for which no ASSUME statement is in effect
| |
| * An attempt was made to combine two terms in a binary expression that are relative to different segments.
| |
| | |
| ==== ALP3519: Too many operands====
| |
| This message appears during processing of an instruction operand list. More operand expressions were encountered than is valid for the instruction set of the target architecture.
| |
| | |
| '''Recovery:''' Remove the offending token(s) beginning at the referenced location.
| |
| | |
| ====ALP3520: Segment address size not supported on this processor====
| |
| A 16-bit processor selection directive was encountered within a 32-bit segment, or an attempt was made to reopen a 32-bit segment after switching to a 16-bit processor type. The selected processor cannot support 32-bit segments.
| |
| | |
| ====ALP3521: Register expected====
| |
| While processing an assembler directive an unexpected token was encountered at the referenced location. A processor register was expected instead.
| |
| | |
| ====ALP3522: Selected processor does not support this instruction====
| |
| A mnemonic or mnemonic/operand combination has been used that is not supported by the processor for which the assembler is currently generating object code.
| |
| | |
| '''Recovery:''' Verify that the correct target processor has been selected with one of the processor selection directives, or that the correct instruction form has been coded. Since ALP does not perform some of the same implicit conversions that MASM 5.10 does, use of the <type> PTR conversion operator may be required to avoid certain type-mismatch problems.
| |
| | |
| ====ALP3523: Cannot change expression word size====
| |
| After the expression word size was explicitly set with an OPTION EXPRxx directive, an attempt was made to alter the setting with another OPTION directive, or by switching to a 32-bit processor after an explicit OPTION EXPR16 was issued. Once set, the expression word size cannot be altered.
| |
| | |
| ====ALP3601: Filename expected====
| |
| The INCLUDELIB directive was used, but an error occurred while attempting to parse the filename parameter.
| |
| | |
| '''Recovery:''' Verify that only legal filename characters are used. If the filename appears as a quoted string literal, verify that the literal uses legal syntax according to the rules for quoted strings.
| |
| | |
| ====ALP3602: Floating-point initializer illegal with integer variable====
| |
| A floating point initializer was used on a variable that was not of type DD , DQ, DT, REAL4, REAL8, or REAL10.
| |
| | |
| ====ALP3603: Integer initializer illegal with floating-point variable====
| |
| An integer initializer was used on a variable that was of type REAL4, REAL8 , or REAL10. Only floating-point initializers can be used with variables having these types.
| |
| | |
| ====ALP3604: Expression has no effect====
| |
| During a data allocation directive, an attempt was made to initialize an item using an expression that was not correctly evaluated.
| |
| | |
| '''Recovery:''' This may indicate an error in the internal assembler logic. Note the conditions of the error, and contact IBM.
| |
| | |
| ====ALP3605: String is empty====
| |
| During a data allocation directive, an attempt was made to initialize an item using a quoted string expression that contained no data.
| |
| | |
| '''Recovery:''' Quoted strings must contain at least one character value, otherwise the expression is illegal.
| |
| | |
| ====ALP3606: Symbol "<identifier> was never defined====
| |
| An identifier was declared with a GROUP or PUBLIC directive, but was never given a full definition. This condition prevents the assembler from writing the appropriate records to the output object file.
| |
| '''Recovery:''' Segments declared in a GROUP directive must defined in a SEGMENT directive. Identifiers declared with the PUBLIC directive must be defined as a code label, data label, or absolute symbolic constant.
| |
| | |
| ====ALP3607: Value not addressable====
| |
| The expression following the END directive did not evaluate to segment relative address. The expression must refer to a memory location to which the operating system loader can pass control when the program is executed.
| |
| | |
| '''Recovery:''' Ensure that the expression contains no machine registers, and that it references a value relative to a segment defined within the module.
| |
| | |
| ====ALP3608: Segment size exceeds 64K limit====
| |
| The amount of data emitted into the current (16-bit) segment has exceeded 65536. No object file can be produced under this condition, and the current location counter has been wrapped back to zero.
| |
| | |
| '''Recovery:''' Reduce the amount of code or data contained in this segment, or move some of the information to another segment.
| |
| | |
| ====ALP3701: Argument expected====
| |
| While processing a directive that accepts a list of comma separated arguments, at least one argument followed by a comma was parsed, but no additional argument was encountered before the end of the line.
| |
| | |
| ====ALP3702: Can't override array with single item====
| |
| Within a structure variable instantiation, an incorrect attempt was made to override the default initializer of a structure member. The structure member was defined to be of type array (having been initialized with a character string or list of expressions enclosed in brackets), and the overriding expression in the structure instantiation was a single numeric expression.
| |
| | |
| '''Recovery:''' Array members can only be overridden using a quoted character string or a bracketed list of numeric expressions.
| |
| | |
| ====ALP3703: .RADIX value must be one of: 2, 8, 10, or 16====
| |
| Self-explanatory.
| |
| | |
| ====ALP3704: Can't nest initializers====
| |
| This message appears when a structure instantiation contained a nested override initializer within brackets, and OPTION OLDSTRUCTS was in effect. Nested structures are not allowed when the assembler is operating in this mode.
| |
| | |
| ====ALP3705: Colon expected====
| |
| Self-explanatory.
| |
| | |
| ====ALP3706: Expecting "<" or "{"====
| |
| When a structure or record variable is allocated, the assembler expects one or more initializer expressions to follow the structure or record type name. Initializer expressions must be enclosed in angle brackets or braces, but an unexpected token was encountered at the referenced location.
| |
| | |
| ====ALP3707: Initializer too long or incorrect type====
| |
| Within the initializer list of a structure instantiation, one of the following conditions occurred:
| |
| * An attempt was made to initialize a structure member with a character string override that exceeded the length of the member definition.
| |
| * The initializer expression type did not match that of the structure member item being initialized.
| |
| | |
| ====ALP3708: Invalid ALIGN setting====
| |
| A zero or incorrect value was specified as the argument to the ALIGN directive.
| |
| | |
| ====ALP3709: Previous definition prevents external attribute====
| |
| An attempt was made to declare an identifier as being external to this module, but a previous conflicting definition already exists. The operation is disallowed.
| |
| | |
| ====ALP3710: Syntax error; unexpected token====
| |
| The referenced token is not valid for the construct being parsed. The assembler could not attempt further processing or diagnosis of the construct.
| |
| | |
| ====ALP3711: Previous definition prevents change in global visibility====
| |
| One of the following conditions has occurred:
| |
| * The PUBLIC directive or keyword was used to export an identifier, but the identifier has already been declared with attributes that prevent it from being exported.
| |
| * A PUBLIC directive was used on a procedure name, but the PRIVATE keyword was used in the PROC directive that defined the procedure.
| |
| Recovery: Verify that the identifier does not appear in a COMM or EXTERN declaration, and that the identifier is a valid code or data label. Insure that the PUBLIC declaration appears before the identifier it references, and that the declaration is processed by the assembler on the first pass.
| |
| | |
| ====ALP3712: "<token>" must be a segment name====
| |
| This message appears during processing of the GROUP directive when one of the arguments was not a valid segment name.
| |
| | |
| '''Recovery:''' Only identifiers defined using the SEGMENT directive are valid arguments to the GROUP directive. If the message is referencing an identifier, verify that it is indeed the name of a valid segment. Verify that the identifier was specified using the correct uppercase and lowercase letters if case sensitive assembly is in effect.
| |
| | |
| ====ALP3713: Label outside of segment boundaries====
| |
| This message appears when a label definition appears outside of any enclosing segment.
| |
| The label is an assembler alias for a segment relative machine address; such an address cannot be assigned to the label unless it appears inside of a program segment. This condition is an error, and must be corrected.
| |
| | |
| '''Recovery:''' Place the definition within a valid segment.
| |
| | |
| ====ALP3714: Directive must be named====
| |
| This message appears when a directive was encountered but was not preceded by a label. A label is required for this directive.
| |
| | |
| '''Recovery:''' Precede the directive with a valid identifier.
| |
| | |
| ====ALP3715: Must specify all columns in .LIST ORDER====
| |
| The .LIST ORDER directive did not specify a position for every possible column. All column names must appear in the list.
| |
| | |
| ====ALP3716: Listing control stack is empty====
| |
| This message appears when the user issues a .LIST POP directive and there are no listing environment entries on the stack.
| |
| | |
| '''Recovery:''' A matching .LIST PUSH directive must be issued before .LIST POP may be used.
| |
| | |
| ====ALP3717: Processor mnemonic used as a label====
| |
| This message is issued when a processor instruction mnemonic is used as an identifier. The severity of this message may be relaxed from Error to Warning in certain circumstances by using the '''+Sk''' command line switch.
| |
| | |
| Related Information:
| |
| * [[#Sk - Control Use of Reserved Words as Labels]]
| |
| | |
| ====ALP3718: Misplaced ENDP; no open PROC====
| |
| This error occurs when the ENDP (end procedure) directive was encountered, but there is no procedure currently open.
| |
| | |
| '''Recovery:''' The PROC directive must be used to open a procedure before the ENDP directive can be used.
| |
| | |
| ====ALP3719: No closing bracket====
| |
| An opening bracket "[" was encountered within a directive or expression, but a matching close bracket "]" was never supplied, or was misplaced.
| |
| | |
| ====ALP3720: Data allocation outside of segment boundaries====
| |
| A data definition directive was encountered, but no program segment has been opened.
| |
| | |
| '''Recovery:''' Place all data allocation directives within a named program segment.
| |
| | |
| ====ALP3721: Operation illegal within structure or union====
| |
| An attempt was made to use a directive or construct that is illegal within the context of a structure definition.
| |
| | |
| '''Recovery:''' Processor instructions are not allowed in structure definitions, and only a subset of assembler directives are legal in this context.
| |
| | |
| ====ALP3722: Expression is not a segment or group====
| |
| One of the following illegal conditions occurred:
| |
| * A segment override expression (using the colon (:) operator) did not contain a valid segment register, segment name or group name expression on the left side of the colon operator.
| |
| * An ASSUME directive contained an expression that did not evaluate to a valid segment or group name. The argument to the ASSUME directive specified a machine segment register, which may only be associated with a segment or group name.
| |
| | |
| '''Recovery:''' Verify the correct spelling of either the register argument or the segment name or group name expression.
| |
| | |
| ====ALP3723: ON or OFF expected====
| |
| A listing control directive was encountered where the value of a flag is being manipulated; the ON or OFF keywords are the only values acceptable in this context.
| |
| | |
| ====ALP3724: ON, OFF, or BLANK expected====
| |
| A listing control directive was encountered where the display or non-display of an individual column is being determined; the ON, OFF, or BLANK keywords are the only values acceptable in this context.
| |
| | |
| ====ALP3725: Phase error between passes====
| |
| The address assigned to a label on pass one of the assembler had a different value on the second pass.
| |
| This usually indicates that a forward reference to a label was not fully qualified, and the eventual definition of the label was different than what was assumed by the assembler on the first pass. On the second pass, the assembler did not need to make any assumptions about the attributes of the symbol, but the resulting generation of object code caused a discrepancy in the value of the location counter.
| |
| | |
| '''Recovery:''' Use the listing control command line options to request a listing for both pass one and pass two of the assembler; use this listing to compare location counter values prior to the point where the phase error occurred. This will reveal the instruction that caused the location counter to become unsynchronized.
| |
| | |
| Related Information:
| |
| * [[#Lp - Generate Listing on Specific Pass]]
| |
| | |
| ====ALP3726: Symbol already defined as different type====
| |
| An identifier has been redeclared to have attributes that conflict with a previous declaration or definition.
| |
| | |
| '''Recovery:''' If this is an external declaration (using an EXTRN or COMM directive) referencing a data variable, ensure that the type specifier has been correctly respecified. Verify that the variable has not already been defined within this module.
| |
| External declarations for data labels or near code labels appearing within segment boundaries must not reappear within the boundaries of a different segment. Labels appearing outside of segment boundaries inherit the default address size (USE16 or USE32), and must not reappear within a segment having a conflicting address size.
| |
| Far code labels may not be redeclared with conflicting address sizes.
| |
| | |
| ====ALP3727: PROC name mismatch====
| |
| The ENDP directive was used to close the current procedure, but the name used in the ENDP directive did not match the name specified in the matching PROC directive.
| |
| | |
| ====ALP3728: Symbol redeclared relative to different segment====
| |
| A data label or near code label appearing in an external declaration was redeclared in a different segment (or outside of segment boundaries) and conflicts with a previous declaration or definition.
| |
| | |
| '''Recovery:''' Data labels or near code labels appearing within segment boundaries must not reappear within the boundaries of a different segment. Labels appearing outside of segment boundaries inherit the default address size (USE16 or USE32), and must not reappear within a segment having a conflicting address size.
| |
| | |
| ====ALP3729: Attribute mismatch during reopen of segment====
| |
| An existing segment was reopened using different or conflicting attributes.
| |
| | |
| '''Recovery:''' All identically named SEGMENT directives must be declared with the same attribute list.
| |
| If an address size attribute (USE16 or USE32) was not explicitly specified in the SEGMENT directive, verify that the default segment word size was not altered between segment declarations with a processor selection directive.
| |
| | |
| ====ALP3730: No segment, structure, or union opened as "<identifier>"====
| |
| The ENDS directive was used, but no segment, structure, or union was open ( or did not match the referenced name) and thus could not be terminated.
| |
| | |
| '''Recovery:''' If a name was given in the message, verify that it matches the name used in the associated SEGMENT, STRUC, or UNION directive. Verify that nested occurrences of SEGMENT, STRUC, or UNION are paired with a matching ENDS directive.
| |
| | |
| ====ALP3731: Identifier expected====
| |
| A directive or expression operator was used such that an identifier was expected, but none was supplied.
| |
| | |
| '''Recovery:''' Check for a possible misspelled identifier; Verify that the identifier was specified using the correct uppercase and lowercase letters if case sensitive assembly is in effect. Verify that the identifier is not a reserved keyword.
| |
| | |
| ====ALP3732: Reserved symbol "<identifier>" cannot be created or modified====
| |
| An invalid operation was performed on a reserved identifier. One of the following conditions occurred:
| |
| * An attempt was made through an EQU (or =) directive to alter the value of a predefined identifier. Unless documented otherwise, this is an illegal operation.
| |
| * The assembler attempted the deferred creation of a reserved symbol, but a user-defined identifier already exists with the same name and has conflicting attributes.
| |
| | |
| ====ALP3733: Symbol redefinition error====
| |
| An attempt was made to redefine an identifier in a context where redefinitions are not allowed. Redefinitions are allowed only for text macros and assembler variables assigned using the equal (=) directive.
| |
| | |
| ====ALP3734: Too many initializers====
| |
| A bracketed expression list within a structure instantiation or record constant contained too many comma-separated expressions. The number of initializer expressions exceeded the number of elements in the structure or record definition.
| |
| | |
| ====ALP3735: Qualified type or type keyword expected====
| |
| This message appears when a type expression or a COMM, EXTRN, or LABEL directive was expecting a type keyword, but none was supplied.
| |
| | |
| ====ALP3736: Unexpected text in statement====
| |
| An assembler directive was fully parsed and recognized, but invalid information was encountered at the referenced location.
| |
| | |
| ====ALP3737: <text>====
| |
| This assembler issues this message to display user defined text when the ECHO or %OUT directives are encountered.
| |
| | |
| ====ALP3738: Symbol redefinition has different value====
| |
| An attempt was made to redefine an EQU symbol to value which differs from a previous definition. EQU symbols may have multiple definitions only if they have identical constant values.
| |
| | |
| ====ALP3739: Directive illegal outside of segment boundaries====
| |
| The referenced directive performs a segment-relative operation and may only be used inside of segment boundaries.
| |
| | |
| ====ALP3740: Alignment value must be a power of 2====
| |
| The expression argument given in the ALIGN directive did not evaluate to a power of 2 (2, 4, 8, etc.).
| |
| | |
| ====ALP3741: Alignment value not valid with current segment alignment====
| |
| The referenced alignment factor was less than the alignment factor specified in the SEGMENT declaration containing the ALIGN or EVEN statement . This condition is illegal because the assembler cannot guarantee that the linker will not invalidate the requested alignment when it exercises its right to position the entire segment according to the alignment factor given in the enclosing SEGMENT declaration.
| |
| | |
| '''Recovery:''' Respecify either the aligment factor or the SEGMENT delaration so that the segment alignment is greater than or equal to any alignment factor requested therein.
| |
| | |
| ====ALP3742: Redefinition has different number of fields====
| |
| A RECORD type redefinition did not contain the same number of fields as a previous definition.
| |
| | |
| ====ALP3743: Redefinition has different value====
| |
| A redefinition construct was encountered (such as a type definition directive) where the redefined value did not match that of a previous definition. Redefinitions are allowed for this particular construct, but they must restate the same value given in the original definition.
| |
| | |
| ====ALP3744: Too many bits in record definition====
| |
| The referenced record definition exceeded the maximum allowable value of 32 bits.
| |
| | |
| ====ALP3745: Record tag or fieldname expected====
| |
| The operand of the MASK or WIDTH operators must be an identifier defined with the RECORD directive. This identifier must be either the tag name of the record itself, or one of the field name entries defined within the body of the RECORD directive.
| |
| | |
| ====ALP3746: Value is out of range====
| |
| The value of the referenced expression is not representable, requires too many significant bits to be stored, or lies outside the range of legal values for this context.
| |
| | |
| ====ALP3747: Mismatch of segment address sizes in group====
| |
| A group was declared to contain segments of differing address sizes. A group may contain either USE16 or USE32 segments, but not a combination of both.
| |
| | |
| ====ALP3748: Segment already a member of group "<group-name>"====
| |
| An attempt was made to assign a segment to more than one parent group.
| |
| | |
| ====ALP3749: Directive requires use of .MODEL====
| |
| A simplified segmentation operation was encountered but a .MODEL directive was never processed.
| |
| | |
| ====ALP3750: PROC must immediately precede LOCAL====
| |
| A LOCAL assembler directive was encountered, and one of the following occurred:
| |
| * The LOCAL directive was not enclosed within a PROC/ENDP procedure block.
| |
| * The LOCAL directive was positioned within a procedure block, but other assembler directives or instructions were encountered between the PROC directive and the LOCAL directive.
| |
| | |
| ====ALP3751: Operand has incorrect size====
| |
| The size given for an operand was incorrect, or did not match that of a destination or target operand where it is to be used.
| |
| | |
| ====ALP3752: Mismatch in <attribute> attribute====
| |
| The value of an attribute specified in a redeclaration or redefinition did not match the value given in the original declaration or definition. The body of the message indicates the type of attribute that is mismatched, and the assembler follows this message with two 5704 informational messages showing the coordinates and values of the mismatched constructs.
| |
| | |
| ====ALP3753: Name collision caused by promotion from inner scope====
| |
| During a definition of a structure (or union) type, a field identifier defined at the outer (current) scope had the same name as a field defined in a promoted inner scope (one created through the use of an unnamed imbedded structure). When a structure type is used to create an unnamed field within another structure type, all of the field names from the inner structure are "promoted", or made visible to the outer defining scope.
| |
|
| |
| '''Recovery:''' One of the field identifier names must be altered to avoid the name collision. Alternatively, the unnamed imbedded structure may be given an explicit field name, in which case its own fields are no longer promoted, and fully-qualified references must be used to reach them from within expressions.
| |
| | |
| ====ALP3754: Cannot determine calling convention====
| |
| A procedure was defined to accept arguments passed on the stack by a calling routine, but no language attribute was specified or assumed for the procedure. The language attribute determines the calling convention, which in turn defines the order that arguments are pushed onto the stack.
| |
| | |
| '''Recovery:''' Use one of the following constructs:
| |
| * Specify an explicit language keyword in the body of the PROC directive.
| |
| * Specify a .MODEL directive with a language keyword argument.
| |
| * Specify an OPTION LANGUAGE directive.
| |
| | |
| ====ALP3801: Argument expected====
| |
| When processing one of the EQU, IRP, IRPC, FOR, or FORC macro directives, the required argument immediately following the directive was missing or incorrectly specified.
| |
| | |
| '''Recovery:''' Modify the referenced token so that it is a valid argument for the directive. If this directive appears within a nested macro expansion, check to see that correct arguments were passed to outer level macros, or that outer level macro definitions are correct.
| |
| | |
| ====ALP3802: EXITM outside of macro====
| |
| The EXITM keyword was encountered outside the context of a macro body.
| |
| | |
| '''Recovery:''' Verify that unexpected conditional assembly results are not affecting the block structure of the program. The EXITM keyword may not be used outside the scope of a macro body.
| |
| | |
| ====ALP3803: Comma expected====
| |
| Self-explanatory. This message is displayed for any preprocessor directive that requires a comma where one was not supplied.
| |
| | |
| ====ALP3804: Extra data on line====
| |
| This message appears any time the preprocessor has parsed a correctly formed preprocessor directive, but additional token(s) (other than comments were encountered before the end of line was reached.
| |
| | |
| '''Recovery:''' Remove the offending token(s) beginning at the referenced location.
| |
| | |
| ====ALP3805: Filename expected====
| |
| This message appears when an INCLUDE preprocessor directive did not contain a properly formed filename. The INCLUDE directive is ignored.
| |
| | |
| ====ALP3806: <text>====
| |
| This is the message printed as part of a conditional error directive; if one of these directives is processed and the user has included text information to be printed, it will appear in the <text> field of the message. If no user text was specified, this parameter will be empty and the message will contain no additional text.
| |
| | |
| Recovery: This was a forced error.
| |
| | |
| ====ALP3807: Identifier expected====
| |
| This message appears when a conditional preprocessor directive was expecting an identifier and one was not supplied.
| |
| | |
| ====ALP3808: Reserved macro "<macro-name>" cannot be redefined====
| |
| The assembler defines the referenced identifier for its own purposes; it may not be redefined by the user.
| |
| | |
| ====ALP3809: Missing ENDM====
| |
| The preprocessor was reading the body of a macro definition when the end of the current input stream was reached; the macro definition was never closed with an ENDM keyword.
| |
| | |
| '''Recovery:''' Verify that unexpected conditional assembly results are not affecting the block structure of the program. A macro definition may not be closed in an input stream different from the one where it was started.
| |
| | |
| ====ALP3810: <ELSExx/ENDIF> without matching IFxxx====
| |
| This message indicates that an ELSE or ENDIF construct was encountered prior to encountering an IF construct.
| |
| | |
| ====ALP3811: Reserved symbol "<identifier>" cannot be modified====
| |
| An attempt was made through the '''-D''' command line option to alter the value of a predefined identifier. Unless documented otherwise, this is an illegal operation.
| |
| | |
| ====ALP3812: Symbol "<identifier>" already defined====
| |
| An attempt was made to define a preprocessor macro name that conflicts with an existing identifier of an incompatible type.
| |
| | |
| ====ALP3813: <Text-Item> expected====
| |
| This message is displayed when a preprocessor directive expected a text argument enclosed in angle brackets < >, but a valid argument was not supplied.
| |
| | |
| ====ALP3814: Invalid character in numeric constant====
| |
| The assembler was parsing a numeric constant and an alphabetic character was encountered that was not a valid radix specifier or hexadecimal digit.
| |
| | |
| ====ALP3815: Illegal digit(s) for specified radix====
| |
| A literal integer constant was qualified with radix override, but was specified using digits that are not valid for the given radix qualifier. For instance, use of the literal '''1234Y''' is not legal because the '''Y''' suffix specifies a binary number and only the digits '''0''' and '''1''' are valid binary digits.
| |
| | |
| ====ALP3816: Expecting ">"====
| |
| This message appears when the preprocessor is parsing a <text-item> and the end of line or end of file was encountered. A closing angle bracket (>) was expected.
| |
| | |
| ====ALP3817: Unterminated COMMENT====
| |
| The preprocessor was scanning the body of a COMMENT directive when the end of the current input stream was encountered; the closing delimiter character originally specified in the COMMENT directive was never encountered.
| |
| | |
| '''Recovery:''' Block comments may not span across input files. Provide a closing delimiter as specified in the opening COMMENT directive.
| |
| | |
| ====ALP3896: Control character illegal in this context====
| |
| A COMMENT preprocessor directive was encountered, and an attempt was made to scan for the next character which signifies the beginning and end of the comment text, but an unexpected non-printable control character was encountered instead.
| |
| | |
| '''Recovery:''' Only characters that are representable as printable text may be used to open and close a COMMENT sequence.
| |
| | |
| ====ALP3897: No closing quote====
| |
| The preprocessor was parsing a quoted string literal, and the end of line or other terminator was encountered before the literal was ended with a closing quote character.
| |
| | |
| '''Recovery:''' Verify that only single quotes (´´) or double quotes ("") are used to open and close a string literal; they must be used in pairs. Verify that the ending quote character was not immediately preceded by another identical quote character; the assembler interprets this sequence as a request to insert a quote character into the string literal.
| |
| | |
| ====ALP3898: Unexpected end of file====
| |
| The lexical analyzer portion of the assembler preprocessor was scanning within the body of a token (for example, a block comment), when the end of the input stream was encountered.
| |
| | |
| ====ALP3899: Unexpected terminator====
| |
| The lexical analyzer portion of the assembler preprocessor was performing a text substitution operation as directed by one of the "!" or "&" operators, when the end of file or internal macro buffer was encountered.
| |
| | |
| ===Message Numbers 4000-4999: Warning Messages===
| |
| Warning messages are issued when the assembler detects a questionable construct in the input stream. The condition is not severe enough to prevent generation of an object file, but the situation should be investigated and corrected since the output program may be incorrect.
| |
| | |
| ====ALP4201: Offset operator applied to register-indirect expression====
| |
| An OFFSET operator was applied to a register-indirect expression. In MASM 5.10 emulation mode this does not cause conversion to an immediate expression; instead the register-indirect addressing mode attributes are retained, and the assembler applies the OFFSET operator to the displacement field, forcing it to have the size of the address offset. Applying the OFFSET operator to a register-indirect expression is illegal if the assembler is not operating under MASM 5.10 emulation.
| |
| ====ALP4202: Invalid type expression; cannot convert====
| |
| Under MASM 5.10 emulation, a constant numeric expression may be used as the left-hand operand of the PTR operator. In the referenced expression, the left-hand operand of the PTR operator did not evaluate to a value suitable for use as the operand size of the right-hand operand. The operand size of the right-hand operator was not converted.
| |
| ====ALP4203: Type conversion operation has no effect====
| |
| A type conversion operation involving the PTR operator was performed on an expression whose type cannot be modified. For example, the right operand of the PTR operator cannot be a register value.
| |
| ====ALP4401: Error closing listing file====
| |
| An error occurred while attempting to close the referenced file.
| |
| Recovery: Verify that no other processes are accessing the file, and that the file system is functioning correctly.
| |
| ====ALP4402: Error deleting listing file====
| |
| An error occurred while attempting to delete the referenced file.
| |
| Recovery: Verify that no other processes are accessing the file, and that the file system is functioning correctly.
| |
| ====ALP4501: Assuming NEAR distance for operand size====
| |
| A CALL or JMP instruction was coded to pass control indirectly through a memory operand of indeterminate size. When operating in MASM 5.10 emulation mode, the memory operand is assumed to have the same size as address size of the segment containing the CALL or JMP instruction, and implies a target having NEAR distance.
| |
| Recovery: The memory operand should be given an explicit size, regardless of whether or not the default address size and NEAR distance is the desired operation. This code will cause assembly errors if not assembled under MASM 5.10 emulation mode.
| |
| ====ALP4502: Can't ASSUME CS to a grouped segment====
| |
| An attempt was made to ASSUME the CS register to a segment that was previously named in a GROUP directive. This implies that the CS register might have different values to access the same body of code at runtime. This is illegal, and the assembler altered the ASSUME operation to refer to the group containing the segment instead.
| |
| Recovery: If running the assembler under MASM 5.10 emulation, change the ASSUME directive to refer to the group name containing the segment; otherwise, remove the ASSUME statement.
| |
| ====ALP4503: Operand size does not match instruction====
| |
| This is a warning message that appears when an operand specifies a size that differs from the operand size of the instruction. In this case, the operand size is implied by the instruction itself, and an explicit operand size is not required. However, if an operand size is supplied, it must match the implied size or this warning will be issued.
| |
| ====ALP4504: [Constant] is immediate in MASM mode====
| |
| This message indicates that a single expression coded as a constant value in square brackets [ ] is treated as though the brackets were not specified (when the assembler is operating in MASM emulation mode, which is the default). This warning is issued because brackets are required for an indirect memory expression when registers are involved, and the connotation is that the presence of brackets is required to force a memory reference, when in fact they are ignored.
| |
| Recovery: Use a segment override (for example, DS:[1234h]) when an indirect memory reference to an absolute address is desired. As explained above, the presence of brackets shown in the example is not required, but they are preferred for readability.
| |
| Note: A future release may provide an alternate mode of operation such that bracketed constant values will be treated as memory references; this warning message thus points out constructs that are incompatible with any future releases operating in this mode. Since the presence of brackets are currently redundant in this context (and indicate a possible programming error), it is recommended that they be removed.
| |
| ====ALP4505: Access to data through a code label====
| |
| This warning occurs when an instruction attempts a memory access through a code label (a procedure name or a label followed by a colon). This is an invalid operation unless a type conversion is first performed on the expression containing the label.
| |
| ====ALP4506: Selected processor does not support this instruction====
| |
| This message is issued under the same circumstances as message ALP3522, but has reduced severity when the assembler is operating under MASM emulation.
| |
| ====ALP4507: Only storing NEAR portion of FAR pointer====
| |
| Within a data allocation directive, a variable was initialized to contain the address of a FAR code label or variable defined in another segment. However, the size of the variable being initialized is not large enough to hold the fully qualified address (both segment and offset) of the item, and only the offset portion was stored.
| |
| Recovery: If the full address of the pointer is desired, then the size of the data item being initialized must be increased. Otherwise, the OFFSET operator should be used in the address expression to truncate the segment information and suppress this warning.
| |
| ====ALP4508: Operand size inferred from immediate value====
| |
| When operating under MASM 5.10 emulation mode, the assembler allows an immediate value to determine the size of the memory operand to which it is applied if its magnitude exceeds that which will fit into a byte. In this case, it is assumed that the operation refers to a word-sized memory operand (2 bytes in USE16 segment, 4 bytes in a USE32 segment). If the magnitude of the immediate value is sufficiently small (less than 128), then the operation is ambiguous, and an error is generated because the assembler does not know whether to treat the memory operand as a byte or a word value.
| |
| Recovery: An explicit size should be given to the memory operand. Code relying on this behavior will not assemble correctly if the assembler is not operating in MASM 5.10 emulation mode.
| |
| ====ALP4509: Operand size mismatch====
| |
| One of the following conditions occurred:
| |
| * An attempt was made within a data allocation directive to initialize an item with an expression having an explicit and different size.
| |
| * A memory operand with an explicit size was used in conjunction with a register operand, but two operand sizes did not match. The register operand size overrides the size of the memory operand.
| |
| * A memory operand with an explicit size was used in conjunction with an address offset. The size of the memory operand and the size implied by the address size of the offset value did not match.
| |
| ====ALP4510: Truncation of significant bits in immediate value====
| |
| One of the following conditions occurred:
| |
| * An operand expression was encoded into the instruction as an immediate value, but the magnitude of the numeric expression exceeded the number of bits required to store it in instruction encoding; the value was truncated to fit in the allotted space.
| |
| Since the assembler uses 32-bit arithmetic during expression processing, operations such as negation or logical inversion of small numeric quantities can result in values that require all 32 bits of precision.
| |
| * A relocatable immediate expression was converted to a smaller type, thus affecting the type of the relocation record generated for resolution by the linker. This could happen if an offset expression was forced into a byte sized storage space.
| |
| Recovery: Use the <type> PTR override to explicitly convert the expression to a value of the proper size.
| |
| ====ALP4512: Can't ASSUME CS to different segment or group; ignored====
| |
| Within an open segment, an attempt was made to ASSUME the CS register to a different segment, or to a group not containing the currently opened segment. The operation was not allowed.
| |
| Recovery: Remove the ASSUME statement, or adjust it so that it specifies the currently opened code segment or a group containing the segment.
| |
| ====ALP4513: Invalid mnemonic/operand combination====
| |
| This message is issued under circumstances similar to that of message ALP3505. In this case an instruction encoding was found for the given mnemonic/operand combination, but the encoding is considered invalid when the assembler is not operating under this level of MASM emulation; thus this warning is issued.
| |
| ====ALP4514: No size for operand, assuming default====
| |
| This message indicates that no operand size was given for the instruction, but the assembler was able to infer an operand size from the instruction itself. This message is only issued when the assembler is operating under MASM 5.10 emulation. In this mode, a default operand size is associated with certain processor mnemonics; this default value is used when no explicit operand size is given.
| |
| Recovery: An explicit operand size should be given for the referenced expression because the assembler is automatically resolving a potentially dangerous ambiguity in its selection of a default operand size.
| |
| ====ALP4601: Error closing object file ====
| |
| An error occurred while attempting to close the referenced file.
| |
| Recovery: Verify that no other processes are accessing the file, and that the file system is functioning correctly.
| |
| ====ALP4602: Error deleting object file ====
| |
| An error occurred while attempting to delete the referenced file.
| |
| Recovery: Verify that no other processes are accessing the file, and that the file system is functioning correctly.
| |
| ====ALP4603: Missing END====
| |
| The end of file was encountered but an END directive was never processed. All top-level assembler modules invoked from the command line must have an END directive as the last statement in the file. Files processed with the INCLUDE preprocessor directive should not contain an END statement.
| |
| ====ALP4701: Unterminated PROC====
| |
| When the end of the source input stream was encountered, it was determined that a procedure was opened with a PROC directive, but never closed.
| |
| Recovery: Any procedures opened with PROC must be closed within the same input stream using the ENDP directive.
| |
| ====ALP4702: Unterminated segment ""====
| |
| When the end of the source input stream was encountered, it was determined that a segment was opened with a SEGMENT directive, but never closed.
| |
| Recovery: Any segments opened with SEGMENT must be closed within the same input stream using the ENDS directive.
| |
| ====ALP4703: Unterminated structure or union====
| |
| When the end of the source input stream was encountered, it was determined that a structure or union was opened with a STRUC/STRUCT or UNION directive , but never closed.
| |
| Recovery: Any structure or union must be terminated using the ENDS directive.
| |
| ====ALP4704: Address size mismatch====
| |
| The referenced address expression was used as a source operand, but the address size of the expression did not match the size of the target operand . An implicit conversion was applied to the address size of the referenced expression.
| |
| ====ALP4706: Processor mnemonic used as a label====
| |
| This message is issued when a processor instruction mnemonic is used as an identifier. This condition is normally an error if the +Sk command line switch is turned off.
| |
| Related Information:
| |
| *Sk - Control Use of Reserved Words as Labels
| |
| | |
| ====ALP4707: Alignment value not valid with current segment alignment====
| |
| The referenced alignment factor was less than the alignment factor specified in the SEGMENT declaration containing the ALIGN statement. This condition is illegal because the assembler cannot guarantee that the linker will not invalidate the requested alignment when it exercises its right to position the entire segment according to the alignment factor given in the enclosing SEGMENT declaration.
| |
| Note: This condition is allowed to exist as a warning under MASM 5.10 emulation for backward compatibility with existing source files.
| |
| Recovery: Respecify either the aligment factor or the SEGMENT delaration so that the segment alignment is greater than or equal to any alignment factor requested therein.
| |
| ====ALP4708: Symbol redeclared relative to different segment====
| |
| This message is issued under the same circumstances as message ALP3728, but has reduced severity when the assembler is operating under MASM emulation.
| |
| ====ALP4709: Label outside segment boundaries====
| |
| This message is issued under the same circumstances as message ALP3713, but has reduced severity when the assembler is operating under MASM 5.10 emulation.
| |
| ====ALP4710: Identifier expected====
| |
| This message is issued under the same circumstances as message ALP3731, but has reduced severity when the assembler is operating under MASM 5.10 emulation.
| |
| ====ALP4711: Attribute respecification ignored====
| |
| An attempt was made in a directive to change an attribute that has already been specified. Once set, the attribute cannot be changed. If the attribute is respecified, it must match the existing setting or this warning will be issued.
| |
| ====ALP4712: Mismatch of segment address sizes in group====
| |
| This message is issued under the same circumstances as message ALP3747, but has reduced severity when the assembler is operating under MASM 5.10 emulation.
| |
| ====ALP4713: Attribute mismatch during reopen of segment====
| |
| This message is issued under the same circumstances as message ALP3729, but has reduced severity when the assembler is operating under MASM 5.10 emulation.
| |
| ====ALP4801: Identifier expected, condition is false====
| |
| For compatibility with MASM, the IFDEF and IFNDEF preprocessor directives will accept a non-identifier token as an argument, but this warning is issued to indicate that the condition cannot be properly tested, and the result is always false.
| |
| Recovery: Modify the argument so that it is a correctly formed identifier.
| |
| ====ALP4802: Extra data on line====
| |
| This message appears under the same conditions as that of ALP3804, but for better compatibility with MASM the severity has been reduced from an error to a warning. This message will be issued if an IFDEF, IFNDEF, ELSEIFDEF, or ELSEIFNDEF directive contains extra data at the end of the line.
| |
| Recovery: Remove the offending token(s) beginning at the referenced location.
| |
| ====ALP4803: Expecting ">"====
| |
| This message appears when the preprocessor is parsing a <text-item> and the end of line or end of file was encountered. A closing angle bracket (>) was expected.
| |
| ====ALP4804: Expression expected, zero assumed====
| |
| For compatibility with MASM, certain preprocessor directives that expect an expression operand will not issue an error if the operand is absent. This warning is issued instead to indicate that an implicit expression value of zero is assumed.
| |
| ====ALP4899: Illegal character====
| |
| This message is issued by the text preprocessor when a character was encountered in the source stream that is not part of the valid execution character set.
| |
| Recovery: This may cause undefined behaviors, and a text editor should be used to remove the offending character.
| |
| | |
| ===Message Numbers 5000-5999: Informational Messages===
| |
| Informational messages may be requested with a command line option (see [[#M - Control Individual Messages or Groups]]) and provide the user with a variety of useful information. All informational messages are disabled by default.
| |
| | |
| ====ALP5001: Number of Errors :<number>====
| |
| Informs the user of the number of error messages issued during the assembly.
| |
| | |
| ====ALP5002: Number of Warnings :<number>====
| |
| Informs the user of the number of warning messages issued during the assembly.
| |
| | |
| ====ALP5003: Number of Symbols :<number>====
| |
| This message indicates how many user identifiers were defined during the assembly.
| |
| | |
| ====ALP5101: Opened message output file "<file>"====
| |
| This message indicates that the message output processor has opened and is prepared to write to the referenced file.
| |
| | |
| ====ALP5201: Operand is declared relative to "<identifier>"====
| |
| This message indicates that the referenced relocatable expression is declared relative to the given segment or group name.
| |
| | |
| ====ALP5301: Assembler is on source pass <number>====
| |
| This messages indicates that the assembler has begun processing the referenced pass through the input stream.
| |
| | |
| ====ALP5401: Closed listing output file "<file>"====
| |
| This message indicates that the listing file processor has closed the referenced file.
| |
| | |
| ====ALP5402: Deleted listing output file "<file>"====
| |
| This message indicates that the listing file processor has deleted the referenced file.
| |
| | |
| ====ALP5403: Opened listing output file "<file>"====
| |
| This message indicates that the listing file processor has opened and is prepared to write to the referenced file.
| |
| | |
| ====ALP5501: Address size is <USE16/USE32>====
| |
| This message provides information to supplement the occurrence of other related warning or error messages. The expression referenced by the message coordinates has inherited or has been assigned the address size given in the message text.
| |
| | |
| ====ALP5502: No size for operand, assuming default====
| |
| This message indicates that no operand size was given for the instruction, but the assembler was able to infer an operand size from the instruction itself.
| |
| | |
| ====ALP5503: Instruction padded with NOP(s)====
| |
| This message indicates that the assembler generated one or more NOP instructions to follow the object code generated for the referenced instruction. The instruction operand list contains a forward-referenced expression which forced the assembler to allow space for the longest possible instruction encoding on the first pass. The generation of NOP instructions may be avoided by qualifying the forward reference with a <type> PTR override.
| |
|
| |
| ====ALP5504: Operand size is <number>====
| |
| This is an informational message that typically accompanies other errors or warnings dealing with operand size problems. This message is issued for every operand expression involved in the condition that caused the associated error or warning message, and indicates the operand size of the referenced expression.
| |
| | |
| ====ALP5505: Segment override has no effect====
| |
| This message is issued when a segment override operator was used in an expression, but the override was discarded because the offset operator was applied.
| |
| | |
| ====ALP5506: Generated ASSUME CS:<signal>====
| |
| This message is issued when an attempt is made to generate code in an open segment for which there is no valid ASSUME CS in effect. The assembler automatically generates an ASSUME statement such that the CS register is associated with the currently opened segment or with the group containing that segment if one exists.
| |
| | |
| ====ALP5601: Closed object output file "<file>"====
| |
| This message indicates that the object file processor has closed the referenced file.
| |
| | |
| ====ALP5602: Deleted object output file "<file>"====
| |
| This message indicates that the object file processor has deleted the referenced file.
| |
| | |
| ====ALP5603: Opened object output file "<file>"====
| |
| This message indicates that the object file processor has opened and is prepared to write to the referenced file.
| |
| | |
| ====ALP5701: Assembly terminated by .ABORT====
| |
| The .ABORT directive was used to terminate the assembler at the referenced location.
| |
| | |
| ====ALP5702: Address size assumed to be <USE16/USE32>====
| |
| This messages indicates that the referenced identifier was an external code label declared outside of segment boundaries, and was assumed to be defined in an external segment having the referenced address size.
| |
| | |
| ====ALP5703: Structure redefinition: "<identifier>"====
| |
| This message indicates that the current structure definition is replacing a previous definition of the same name.
| |
| | |
| ====ALP5704: Declaration sets <attribute> = <keyword>====
| |
| This message describes the attribute that is mismatched in a segment redeclaration.
| |
| | |
| ====ALP5705: <directive> outside of segment boundaries====
| |
| This message appears when an external declaration (COMM or EXTRN) appears outside of any enclosing segment.
| |
| | |
| If an external declaration is not enclosed in a segment definition that describes how the external symbol is ultimately defined, the assembler is deprived of segment attribute information; in particular, USE16 versus USE32. This could cause the assembler to generate incorrect object code, and may also cause linker errors.
| |
| Recovery: Place the external declaration within a segment definition that correctly reflects the segment definition in the external module where the symbol is defined.
| |
| | |
| ====ALP5801: Begin skipping tokens====
| |
| This message indicates that the results of a conditional assembly directive were evaluated to be false, and that the preprocessor has begun discarding tokens at the referenced location. No tokens will be returned to the parser until an appropriate ELSE or ENDIF condition is encountered.
| |
| | |
| ====ALP5802: Finished skipping tokens====
| |
| This message indicates that a false conditional block was ended with an appropriate ELSE or ENDIF construct. The preprocessor will begin returning tokens to the parser after the referenced location.
| |
| | |
| ====ALP5803: Closed source file "<file>"====
| |
| This message indicates that the preprocessor has closed the referenced file.
| |
| | |
| ====ALP5804: Opened source file "<file>"====
| |
| This message indicates that the preprocessor has opened and is prepared to read from the referenced file.
| |
| | |
| ====ALP5805: Macro redefinition: "<macro-name>"====
| |
| This message indicates that the current macro definition is replacing a previous definition of the same name.
| |
| | |
| ====ALP5806: Opened INCLUDE file "<file>"====
| |
| This message indicates that the preprocessor has opened and is prepared to read from the referenced include file.
| |
| | |
| ====ALP5807: Closed INCLUDE file "<file>"====
| |
| This message indicates that the preprocessor has closed the referenced include file.
| |
| | |
| ====ALP5901: Closed response file "<file>"====
| |
| This message indicates that the command line processor has closed the referenced file.
| |
| | |
| ====ALP5902: Opened response file "<file>"====
| |
| This message indicates that the command line processor has opened and is prepared to read from the referenced file.
| |
| | |
| ==Return Codes== | |
| When ALP completes, it passes a return code back to the program that invoked it. This return code shows whether ALP completed successfully or with an error. | |
| The return codes are: | |
| * 0 Normal program completion. | |
| * 1 User-specified file not found. | |
| * 2 Unexpected system error. | |
| * 3 Terminated by user or operating system. | |
| * 4 Syntax errors in input file. | |
| * 5 Command line usage error. | |
| * 6 Internal sanity check failure. | |
| * 7 Error accessing ALP messages file. | | * 7 Error accessing ALP messages file. |
|
| |
|
Line 7,080: |
Line 3,661: |
| ''October 1997'' | | ''October 1997'' |
|
| |
|
| The following paragraph does not apply to the United Kingdom or any country where such provisions are inconsistent with local law: | | The following paragraph does not apply to the United Kingdom or any country where such provisions are inconsistent with local law: |
|
| |
|
| INTERNATIONAL BUSINESS MACHINES CORPORATION PROVIDES THIS PUBLICATION "AS IS". WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Some states do not allow disclaimer of express or implied warranties in certain transactions, therefore, this statement may not apply to you. | | INTERNATIONAL BUSINESS MACHINES CORPORATION PROVIDES THIS PUBLICATION "AS IS". WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Some states do not allow disclaimer of express or implied warranties in certain transactions, therefore, this statement may not apply to you. |
|
| |
| This publication could include technical inaccuracies or typographical errors. Changes are periodically made to the information herein; these changes will be incorporated in new editions of the publication. IBM may make improvements and/or changes in the product(s) and/or the program(s) described in this publication at any time.
| |
|
| |
|
| It is possible that this publication may contain reference to, or information about, IBM products (machines and programs), programming, or services that are not announced in your country. Such references or information must not be construed to mean that IBM intends to announce such IBM products, programming, or services in your country. | | This publication could include technical inaccuracies or typographical errors. Changes are periodically made to the information herein; these changes will be incorporated in new editions of the publication. IBM may make improvements and/or changes in the product(s) and/or the program(s) described in this publication at any time. |
| | |
| | It is possible that this publication may contain reference to, or information about, IBM products (machines and programs), programming, or services that are not announced in your country. Such references or information must not be construed to mean that IBM intends to announce such IBM products, programming, or services in your country. |
|
| |
|
| Requests for technical information about IBM products should be made to your IBM authorized reseller or IBM marketing representative. | | Requests for technical information about IBM products should be made to your IBM authorized reseller or IBM marketing representative. |
| (C) Copyright International Business Machines Corporation 1995-1997. All rights reserved. Note to U.S. Government Users -- Documentation related to restricted rights -- Use, duplication or disclosure is subject to restrictions set forth in GSA ADP Schedule Contract with IBM Corp. | | (C) Copyright International Business Machines Corporation 1995-1997. All rights reserved. Note to U.S. Government Users -- Documentation related to restricted rights -- Use, duplication or disclosure is subject to restrictions set forth in GSA ADP Schedule Contract with IBM Corp. |
|
| |
|
| The [[#Processor Reference]] portion of this manual contains information reprinted with permission from Intel Corporation. | | The [[#Processor Reference]] portion of this manual contains information reprinted with permission from Intel Corporation. |
|
| |
|
| ===Disclaimers=== | | ===Disclaimers=== |
| References in this publication to IBM products, programs, or services do not imply that IBM intends to make these available in all countries in which IBM operates. Any reference to an IBM product, program or service is not intended to state or imply that only IBM's product, program, or service may be used. Any functionally equivalent product, program, or service that does not infringe any of IBM's intellectual property rights or other legally protectable rights may be used instead of the IBM product, program, or service. Evaluation and verification of operation in conjunction with other products, programs, or services, except those expressly designated by IBM, are the user's responsibility. | | References in this publication to IBM products, programs, or services do not imply that IBM intends to make these available in all countries in which IBM operates. Any reference to an IBM product, program or service is not intended to state or imply that only IBM's product, program, or service may be used. Any functionally equivalent product, program, or service that does not infringe any of IBM's intellectual property rights or other legally protectable rights may be used instead of the IBM product, program, or service. Evaluation and verification of operation in conjunction with other products, programs, or services, except those expressly designated by IBM, are the user's responsibility. |
|
| |
|
| IBM may have patents or pending patent applications covering subject matter in this document. The furnishing of this document does not give you any license to these patents. You can send license inquiries, in writing, to the IBM Director of Licensing, IBM Corporation, 500 Columbus Avenue, Thornwood NY 10594, U.S.A. | | IBM may have patents or pending patent applications covering subject matter in this document. The furnishing of this document does not give you any license to these patents. You can send license inquiries, in writing, to the IBM Director of Licensing, IBM Corporation, 500 Columbus Avenue, Thornwood NY 10594, U.S.A. |
|
| |
|
| ===Trademarks=== | | ===Trademarks=== |
Reprint Courtesy of International Business Machines Corporation, © International Business Machines Corporation
About this Reference
The following notations are used in this reference:
KEYWORD |
Commands and language keywords.
|
KEYWORD |
The default value for a command or language keyword when multiple values are possible but none are actually specified.
|
Phrase |
Typically indicates a hypertext link to a separate panel containing a description for that phrase.
|
Parameter |
Parameters whose actual names or values are to be supplied by the programmer.
|
Definition |
A term being defined for the first time, or special emphasis.
|
Subscript |
Subscripted text.
|
Superscript |
Superscripted text (other than ý).
|
<Name> |
A text value represented by "Name" is to be substituted in place of <Name> typically at assembler run-time.
|
Assembly Language Processor (ALP) Overview
The Assembly Language Processor (ALP) is an assembler that runs under OS/2 Warp. ALP is a functional replacement for the Microsoft Macro Assembler (MASM) and accepts:
- The full syntax of the Intel 80X86 architecture
- The full syntax of the MASM 5.10 high-level directive language
- A subset of the MASM 6.00 high-level directive language
ALP generates standard Object Module Format (OMF) files that can be linked to produce DOS or OS/2 executables. It can also generate symbolic debugging information compatible with the IBM family of source code debuggers. A MASM 5.10-compatible command line utility (MASM2ALP) is also provided to enable use of ALP with little or no change to existing build environments.
ALP also offers a rich set of command line options, as well as a comprehensive listing output cabability that is highly configurable, allowing a visual perspective not possible with other assemblers.
Language Elements
- Description
The following sections describe the elements you use to build an ALP program source file.
Character Set
All elements in an assembler language source file are built from collections of characters contained in the character set, which are defined as:
- The uppercase and lowercase letters of the English alphabet
- The decimal digits 0 through 9
- The following graphic characters:
~ ! " # $ % ^ & ' ( ) |
* + , - . / : ; = < > ?
[ \ ] _ { } @
- The space and horizontal tab characters
- The end of line character(s)
White Space
White space is a character or contiguous stream of characters that is ignored or removed from the input stream by the ALP preprocessor.
White space characters are any contiguous sequence of one or more space or tab characters not enclosed in single or double quotes. White space characters are significant only in that they serve to separate language tokens from one another; they are removed from the input stream by the scanner.
- Syntax
Token:
- Reserved-Word
- Identifier
- Literal
- Punctuator
Reserved Words
- Description
This section describes all of the assembler reserved words.
- Syntax
Reserved-Word:
- Preprocessor-Directive
- Assembler-Directive
- Processor-Mnemonic
- Processor-Register
- Scalar-TypeName
- Distance-TypeName
- Language-Name
- Anonymous-Label-Alias
- Location-Counter-Alias
- Indeterminate-Value-Alias
- Directive-Keyword
- Operator-Keyword
Preprocessor Directives
- Description
Preprocessor Directives are symbolic names that describe the various assembly-time text processing instructions interpreted by the preprocessor phase of the assembler.
- Syntax
Preprocessor-Directive: one of
CATSTR COMMENT ELSE ELSEIF
ELSEIF1 ELSEIF2 ELSEIFB ELSEIFDEF
ELSEIFDIF ELSEIFDIFI ELSEIFE ELSEIFIDN
ELSEIFIDNI ELSEIFNB ELSEIFNDEF ENDIF
ENDM EQU EXITM FOR
FORC IF IF1 IF2
IFB IFDEF IFDIF IFDIFI
IFE IFIDN IFIDNI IFNB
IFNDEF INCLUDE INSTR IRP
IRPC LOCAL MACRO PURGE
REPEAT REPT SIZESTR SUBSTR
Assembler Directives
- Description
Assembler Directives are symbolic names that describe the various assembly-time instructions interpreted by the assembler itself.
- Syntax
Assembler-Directive: one of
.186 .286 .286C .286P
.287 .386 .386C .386P
.387 .486 .486C .486P
.586 .586P .686 .686P
.8086 .8087 ALIGN .ALPHA
ASSUME %BIN .CODE COMM
.CONST .CREF .DATA .DATA?
DB DD DF DOSSEG
.DOSSEG DQ DT DW
ECHO END ENDP ENDS
EQU .ERR .ERR1 .ERR2
.ERRB .ERRDEF .ERRDIF .ERRDIFI
.ERRE .ERRIDN .ERRIDNI .ERRNB
.ERRNDEF .ERRNZ EVEN EXTERN
EXTERNDEF EXTRN .FARDATA .FARDATA?
GROUP INCLUDELIB LABEL .LALL
.LFCOND .LIST .LISTALL .LISTIF
.LISTMACRO .LISTMACROALL LOCAL .MMX
.MODEL NAME .NOCREF .NOLIST
.NOLISTIF .NOLISTMACRO .NOMMX OPTION
ORG %OUT PAGE PROC
PUBLIC .RADIX RECORD .SALL
SEGMENT .SEQ .SFCOND .STACK
STRUC STRUCT SUBTITLE SUBTTL
.TFCOND TITLE TYPEDEF UNION
.XALL .XCREF .XLIST
Processor Mnemonics
- Description
Processor Mnemonics are symbolic names given to the various instructions in the processor instruction set.
- Syntax
Processor-Mnemonic: one of
AAA AAD AAM AAS ADC
ADD AND ARPL BOUND BSF
BSR BSWAP BT BTC BTR
BTS CALL CBW CDQ CLC
CLD CLI CLTS CMC CMOVA
CMOVAE CMOVB CMOVBE CMOVC CMOVE
CMOVG CMOVGE CMOVL CMOVLE CMOVNA
CMOVNAE CMOVNB CMOVNBE CMOVNC CMOVNE
CMOVNG CMOVNGE CMOVNL CMOVNLE CMOVNO
CMOVNP CMOVNS CMOVNZ CMOVO CMOVP
CMOVPE CMOVPO CMOVS CMOVZ CMP
CMPS CMPSB CMPSD CMPSW CMPXCHG
CMPXCHG8B CPUID CWD CWDE DAA
DAS DEC DIV EMMS ENTER
ESC F2XM1 FABS FADD FADDP
FBLD FBSTP FCHS FCLEX FCMOVB
FCMOVBE FCMOVE FCMOVNB FCMOVNBE FCMOVNE
FCMOVNU FCMOVU FCOM FCOMI FCOMIP
FCOMP FCOMPP FCOS FDECSTP FDISI
FDIV FDIVP FDIVR FDIVRP FENI
FFREE FIADD FICOM FICOMP FIDIV
FIDIVR FILD FIMUL FINCSTP FINIT
FIST FISTP FISUB FISUBR FLD
FLD1 FLDCW FLDENV FLDENVD FLDENVW
FLDL2E FLDL2T FLDLG2 FLDLN2 FLDPI
FLDZ FMUL FMULP FNCLEX FNDISI
FNENI FNINIT FNOP FNSAVE FNSAVED
FNSAVEW FNSTCW FNSTENV FNSTENVD FNSTENVW
FNSTSW FPATAN FPREM FPREM1 FPTAN
FRNDINT FRSTOR FRSTORD FRSTORW FSAVE
FSAVED FSAVEW FSCALE FSETPM FSIN
FSINCOS FSQRT FST FSTCW FSTENV
FSTENVD FSTENVW FSTP FSTSW FSUB
FSUBP FSUBR FSUBRP FTST FUCOM
FUCOMI FUCOMIP FUCOMP FUCOMPP FWAIT
FXAM FXCH FXTRACT FYL2X FYL2XP1
HLT IDIV IMUL IN INC
INS INSB INSD INSW INT
INTO INVD INVLPG IRET IRETD
IRETDF IRETF JA JAE JB
JBE JC JCXZ JE JECXZ
JG JGE JL JLE JMP
JNA JNAE JNB JNBE JNC
JNE JNG JNGE JNL JNLE
JNO JNP JNS JNZ JO
JP JPE JPO JS JZ
LAHF LAR LDS LEA LEAVE
LES LFS LGDT LGS LIDT
LLDT LMSW LOCK LODS LODSB
LODSD LODSW LOOP LOOPD LOOPE
LOOPED LOOPEW LOOPNE LOOPNED LOOPNEW
LOOPNZ LOOPNZD LOOPNZW LOOPW LOOPZ
LOOPZD LOOPZW LSL LSS LTR
MOV MOVD MOVQ MOVS MOVSB
MOVSD MOVSW MOVSX MOVZX MUL
NEG NOP NOT OR OUT
OUTS OUTSB OUTSD OUTSW PACKSSDW
PACKSSWB PACKUSWB PADDB PADDD PADDSB
PADDSW PADDUSB PADDUSW PADDW PAND
PANDN PCMPEQB PCMPEQD PCMPEQW PCMPGTB
PCMPGTD PCMPGTW PMADDWD PMULHW PMULLW
POP POPA POPAD POPD POPF
POPFD POPW POR PSLLD PSLLQ
PSLLW PSRAD PSRAW PSRLD PSRLQ
PSRLW PSUBB PSUBD PSUBSB PSUBSW
PSUBUSB PSUBUSW PSUBW PUNPCKHBW PUNPCKHDQ
PUNPCKHWD PUNPCKLBW PUNPCKLDQ PUNPCKLWD PUSH
PUSHA PUSHAD PUSHD PUSHF PUSHFD
PUSHW PXOR RCL RCR RDMSR
RDPMC RDTSC REP REPE REPNE
REPNZ REPZ RET RETF RETN
ROL ROR RSM SAHF SAL
SAR SBB SCAS SCASB SCASD
SCASW SETA SETAE SETB SETBE
SETC SETE SETG SETGE SETL
SETLE SETNA SETNAE SETNB SETNBE
SETNC SETNE SETNG SETNGE SETNL
SETNLE SETNO SETNP SETNS SETNZ
SETO SETP SETPE SETPO SETS
SETZ SGDT SHL SHLD SHR
SHRD SIDT SLDT SMSW STC
STD STI STOS STOSB STOSD
STOSW STR SUB TEST UC2
VERR VERW WAIT WBINVD WRMSR
XADD XCHG XLAT XLATB XOR
Processor Registers
- Description
Processor Registers are the symbolic names assigned to the various internal processor registers. They are normally used as operands to processor instructions.
- Syntax
Processor-Register:
- General-Purpose-Register
- Segment-Register
- Control-Register
- Debug-Register
- Test-Register
- MMX-Register
- Floating-Point-Register
General-Purpose-Register:
- 8-Bit-Register
- 16-Bit-Register
- 32-Bit-Register
8-Bit-Register: one of
- AL AH BL BH CL CH DL DH
16-Bit-Register: one of
- AX BX CX DX DI SI BP SP
32-Bit-Register: one of
- EAX EBX ECX EDX EDI ESI EBP ESP
Segment-Register: one of
- CS DS ES FS GS SS
Control-Register: one of
- CR0 CR2 CR3 CR4
Debug-Register: one of
- DR0 DR1 DR2 DR3 DR4 DR5 DR6 DR7
Test-Register: one of
- TR3 TR4 TR5 TR6 TR7
MMX-Register: one of
- MM0 MM1 MM2 MM3 MM4 MM5 MM6 MM7
Floating-Point-Register:
ST
Scalar Type Names
- Description
Scalar Type Names are the symbolic names given to the integral data types. These are the fundamental types of data upon which the processor can directly operate.
- Syntax
Scalar-TypeName:
- BYTE
- SBYTE
- WORD
- SWORD
- DWORD
- SDWORD
- REAL4
- FWORD
- QWORD
- REAL8
- TBYTE
- REAL10
Distance Type Names
- Description
Distance Type Names are the symbolic names given to the integral types of pointers directly supported by the processor. Their names reflect a fundamental property of the Intel processor architecture known as distance. The type of pointer is defined by the distance required to reach the information to which it points.
- Syntax
Distance-TypeName:
- NEAR
- NEAR16
- NEAR32
- FAR
- FAR16
- FAR32
Language Names
- Description
Language Names refer to the various high level programming languages (or more specifically, the calling conventions used by such languages) with which the assembler has the ability to interface.
- Syntax
Language-Name:
- C
- SYSCALL
- STDCALL
- PASCAL
- FORTRAN
- BASIC
- OPTLINK
Anonymous Label Aliases
- Description
The Anonymous Label Aliases are reserved symbolic names that return a context-sensitive value when referenced in expressions.
The reserved name @B (backward reference) returns the internally generated name representing the nearest @@: code label appearing before the current location in the input stream.
The reserved name @F (forward reference) returns the internally generated name representing the nearest @@: code label appearing after the current location in the input stream.
- Syntax
Anonymous-Label-Alias:
- @B
- @F
Location Counter Alias
- Description
The Location Counter Alias is a reserved name used in expressions to return the offset within the current segment or structure being assembled.
- Syntax
Location-Counter-Alias:
- $
Indeterminate Value Alias
- Description
The Indeterminate Value Alias is a reserved name used in expressions to represent an uninitialized value.
- Syntax
Indeterminate-Value-Alias:
- ?
Directive Keywords
- Description
Directive Keywords are symbolic names recognized and used in the body of various assembler directives.
- Syntax
Directive-Keyword:
ABS AT BASIC C
CASEMAP CODE COMMON DOTNAME
EMULATOR EPILOGUE ERROR EXPORT
EXPR16 EXPR32 FARSTACK FLAT
FORTRAN HUGE LANGUAGE LARGE
LJMP MEDIUM NEARSTACK NODOTNAME
NOEMULATOR NOKEYWORD NOLANGUAGE NOLJMP
NONE NOOLDMACROS NOOLDSTRUCTS NOREADONLY
NOSCOPED NOSIGNEXTEND NOTHING NOTPUBLIC
OLDMACROS OLDSTRUCTS OPTLINK OS_DOS
OS_OS2 PAGE PARA PASCAL
PRIVATE PROC PROLOGUE PUBLIC
READONLY SCOPED SEGMENT SIGNEXTEND
SMALL STACK STDCALL SYSCALL
TINY USE16 USE32 USES
Operator Keywords
- Description
Operator Keywords are symbolic names used in expressions to denote an operation to be performed on one or more operands.
- Syntax
Operator-Keyword:
AND DUP EQ GE
GT HIGH HIGHWORD LE
LENGTH LENGTHOF LOW LOWWORD
LT MASK MOD NE
NOT OFFSET OPATTR OR
PTR SEG SHL SHORT
SHR SIZE SIZEOF THIS
.TYPE TYPE WIDTH XOR
Identifiers
- Description
This section describes the syntax for identifiers and the various types of information they can be made to represent.
- Syntax
Identifier:
- Normal-Identifier
- Dot-Identifier
- Normal-Identifier
- NonDigit
- Normal-Identifier Identifer-Character
Dot-Identifier
. Normal-Identifier
Identifier-Character
NonDigit
Digit
NonDigit: one of
_ $ @ ?
a b c d e f g h i j k l m
n o p q r s t u v w x y z
A B C D E F G H I J K L M
N O P Q R S T U V W X Y Z
Digit: one of
0 1 2 3 4 5 6 7 8 9
Identifier Types
- Description
This section describes the various types of identifiers that the assembler will create and manipulate.
- Definition
Identifier-Type:
- EquateName
- FieldName
- GroupName
- LabelName
- MacroName
- SegmentName
- UserDefined-TypeName
Equate Name
- Definition
EquateName:
- Numeric-EquateName
- Text-EquateName
- Description
An EquateName is a symbolic identifier that is associated with an expression or a body of text. The assembler substitutes the value of the EquateName at the point of reference.
Numeric Equate Name
An identifier becomes a Numeric-EquateName when it is defined in a EQU or = directive. Procedure parameter names and local variable names are also created as Numeric-EquateNames, but are visible only from within the procedure where they are defined. All other Numeric-EquateNames are globally-scoped identifiers visible across the entire module.
A Numeric-EquateName may only be referenced from within expressions, as its replacement value is itself an expression.
Text Equate Name
A Text-EquateName is a globally-scoped identifier created during the processing of a EQU preprocessor directive. A Text-EquateName is associated with a body of text whose content may not span across line breaks. In certain contexts the assembler replaces the Text-EquateName with the text that it represents and recursively evaluates the result.
Field Name
- Definition
FieldName:
- Record-FieldName
- Structure-FieldName
- Union-FieldName
- Description
An identifier becomes a FieldName when it is defined within a RECORD, STRUCT, or UNION directive.
Record Field Name
A Record-FieldName is a globally-scoped identifier created during the processing of a RECORD directive. It is a special variation of a Numeric-EquateName and can be used in the same contexts.
Structure Field Name
An identifier becomes a Structure-FieldName when it is defined in a STRUCT directive. If the assembler is operating in M510 mode, or if the OPTION OLDSTRUCTS directive has been specified, then a Structure-FieldName is a globally-scoped identifier treated as a special variation of a Numeric-EquateName and can be used in the same contexts. Otherwise, a Structure-FieldName is private to the defining structure and is only accessible in expressions through use of the Structure/Union Field Selection (. Operator).
Union Field Name
An identifier becomes a Union-FieldName when it is defined in a UNION directive. A Union-FieldName is private to the defining union and is only accessible in expressions through use of the Structure/Union Field Selection (. Operator).
Group Name
A GroupName is a globally-scoped identifier created during the processing of a GROUP directive. It is referenced from within expressions.
Label Name
- Definition
LabelName:
- Code-LabelName
- Data-LabelName
- Description
A LabelName is globally-scoped identifier that is associated with a program address at application run-time. It has an explicit or inherited Type-Declaration, and an optional Language-Attribute. These attributes are described in the following sections.
- Type Declaration
The type declaration associated with a label name depends on how the label was defined. See the Code-LabelName and Data-LabelName sections for descriptions on how this attribute is assigned.
- Language Attribute
A LabelName can have an assigned Language-Attribute, set either implicitly through the use of a Language-Name keyword in the body of a .MODEL or OPTION directive, or explicitly through the use of an overriding Language-Name keyword in the body of a EXTERN/EXTRN, EXTERNDEF, PROC, or PUBLIC directive. The Language-Attribute determines the exact spelling of the LabelName identifier when it is written to the object file. According to the Language-Attribute, identifier spellings are modified from their appearance in the assembly language source module as follow:
LANGUAGE ATTRIBUTE |
IDENTIFIER SPELLING
|
OPTLINK, SYSCALL |
No modifications are made to the identifier when written to the object file.
|
C, STDCALL |
A leading underscore character is appended to the front of the name.
|
BASIC, FORTRAN, PASCAL |
All characters in the identifier are converted to uppercase.
|
Code Label Name
- Definition
Code-LabelName:
- Target-LabelName
- Procedure-LabelName
- Description
A Code-LabelName is an identifier that is associated with an executable code address at application run-time. There are two types of Code-LabelNames: Target-LabelNames and Procedure-LabelNames.
Target Label Name
An identifier becomes a Target-LabelName when it is defined with a :, ::, or LABEL directive.
If a Target-LabelName created with a single colon (:) is defined within the body of a procedure, then the name is visible only from within that procedure unless operating in M510 mode (and no .MODEL directive with a Language-Name has been specified), or unless the OPTION NOSCOPED directive has been specified.
A Target-LabelName defined outside the body of a procedure is visible to the entire module, and may also be given PUBLIC visibility.
Procedure Label Name
An identifier becomes a Procedure-LabelName when it is defined in a PROC directive.
Data Label Name
A Data-LabelName is an identifier that is the address of a program variable at application run-time. An identifier becomes a Data-LabelName when it is named in a data allocation statement, or when a scalar, aggregate, or vector type is associated with the identifier named in a LABEL, EXTERN/ EXTRN, EXTERNDEF, or COMM directive.
Macro Name
A MacroName is a globally-scoped identifier created during the processing of a MACRO directive. It is associated with a multi-line body of text. A MacroName may only be used in contexts where a normal assembler directive is expected.
Macro Parameter Name
An identifier becomes a Macro-ParameterName when it is named as a parameter to a macro in a MACRO directive. It is associated with a body of text whose content may not span across line breaks. It is only recognized and acted upon from within the body of a macro expansion.
Segment Name
A SegmentName is a globally-scoped identifier created during the processing of a SEGMENT directive. It may be referenced from within expressions or in the body of a GROUP directive.
User-Defined Type Name
- Definition
UserDefined-TypeName:
- Record-TypeName
- Structure-TypeName
- Typedef-TypeName
- Union-TypeName
- Description
An identifier becomes a UserDefined-TypeName when it is defined within a RECORD, STRUCT, TYPEDEF, or UNION directive.
Record Type Name
A Record-TypeName is a globally-scoped identifier created during the processing of a RECORD directive. It is recognized from within Expressions, Type-Declarations, or as a pseudo-directive in a data allocation statement.
Structure Type Name
A Structure-TypeName is a globally-scoped identifier created during the processing of a STRUCT directive. It is recognized from within Expressions, Type-Declarations, or as a pseudo-directive in a data allocation statement.
Typedef Type Name
A Typedef-TypeName is a globally-scoped identifier created during the processing of a TYPEDEF directive. It is recognized from within Expressions, Type-Declarations, or as a pseudo-directive in a data allocation statement.
Union Type Name
A Union-TypeName is a globally-scoped identifier created during the processing of a UNION directive. It is recognized from within Expressions, Type-Declarations, or as a pseudo-directive in a data allocation statement.
Predefined Identifiers
The following sections describe the predefined identifiers created by the assembler. When a case-sensitive assembly is being performed, the predefined identifiers must be spelled exactly as they appear in the following descriptions with respect to uppercase and lowercase characters.
Segment Information
The following sections describe the predefined identifiers created by the assembler in support of segment manipulation.
@code
The @code identifier is a Text-EquateName created by the assembler when a .MODEL directive is encountered, at which time the assembler performs an automatic ASSUME CS:@code operation. The @code symbol is not defined if a .MODEL directive has not been issued.
Under MASM 5.10 emulation, the @code symbol is set to the name of the implicitly-defined default code segment (the segment opened when a .CODE directive is used) and its value is never changed. In other modes, the @code symbol is updated to reflect whatever segment is opened by using .CODE, whether defined implicitly or as an explicit parameter to the .CODE directive.
The value assigned to the @code symbol when the default code segment is opened is determined by the memory model as follows:
Memory Model Value for @code
- TINY DGROUP
- SMALL _TEXT
- MEDIUM module _TEXT
- COMPACT_TEXT
- LARGE module _TEXT
- HUGE module _TEXT
- FLAT CODE32
The module entry is replaced with base file name of the top-level module being assembled.
@CodeSize
The @CodeSize identifier is a Numeric-EquateName created by the assembler when a .MODEL directive is encountered. @CodeSize indicates whether code segments created by the .CODE directive are named such that the linker will combine them into a single (NEAR) segment or into multiple (FAR) segments. The @CodeSize symbol is set to 0 (NEAR) for the TINY, SMALL, COMPACT, and FLAT memory models, and to 1 (FAR) for the MEDIUM, LARGE, and HUGE memory models. The @CodeSize symbol is not defined if a .MODEL directive has not been issued.
@CurSeg
The @CurSeg identifier is a Text-EquateName defined by the assembler to hold the name of the currently opened segment. If no segment is currently open, @CurSeg will expand into an empty string.
@data
The @data identifier is a Text-EquateName created by the assembler when a .MODEL directive is encountered. It expands to the group name shared by all of the near data segments. If a .MODEL FLAT has been issued, the @data identifier expands to FLAT. For all other memory models, it expands to DGROUP.
@DataSize
The @DataSize identifier is a Numeric-EquateName created by the assembler when a .MODEL directive is encountered, and represents the default data distance. Depending on the currently selected memory model, the @DataSize identifier is set to the following values:
- TINY 0
- SMALL 0
- COMPACT 1
- MEDIUM 1
- LARGE 1
- HUGE 2
- FLAT 0
@Model
The @Model identifier is a Numeric-EquateName created by the assembler when a .MODEL directive is encountered, and is set to a unique value for each memory model. The values are as follows:
- TINY 1
- SMALL 2
- COMPACT 3
- MEDIUM 4
- LARGE 5
- HUGE 6
- FLAT 7
@WordSize
The @WordSize identifier is a Numeric-EquateName that reflects the address size attribute of the current segment. It is set to 2 for a USE16 segment, and 4 for a USE32 segment. If no segment is currently open, it reflects the default address size as determined by the currently selected processor.
Version Information
These identifiers offer methods of testing the various operating modes of the assembler to determine what features are activated or disabled, or how the assembler will behave under various conditions.
@Alp
The @Alp identifier is a Text-EquateName that can be tested to determine if ALP is assembling the source file (versus some other assembler). It is always set to the string 100.
@AlpMajor
The @AlpMajor identifier is a Text-EquateName that reflects the major portion of the three-part assembler version number. It is padded on the right with zeros to allow major version number comparisions independant of the minor version and revisions numbers. See @AlpVersion for more information.
This identifier is only defined in ALP mode.
@AlpMinor
The @AlpMinor identifier is a Text-EquateName that reflects the minor portion of the three-part assembler version number. It is padded on the right with zeros to allow minor version number comparisions independant of the major version and revisions numbers. See @AlpVersion for more information.
This identifier is only defined in ALP mode.
@AlpRevision
The @AlpRevision identifier is a Text-EquateName that reflects the revision portion of the three-part assembler version number. It allows revision number comparisions independant of the major and minor version numbers. See @AlpVersion for more information.
This identifier is only defined in ALP mode.
@AlpVersion
The @AlpVersion identifier is a Text-EquateName that reflects the full three-part assembler version number. This is an encoding of the version number printed in the program banner when the assembler is invoked. This number and its requisite parts may be tested to determine the presence or absence of features provided by the assembler.
The assembler version number consists of three parts:
- The major version number (one digit)
- The minor version number (two digits)
- The revision number (three digits)
In the assembler banner, the numbers are separated by the period (.) character; the period is removed from the text defined by the predefined identifiers.
For example, if the major version number is 1, the minor version number is 2, and the revision number is 3, then the full version number is printed in the assembler banner as 1.02.003, and the various predefined version identifers would be set as follows:
@AlpVersion 102003
@AlpMajor 100000
@AlpMinor 2000
@AlpRevision 003
This identifier is only defined in ALP mode.
@Cpu
The @Cpu identifier is a Numeric-EquateName that reflects the currently selected processor for which ALP is assembling instructions. This value is affected by issuing a Processor-Control-Directive, and is a bit map that indicates the currently active processor instruction set(s).
B |
A |
9 |
8 |
7 |
6 |
5 |
4 |
3 |
2 |
1 |
0 |
BIT SET IF ASSEMBLING FOR
|
|
|
|
|
|
|
|
|
|
|
|
1 |
8086/8088
|
|
|
|
|
|
|
|
|
|
|
1 |
|
80186
|
|
|
|
|
|
|
|
|
|
1 |
|
|
80286
|
|
|
|
|
|
|
|
|
1 |
|
|
|
80386
|
|
|
|
|
|
|
|
1 |
|
|
|
|
80486
|
|
|
|
|
|
|
1 |
|
|
|
|
|
80586 (Pentium)
|
|
|
|
|
|
1 |
|
|
|
|
|
|
80686 (Pentium Pro)
|
|
|
|
|
1 |
|
|
|
|
|
|
|
Privileged mode
|
|
|
|
1 |
|
|
|
|
|
|
|
|
8087
|
|
|
1 |
|
|
|
|
|
|
|
|
|
MMX Extensions
|
|
1 |
|
|
|
|
|
|
|
|
|
|
80287
|
1 |
|
|
|
|
|
|
|
|
|
|
|
80387
|
@Version
The @Version identifier is a Text-EquateName that reflects the MASM-compatible version number. The current emulation mode of the assembler affects the value of this symbol as follows:
- M510 510
- M600 600
- ALP 4294967295 (the highest possible value for an unsigned 32-bit integer)
Date and Time Information
These identifiers allow the programmer to query the system date or time during the assembly. Each time they are referenced, a new system request for the current date and time is made and the values held in the identifiers are refreshed.
@Date
The @Date identifier is a Text-EquateName that is set to the current system date. If the current operating mode is M600, the date is returned in the MM/DD/YY format. In native ALP mode, the date is returned in the MM/DD/YYYY format.
The @Date identifier is not available in M510 mode.
@Time
The @Time identifier is a Text-EquateName that is set to the current system time in 24-hour HH:MM:SS format.
The @Time identifier is not available in M510 mode.
File Information
These identifiers return information about the file(s) being assembled.
@FileName
The @FileName identifier is a Text-EquateName that is set to the base name of the main file being assembled (as it appears on the command line).
@Line
The @Line identifier is a Numeric-EquateName that is set to the current source line number in the file currently being assembled.
The @Line identifier is not available in M510 mode.
Literals
- Description
Literals are the notational method whereby numeric values or strings of character data are represented in the source stream. Literals are also commonly referred to as constants (especially in the context of high level languages) because they typically represent objects whose values do not change throughout the life of the assembly or compilation. However, literals should not be confused with run-time "constants"; ("read-only"; data items allocated by the programmer); they are assembly-time tokens used by the assembler to represent numeric values or character strings.
- Syntax
Literal:
- Floating-Point-Literal
- Integer-Literal
- String-Literal
Integer Literals
- Description
An integer literal represents a fixed-point numeric value. An integer literal must begin with one of the numeric digits 0 - 9, and may be optionally terminated with a suffix character called a radix specifier. The radix specifier tells the assembler whether the literal is to be interpreted as a base 2 (binary), 8 (octal), 10 (decimal), or 16 ( hexadecimal) number. If the literal is not suffixed with a radix specifier , the assembler uses the value of the current radix to determine the base of the number. The default radix is 10 (decimal), but the .RADIX directive can be used to specify an alternate radix.
- Syntax
Integer-Literal:
- Binary-Integer-Literal
- Octal-Integer-Literal
- Decimal-Integer-Literal
- Hexadecimal-Integer-Literal
Binary Integer Literals
- Syntax
Binary-Integer-Literal:
- Unqualified-Binary-Integer-Literal
- Qualified-Binary-Integer-Literal
Unqualified-Binary-Integer-Literal:
- Binary-Digit
- Binary-Integer-Literal Binary-Digit
Qualified-Binary-Integer-Literal:
- Unqualified-Binary-Integer-Literal Binary-Radix
Binary-Digit:
- 0
- 1
Binary-Radix:
- b
- B
- y
- Y
- Description
A base-2 number containing either of the digits 0 and 1.
- Examples
The following are examples of unqualified binary integer literals:
10101
0
000001
1111000010101010
The following are examples of qualified binary integer literals:
00001111b
1111Y
00y
1111000010101010B
Octal Integer Literals
- Syntax
Octal-Integer-Literal:
- Unqualified-Octal-Integer-Literal
- Qualified-Octal-Integer-Literal
Unqualified-Octal-Integer-Literal:
- Octal-Digit
- Octal-Integer-Literal Octal-Digit
Qualified-Octal-Integer-Literal:
- Unqualified-Octal-Integer-Literal Octal-Radix
Octal-Digit: one of:
0 1 2 3 4 5 6 7
Octal-Radix:
- o
- O
- q
- Q
- Description
A base-8 number containing any of the digits 0 through 7.
- Examples
The following are examples of unqualified octal integer literals:
01234567
27
765
The following are examples of qualified octal integer literals:
27q
013o
567O
01234567Q
Decimal Integer Literals
- Syntax
Decimal-Integer-Literal:
- Unqualified-Decimal-Integer-Literal
- Qualified-Decimal-Integer-Literal
Unqualified-Decimal-Integer-Literal:
- Decimal-Digit
- Decimal-Integer-Literal Decimal-Digit
Qualified-Decimal-Integer-Literal:
- Unqualified-Decimal-Integer-Literal Decimal-Radix
Decimal-Digit: one of:
0 1 2 3 4 5 6 7 8 9
Decimal-Radix:
- d
- D
- t
- T
- Description
A base-10 number containing any of the digits 0 through 9.
- Examples
The following are examples of unqualified decimal integer literals:
0123456789
19
090
The following are examples of qualified decimal integer literals:
01d
89t
4567D
0123456789T
Hexadecimal Integer Literals
- Syntax
Hexadecimal-Integer-Literal:
- Unqualified-Hexadecimal-Integer-Literal
- Qualified-Hexadecimal-Integer-Literal
Unqualified-Hexadecimal-Integer-Literal:
- Decimal-Digit
- Hexadecimal-Integer-Literal Decimal-Digit
- Hexadecimal-Integer-Literal Hexadecimal-Digit
Qualified-Hexadecimal-Integer-Literal:
- Unqualified-Hexadecimal-Integer-Literal Hexadecimal-Radix
Decimal-Digit: one of:
0 1 2 3 4 5 6 7 8 9
Hexadecimal-Digit: one of:
a b c d e f
A B C D E F
Hexadecimal-Radix:
- h
- H
- Description
A base-16 number using any combination of the digits 0 through 9 and the lowercase letters a through f or the uppercase letters A through F. The lowercase and uppercase representations of any given hexadecimal letter are equivalent.
- Constraints
A hexadecimal integer literal may not begin with any of the alphabetic hexadecimal characters or it will be interpreted as an identifier; such numbers must be prefixed with the 0 digit.
- Examples
The following are examples of unqualified hexadecimal integer literals:
01BD
9A
0AB
The following are examples of qualified hexadecimal integer literals:
1234ABCDh
01DH
0bh
1111FFFFH
Floating-Point Literals
- Description
A floating-point literal is a notation for representing real numbers. The assembler provides both decimal and hexadecimal floating-point notations for representing real numbers.
- Syntax
Floating-Point-Literal:
- Decimal-Floating-Point-Literal
- Hexadecimal-Floating-Point-Literal
Decimal Floating-Point Literals
- Syntax
Decimal-Floating-Point-Literal:
Significand-Part
Significand-Part Exponent-Part
Significand-Part:
Digit-Sequence.Digit-Sequence
Digit-Sequence.
Exponent-Part:
E-Character Digit-Sequence
E-Character Sign Digit-Sequence
E-Character:
e
E
Sign:
-
+
Digit-Sequence:
Digit
Digit-Sequence Digit
Digit:one of:
0 1 2 3 4 5 6 7 8 9
- Description
A decimal floating-point literal has a significand part that may be followed by an exponent part. The significand part consists of a digit sequence representing the whole-number part, followed by a period (.), followed by a digit sequence representing the fraction part. The exponent part consists of an introductory character (eor E), followed by an optional sign character (+or -), followed by a digit sequence representing the exponent.
- Constraints
The introductory Digit-Sequence in the Significand-Part must be specified ( the literal cannot begin with a ".").
- Examples
25.23
2.523E1
2523.0E-2
Hexadecimal Floating-Point Literals
- Syntax
Hexadecimal-Floating-Point-Literal:
Hexadecimal-Literal Float-Radix
Hexadecimal-Literal:
Decimal-Digit
Hexadecimal-Literal Decimal-Digit
Hexadecimal-Literal Hexadecimal-Digit
Decimal-Digit:one of:
0 1 2 3 4 5 6 7 8 9
Hexadecimal-Digit:one of:
a b c d e f
A B C D E F
Float-Radix:
r
R
- Description
A hexadecimal floating-point literal provides a means of initializing floating point values using a notation more closely tied to the internal machine representation than that of the Decimal-Floating-Point-Literal. Such literals are coded in a fashion similar to that of a normal Hexadecimal-Integer-Literal, but a different radix suffix is used to inform the assembler that the value is to be used in the allocation of real numbers rather than integers.
- Constraints
A hexadecimal floating-point literal may not begin with any of the alphabetic hexadecimal characters or it will be interpreted as an identifier; such numbers must be prefixed with the 0 digit.
The literal must specify the correct number of hexadecimal digits according to the size of the real-number data-type to which it will be assigned. For REAL4, REAL8, and REAL10 variables, the respective number of digits in the literal must be 8, 16, and 20. For literals encoded with a leading zero, the respective number of digits must be 9, 17, and 21.
- Examples
3F800000r
String Literals
- Syntax
String-Literal:
D-String
S-String
D-String:
D-Quote D-Quote
D-Quote D-Char-Sequence D-Quote
S-String:
S-Quote S-Quote
S-Quote S-Char-Sequence S-Quote
D-Char-Sequence:
any printable character except D-Quote
D-Quote D-Quote
S-Char-Sequence:
any printable character except S-Quote
S-Quote S-Quote
D-Quote:
"
S-Quote:
- Description
A string literal contains a sequence of zero or more characters enclosed in quotation mark symbols. Either a single (') or double (") quotation mark symbol may be used as the quote character that opens and closes the string literal. If a single quotation mark symbol is used as the quote character, then double quotation mark symbols may appear as data characters within the string literal, and vice versa. If the quote character must also appear as a character within the string literal, use two adjacent quote characters; this will allow a single occurrence of the quote character to be inserted into the string literal.
A quote character must be used to terminate the string literal before the end of the line is reached, otherwise an error message is issued and the literal is terminated by the end of line character. A string literal may span multiple lines only if a backslash (\) appears as the last non- whitespace character on the line, in which case the backslash, all surrounding whitespace characters, and the end of line character are deleted and the literal is continued with the first character on the next line.
- Examples
'Hello, world'
"That's the way it is"
'Unless its not'
"SuperStringCon \
catenated"
Punctuators
- Description
Punctuators are used as operators and separator characters.
- Syntax
Punctuator:one of
[ ] ( ) { } * , : = ; %
Declarations
A Type Declaration is a language construct that specifies the characteristics of code and data objects used in a program.
Type Declarations
- Description
A Type-Declaration is a common construct used in various assembler directives to establish type attribute information for a program object. A Type-Declaration is needed to determine the data type of a variable or labeled address. The TYPEDEF directive offers a method of assigning a name to a Type-Declaration.
- Syntax
Type-Declaration:
- TypeName
- TypeName Array-Spec
- Pointer-Spec
- Pointer-Spec TypeName
- Pointer-Spec TypeName Array-Spec
Pointer-Spec:
- PTR
- Distance-TypeName PTR
- Pointer-Spec Array-Spec
Array-Spec:
- [ Expression ]
- Array-Spec [ Expression ]
TypeName:
- Distance-TypeName
- Scalar-TypeName
- UserDefined-TypeName
- Examples
The TYPEDEF directive is used to illustrate the type declaration syntax:
CHAR typedef byte ; Alias of intrinsic TypeName
PBYTE typedef ptr byte ; Pointer to intrinsic TypeName
PCHAR typedef ptr CHAR ; Pointer to TypeDef-TypeName
PPCHAR typedef ptr PCHAR ; Pointer to a pointer to a CHAR
PPBYTE typedef ptr ptr byte ; Similar to PPCHAR
PVOID typedef ptr ; Pointer to nothing (pointer to code)
PCODE typedef ptr PROC ; Similar to PVOID
PFCODE typedef far ptr far ; Far pointer to far code address
; vector declarations
ACHAR typedef CHAR[16] ; Array of 16 characters
AAWORD typedef word[2][2] ; multi-dimensional array
APBYTE typedef ptr[8] byte ; Array of 8 pointers to byte
APACHAR typedef ptr[4] ACHAR ; Array of 4 ptrs to arrays of 16 chars
SIZES_T struct ; define an intrinsic structure type
little byte ?
Medium word ?
BIG dword ?
SIZES_T ends
SIZES typedef SIZES_T ; alias for intrinsic structure type
PSIZES typedef ptr SIZES_T ; and a type to point to it
PFORWARD typedef ptr FORWARD ; Pointers to forward-referenced types
FORWARD struct ; are assumed to be pointers to structs
blah word ?
FORWARD ends
Expressions
An expression is a sequence of operators and operands that are evaluated to derive a numeric result, an effective address, or a register operand.
Expressions are specified using standard infix notation, which is recursive in nature, ie., expressions may be nested within other expressions. The evaluation of an expression occurs in a left to right manner, and is influenced by the rules of operator precedence and associativity. The order in which expressions are evaluated can be controlled by grouping operands and operators together using parentheses ().
Expression Syntax
- Description
This section describes the complete expression syntax.
- Syntax
Expression:
- Duplicative-Expression
Duplicative-Expression:
- Attribute-Expression
- Attribute-Expression DUP ( Initializer-List )
Attribute-Expression:
- OR-Expression SHORT Additive-Expression
- .TYPE OR-Expression
- OPATTR OR-Expression
OR-Expression:
- AND-Expression
- OR-Expression OR AND-Expression
- OR-Expression XOR AND-Expression
AND-Expression]]:
- NOT-Expression]]
- AND-Expression]] AND NOT-Expression
NOT-Expression]]:
- Relational-Expression NOT Relational-Expression
Relational-Expression:
- Additive-Expression
- Relational-Expression EQ Additive-Expression
- Relational-Expression NE Additive-Expression
- Relational-Expression GT Additive-Expression
- Relational-Expression GE Additive-Expression
- Relational-Expression LT Additive-Expression
- Relational-Expression LE Additive-Expression
Additive-Expression:'
- Multiplicative-Expression
- Additive-Expression + Multiplicative-Expression
- Additive-Expression - Multiplicative-Expression
Multiplicative-Expression:
- Narrowed-Expression
- Multiplicative-Expression * Narrowed-Expression
- Multiplicative-Expression / Narrowed-Expression
- Multiplicative-Expression MOD Narrowed-Expression
- Multiplicative-Expression SHL Narrowed-Expression
- Multiplicative-Expression SHR Narrowed-Expression
Narrowed-Expression:
- Cast-Expression
- HIGH Cast-Expression
- HIGHWORD Cast-Expression
- LOW Cast-Expression
- LOWWORD Cast-Expression
Cast-Expression:
- Element-Selection-Expression
- OFFSET Cast-Expression
- SEG Cast-Expression
- THIS Element-Selection-Expression
- TYPE Element-Selection-Expression
- Cast-Expression PTR Cast-Expression
- Cast-Expression : Cast-Expression
Element-Selection-Expression:
- Sign-Expression
- Element-Selection-Expression
- Sign-Expression
- Element-Selection-Expression . Sign-Expression
Sign-Expression:
- Primary-Expression
- - Primary-Expression
- + Primary-Expression
Primary-Expression:
- Literal-Operand
- Record-Constant
- Identifier-Operand
- Register-Operand
- Integral-TypeName-Operand
- Value-Substitution-Operand
- LENGTH Identifier-Operand
- LENGTHOF Identifier-Operand
- MASK Identifier-Operand
- SIZE Element-Selection-Expression
- SIZEOF Element-Selection-Expression
- WIDTH Identifier-Operand
- Parenthesized-Expression
- Indirected-Expression
- Compound-Initializer
Literal-Operand:
- Floating-Point-Literal
- Integer-Literal
- String-Literal]]
Record-Constant:
- Identifier-Operand < Field-List >
- Identifier-Operand { Field-List }
Field-List:
- Attribute-Expression
- Field-List , Attribute-Expression
Identifier-Operand:
- Identifier
Register-Operand:
- Processor-Register
Integral-TypeName-Operand:
- Scalar-TypeName
- Distance-TypeName
Value-Substitution-Operand:
- Anonymous-Label-Alias
- Location-Counter-Alias
- Indeterminate-Value-Alias
- FLAT
Parenthesized-Expression:
- ( Attribute-Expression )
Indirected-Expression:
- [ Attribute-Expression ]
Compound-Initializer:
- < Initializer-List >
- { Initializer-List }
Initializer-List:
- Duplicative-Expression
- Initializer-List , Duplicative-Expression
Duplicative Initialization Expression
- Description
A Duplicative Initialization Expression is one that can be optionally used during the initialization of variables such that the operand is duplicated a specified number of times.
- Syntax
Duplicative-Expression:
- Attribute-Expression
- Attribute-Expression
- #DUP ( Initializer-List )
Initializer-List:
- Duplicative-Expression
- Initializer-List , Duplicative-Expression
Duplicative Initialization (DUP Operator)
- Description
The DUP operator creates a Duplicated-ExpressionType from the Initializer-List enclosed in parentheses. This construct can be used to create arrays of information during data allocation.
- Syntax
Attribute-Expression DUP (Initializer-List)
Initializer-List:
Duplicative-Expression
Initializer-List,|Duplicative-Expression
- Constraints
The left hand operand of the DUP operator must evaluate to an Absolute-ExpressionType.
Each Duplicative-Expression in the Initializer-List must evaluate to an Initializer-ExpressionType.
- Examples
STR STRUCT
One BYTE 0
Two BYTE 0
STR ENDS
Array1 WORD 4 DUP (1,2,3,4) ; allocates 16 words
Array2 STR 8 DUP (<1,2>) ; 8 structures
Attribute Expression
- Description
An Attribute Expression is one that optionally extracts or modifies one or more of the basic properties of its operand.
- Syntax
Attribute-Expression:
- OR-Expression
- SHORT Additive-Expression
- .TYPE OR-Expression
- OPATTR OR-Expression
Expression Descriptor Bitmap (.TYPE Operator)
- Description
The .TYPE operator is considered obsolete. The #OPATTR operator should be used instead.
The .TYPE operator returns a byte value bitmap that describes various attributes of its operand. The return value is 0 if the expression could not be correctly parsed or evaluated, otherwise the bitmap returned is formatted according to the following table:
7 |
6 |
5 |
4 |
3 |
2 |
1 |
0 |
BIT SET IF EXPRESSION
|
|
|
|
|
|
|
|
1 |
Is a Direct-ExpressionType
|
|
|
|
|
|
|
1 |
|
Is a Indirect-ExpressionType, an Indexed-ExpressionType, or a combination of both
|
|
|
|
|
|
1 |
|
|
Is an Immediate-ExpressionType
|
|
|
|
|
1 |
|
|
|
Is an Indirect-ExpressionType
|
|
|
|
1 |
|
|
|
|
Is a Register-ExpressionType
|
|
|
1 |
|
|
|
|
|
Was parsed and evaluated without error (no undefined symbols, etc.)
|
|
1 |
|
|
|
|
|
|
Is relative to the SS Segment-Register
|
1 |
|
|
|
|
|
|
|
Contains an External Reference
|
.TYPE OR-Expression
- Syntax
.TYPE OR-Expression
- Examples
BumpCounter macro bump
if (((.TYPE (bump)) and 07h) eq 04h)
Counter = Counter + bump
else
.err <Non-constant value passed to BumpCounter>
endif
endm
Extended Descriptor Bitmap (OPATTR Operator)
OPATTR OR-Expression
- Syntax
OPATTR OR-Expression'
- Description
The OPATTR operator returns a superset of the information returned by the .TYPE operator, which should be considered obsolete.
The OPATTR operator returns a word value bitmap that describes various attributes of its operand. The return value is 0 if the expression could not be correctly parsed or evaluated, otherwise the bitmap returned is formatted according to the following table:
A98
|
7
|
6
|
5
|
4
|
3
|
2
|
1
|
0
|
BIT SET IF EXPRESSION
|
|
|
|
|
|
|
|
|
1
|
Is a Direct-ExpressionType
|
|
|
|
|
|
|
|
1
|
|
Is a Indirect-ExpressionType, an Indexed-ExpressionType, or a combination of both
|
|
|
|
|
|
|
1
|
|
|
Is an Immediate-ExpressionType
|
|
|
|
|
|
1
|
|
|
|
Is an Indirect-ExpressionType
|
|
|
|
|
1
|
|
|
|
|
Is a Register-ExpressionType
|
|
|
|
1
|
|
|
|
|
|
Was parsed and evaluated without error (no undefined symbols, etc.)
|
|
|
1
|
|
|
|
|
|
|
Is relative to the SS Segment-Register
|
|
1
|
|
|
|
|
|
|
|
Contains an External Reference
|
LLL
|
|
|
|
|
|
|
|
|
Language encoding (described below)
|
The LLL field (bits 8, 9, and A) comprise an enumerated value that describes the language attribute assigned to the expression as follows:
- 000 No language attribute used in expression
- 001 C
- 010 SYSCALL
- 011 STDCALL
- 100 PASCAL
- 101 FORTRAN
- 110 BASIC
- 111 OPTLINK
- Constraints
This operator is not available in M510 mode.
- Examples
L_MASK equ 011100000000y ; mask to isolate language bits
L_OPTLINK equ 011100000000y ; setting for OptLink calling convention
VerifyCallBack macro ProcName
if (((OPATTR (ProcName)) and L_MASK) ne L_OPTLINK)
.err <Call-back routine must have OptLink linkage>
endif
endm
Force Short Relative Address (SHORT Operator)
- Syntax
SHORT Additive-Expression
- Description
The SHORT operator forces the assembler to calculate the distance from the start of the next instruction to the target specified by the operand (given by Additive-Expression) to be less than 128 bytes away. This can cause the assembler to generate more efficient control transfer instructions when the target is a forward reference. By default, the assembler assumes that the code-relative target is of NEAR distance when the target is an unqualified forward reference.
- Constraints
The Additive-Expression must evaluate to a Direct-ExpressionType.
- Examples
JMP Forward ; target unknown, NEAR jump generated
JMP SHORT Forward ; force SHORT encoding
.
. ; fewer than 128 bytes of instructions
.
Forward: ; definition of target
Bitwise OR Expression
- Description
A Bitwise OR Expression is one where an optional binary bitwise OR operation between the left and right operands is performed and the result returned.
- Syntax
OR-Expression: AND-Expression
OR-Expression OR AND-Expression
OR-Expression XOR AND-Expression
Bitwise Inclusive OR (OR Operator)
- Syntax
OR-Expression OR AND-Expression
- Description
The OR operator performs a binary bitwise OR operation on the left and right hand operands.
- Constraints
Each operand must evaluate to a Constant-ExpressionType.
- Examples
One EQU 1
Two EQU 2
MOV AX, One OR Two ; moves 3 into AX
Bitwise Exclusive OR (XOR Operator)
- Syntax
OR-Expression XOR AND-Expression
- Description
The XOR operator performs a binary bitwise XOR operation on the left and right hand operands.
- Constraints
Each operand must evaluate to a Constant-ExpressionType.
- Examples
Lower EQU 0101y ; 7h - binary radix suffix
Upper EQU 1100y ; Eh - binary radix suffix
MOV AX, Upper XOR Lower ; moves 1001 into AX
Bitwise AND Expression
- Description
A Bitwise AND Expression is one where an optional binary bitwise AND operation between the left and right operands is performed and the result returned.
- Syntax
AND-Expression:
- NOT-Expression
- AND-Expression AND NOT-Expression
Bitwise AND (AND Operator)
- Syntax
AND-Expression AND NOT-Expression
- Description
The AND operator performs a binary bitwise AND operation on the left and right hand operands.
- Constraints
Each operand must evaluate to a Constant-ExpressionType.
- Examples
Lower EQU 0111y ; 7h - binary radix suffix
Upper EQU 1110y ; Eh - binary radix suffix
MOV AX, Upper XOR Lower ; moves 0110 into AX
Bitwise One's Complement Expression
- Description
A Bitwise One's Complement Expression is one that performs an optional unary bitwise negation of its operand and returns the result.
- Syntax
NOT-Expression:
Relational-Expression
NOT Relational-Expression
Bitwise One's Complement (NOT Operator)
- Syntax
NOT Relational-Expression
- Description
The NOT operator performs a unary bitwise negation on its operand.
- Constraints
The operand must evaluate to a Constant-ExpressionType.
- Examples
Value EQU 0111y ; 7h - binary radix suffix
MOV EAX, NOT Value ; moves FFFFFFF8 into EAX
Relational Expression
- Description
A Relational Expression is one where an optional binary comparision operation between the left and right operands is performed and the result returned.
- Syntax
- Relational-Expression:
- Additive-Expression
- Relational-Expression EQ Additive-Expression
- Relational-Expression NE Additive-Expression
- Relational-Expression GT Additive-Expression
- Relational-Expression GE Additive-Expression
- Relational-Expression LT Additive-Expression
- Relational-Expression LE Additive-Expression
Equal To (EQ Operator)
- Syntax
- Relational-Expression EQ Additive-Expression
- Description
The EQ operator performs a binary logical comparision on the left and right hand operands. It returns true (all bits on) if they are equal, and false (all bits off) if they are not equal.
- Constraints
Each operand must evaluate to a Constant-ExpressionType.
- Examples
IF 1234 EQ 5678
TRUE = 1
ELSE
TRUE = 0 ; Sets TRUE to 0
ENDIF
Not Equal To (NE Operator)
- Syntax
- Relational-Expression NE Additive-Expression
- Description
The NE operator performs a binary logical comparision on the left and right hand operands. It returns true (all bits on) if they are not equal, and false (all bits off) if they are equal.
- Constraints
Each operand must evaluate to a Constant-ExpressionType.
- Examples
IF 1234 NE 5678
TRUE = 1 ; Sets TRUE to 1
ELSE
TRUE = 0
ENDIF
Greater Than (GT Operator)
- Syntax
- Relational-Expression GT Additive-Expression
- Description
The GT operator performs a binary logical comparision on the left and right hand operands. It returns true (all bits on) if the left operand is greater than the right operand, and false (all bits off) if it is not.
- Constraints
Each operand must evaluate to a Constant-ExpressionType.
- Examples
IF 1234 GT 5678
TRUE = 1
ELSE
TRUE = 0 ; Sets TRUE to 0
ENDIF
Greater Than or Equal To (GE Operator)
- Syntax
- Relational-Expression GE Additive-Expression
- Description
The GE operator performs a binary logical comparision on the left and right hand operands. It returns true (all bits on) if the left operand is greater than or equal to the right operand, and false (all bits off) if it is not.
- Constraints
Each operand must evaluate to a Constant-ExpressionType.
- Examples
IF 1234 GE 1234
TRUE = 1 ; Sets TRUE to 1
ELSE
TRUE = 0
ENDIF
Less Than (LT Operator)
- Syntax
- Relational-Expression LT Additive-Expression
- Description
The LT operator performs a binary logical comparision on the left and right hand operands. It returns true (all bits on) if the left operand is less than the right operand, and false (all bits off) if it is not.
- Constraints
Each operand must evaluate to a Constant-ExpressionType.
- Examples
IF 1234 LT 5678
TRUE = 1 ; Sets TRUE to 1
ELSE
TRUE = 0
ENDIF
Less Than or Equal To (LE Operator)
- Syntax
- Relational-Expression LE Additive-Expression
- Description
The LE operator performs a binary logical comparision on the left and right hand operands. It returns true (all bits on) if the left operand is less than or equal to the right operand, and false (all bits off) if it is not.
- Constraints
Each operand must evaluate to a Constant-ExpressionType.
- Examples
IF 1234 LE 1234
TRUE = 1 ; Sets TRUE to 1
ELSE
TRUE = 0
ENDIF
Additive Expression
- Description
A Additive Expression is one where an optional binary additive arithmetic operation between the left and right operands is performed and the result returned.
- Syntax
- Additive-Expression:
- Multiplicative-Expression
- Additive-Expression + Multiplicative-Expression
- Additive-Expression - Multiplicative-Expression
Addition (+ Operator)
- Syntax
- Additive-Expression + Multiplicative-Expression
- Description
The + operator performs a binary addition operation on the left and right hand operands, and returns the result.
- Constraints
One of the operands must evaluate to a Constant-ExpressionType. If one of the operands references an external identifier, then the other operand must be a Constant-ExpressionType without an external reference. Both operands must be of scalar type.
- Examples
VALUE = 100 + 11 ; sets VALUE to 111
Subtraction (- Operator)
- Syntax
- Additive-Expression - Multiplicative-Expression
- Description
The - operator performs a binary subtraction operation on the left and right hand operands, and returns the result.
- Constraints
The right operand must evaluate to a Constant-ExpressionType and reference no external identifiers. If both operands are relocatable, they must reside within the same segment, in which case the result is converted to a Absolute-ExpressionType. Both operands must be of scalar type.
- Examples
VALUE = 111 - 11 ; sets VALUE to 100
Multiplicative Expression
- Description
A Multiplicative Expression is one where an optional binary multiplicative arithmetic operation between the left and right operands is performed and the result returned.
- Syntax
- Multiplicative-Expression:
- Narrowed-Expression
- Multiplicative-Expression * Narrowed-Expression
- Multiplicative-Expression / Narrowed-Expression
- Multiplicative-Expression MOD Narrowed-Expression
- Multiplicative-Expression SHL Narrowed-Expression
- Multiplicative-Expression SHR Narrowed-Expression
Multiplication (* Operator)
- Syntax
- Multiplicative-Expression * Narrowed-Expression
- Description
The * operator performs a binary multiplication operation on the left and right hand operands, and returns the result.
- Constraints
Each operand must evaluate to a Constant-ExpressionType.
- Examples
VALUE = 9 * 3 ; sets VALUE to 27
Division (/ Operator)
- Syntax
- Multiplicative-Expression / Narrowed-Expression
- Description
The / operator performs a binary division operation on the left and right hand operands, and returns the result.
- Constraints
Each operand must evaluate to a Constant-ExpressionType.
- Examples
VALUE = 27 / 9 ; sets VALUE to 3
Remainder (MOD Operator)
- Syntax
- Multiplicative-Expression MOD Narrowed-Expression
- Description
The MOD operator performs a binary modulus division operation on the left and right hand operands, and returns the remainder as the result.
- Constraints
Each operand must evaluate to a Constant-ExpressionType.
- Examples
VALUE = 18 MOD 4 ; sets VALUE to 2
Bitwise Left Shift (SHL Operator)
- Syntax
- Multiplicative-Expression SHL Narrowed-Expression
- Description
The SHL operator shifts the bits in the left hand operand to the left by the number of bits specified in the right hand operand, and returns the result.
- Constraints
Each operand must evaluate to a Constant-ExpressionType.
- Examples
VALUE = 1111y SHL 4 ; sets VALUE to 11110000y
Bitwise Right Shift (SHR Operator)
- Syntax
- Multiplicative-Expression SHR Narrowed-Expression
- Description
The SHR operator shifts the bits in the left hand operand to the right by the number of bits specified in the right hand operand, and returns the result.
- Constraints
Each operand must evaluate to a Constant-ExpressionType.
- Examples
VALUE = 11110000y SHR 4 ; sets VALUE to 00001111y
Narrowed Expression
- Description
A Narrowed Expression is one that performs an optional unary narrowing operation on its operand and returns the result.
- Syntax
Narrowed-Expression:
- Cast-Expression HIGH Cast-Expression
- HIGHWORD Cast-Expression
- LOW Cast-Expression
- LOWWORD Cast-Expression
Upper 8 Bits of WORD Expression (HIGH Operator)
- Syntax
- HIGH Cast-Expression
- Description
The HIGH operator returns the upper 8 bits of a 16-bit expression. Only bits 8-15 are returned, even if the magnitude of the operand exceeds 16 bits.
- Constraints
The operand must evaluate to a Constant-ExpressionType.
- Examples
FIRST = 1234h
SECOND = HIGH FIRST ; Sets SECOND to 12h
Upper 16 Bits of DWORD Expression (HIGHWORD Operator)
- Syntax
- HIGHWORD Cast-Expression
- Description
The HIGHWORD operator returns the upper 16 bits of a 32-bit expression. Only bits 16-31 are returned, even if the magnitude of the operand exceeds 32 bits.
- Constraints
The operand must evaluate to a Constant-ExpressionType.
This operator is not available in M510 mode.
- Examples
FIRST = 12345678h
SECOND = HIGHWORD FIRST ; Sets SECOND to 1234h
Lower 8 Bits of WORD Expression (LOW Operator)
- Syntax
- LOW Cast-Expression
- Description
The LOW operator returns the lower 8 bits of its operand.
- Constraints
The operand must evaluate to a Constant-ExpressionType.
- Examples
FIRST = 1234h
SECOND = LOW FIRST ; Sets SECOND to 34h
Lower 16 Bits of DWORD Expression (LOWWORD Operator)
- Syntax
- LOWWORD Cast-Expression
- Description
The LOWWORD operator returns the lower 16 bits of its operand.
- Constraints
The operand must evaluate to a Constant-ExpressionType.
This operator is not available in #M510 mode.
- Examples
FIRST = 12345678h
SECOND = LOWWORD FIRST ; Sets SECOND to 5678h
Type Conversion Expression
- Description
A Type Conversion Expression is one that performs an optional type conversion operation on its operand and returns the result.
- Syntax
Cast-Expression:
- Element-Selection-Expression
- OFFSET Cast-Expression
- SEG Cast-Expression
- THIS Element-Selection-Expression
- TYPE Element-Selection-Expression
- Cast-Expression PTR Cast-Expression
- Cast-Expression : Cast-Expression
Address Offset (OFFSET Operator)
- Description
The OFFSET operator returns the offset portion of its operand. For relocatable values, this is the offset into the segment or group to which the expression is relative.
- Syntax
OFFSET Cast-Expression
- Constraints
The operand may evaluate to any one of the following #ExpressionTypes:
- Absolute-ExpressionType
- Constant-ExpressionType
- Immediate-ExpressionType
- Direct-ExpressionType
- Indirect-ExpressionType
- Examples
CodeLabel:
MOV AX, CodeLabel ; illegal, no data at address
MOV AX, OFFSET CodeLabel ; we want the address itself
Address Segment (SEG Operator)
- Syntax
SEG Cast-Expression
- Description
The SEG operator returns the segment or group to which a relocatable expression is relative.
- Constraints
The operand must evaluate to one of the following ExpressionTypes:
- Immediate-ExpressionType
- Direct-ExpressionType
- Indirect-ExpressionType
- Indexed-ExpressionType
- Examples
DATA SEGMENT
Stuff DB ?
MOV AX, SEG Stuff ; This construct is
MOV AX, DATA ; equivalent to this
DATA ENDS
Address Alias (THIS Operator)
- Syntax
THIS Element-Selection-Expression
- Description
The THIS operator returns an operand whose:
- Relative Frame attribute is set to that of the current segment
- Displacement attribute is set to the current location counter
- Type Declaration attribute is set to that of the expression given by the Element-Selection-Expression operand.
- Constraints
The operand must evaluate to a Type-ExpressionType.
- Examples
DATA SEGMENT
ALIAS EQU THIS BYTE ; reference this address as a byte
Stuff DB ?
MOV AL, ALIAS ; This construct is
MOV AL, Stuff ; equivalent to this
DATA ENDS
- Syntax
TYPE Element-Selection-Expression
- Description
The TYPE operator returns the Type-ExpressionType attribute of its operand.
- Constraints
None
- Examples
CODE SEGMENT
ASSUME CS:CODE, DS:CODE
Stuff DB ? ; TYPE Stuff is BYTE
MOV [BX],(TYPE Stuff) PTR 1 ; stores 1 as a BYTE at [BX]
CODE ENDS
Type Conversion (PTR Operator)
- Syntax
Cast-Expression PTR Cast-Expression
- Description
The PTRoperator converts the right operand to the type specified by the left operand.
- Constraints
The left operand must be a Type-ExpressionType.
- Examples
CODE SEGMENT
MOV BYTE PTR [BX], 1 ; stores 1 as a BYTE at [BX]
CODE ENDS
Segment Override (: Operator)
- Syntax
Cast-Expression : Cast-Expression
- Description
The : (colon) operator forces the right operand to have the Relative Frame attribute of the left operand.
- Constraints
The left operand must evaluate to one of the following #ExpressionTypes:
- Register-ExpressionType where the Register Value attribute is that of a Segment-Register
- Immediate-ExpressionType where the Relative Frame attribute is that of a GroupName or SegmentName.
- Examples
DATA SEGMENT
Variable DW ?
DATA ENDS
DGROUP GROUP DATA, CODE
CODE SEGMENT
ASSUME CS:CODE, DS:DGROUP
MOV AX, DGROUP:Variable ; insure Variable is relative to DGROUP
ASSUME DS:NOTHING
MOV BX, CS:Variable ; access Variable through CS register
CODE ENDS
Element Selection Expression
- Description
A Element Selection Expression is one that optionally selects a specific element of its operand and returns a reference to it.
- Syntax
Element-Selection-Expression:
- Sign-Expression]]
- Element-Selection-Expression [Sign-Expression]
- Element-Selection-Expression .Sign-Expression
Subscript ([] Operator)
- Syntax
Element-Selection-Expression [ Sign-Expression ]
- Description
The [] binary operator performs a subscripting (or indexing) operation between the operand to the left of the brackets and the operand enclosed within the brackets. This is a simple additive operation of BYTE granularity; the arithmetic performed is not influenced by the Operand Size of either operand.
The syntax for this operator describes a binary operation between the left hand expression and the bracketed expression. The bracketed expression is also subject to the same operations performed during the processing of a standalone Indirected-Expression as described in the section on Primary-Expressions.
- Constraints
Only one of the operands may specify a relocatable value.
- Examples
CODE SEGMENT
ASSUME CS:CODE, DS:CODE
Value DB 0 ; Value [0]
DB 1 ; Value [1]
DB 2 ; Value [2]
DB 3 ; Value [3]
DB 4 ; Value [4]
MOV AL, Value [3] ; load AL with the fourth byte at Value (3)
MOV BX, offset Value ; get address of Value
MOV AL, [BX] [1] [2] ; also gets the fourth byte ( 3 )
CODE ENDS
Structure/Union Field Selection (. Operator)
- Syntax
Element-Selection-Expression . Sign-Expression
- Description
The . (period) operator selects a structure or union field entry. It adds the left and right hand operands together and returns the result. The left operand should be an Indirect-ExpressionType, Indexed-ExpressionType, or Type-ExpressionType whose Type Declaration attribute resolves to that of a Structure-TypeName or Union-TypeName. The right operand should refer to a FieldName defined within the referenced type.
The Operand Size attribute of the result depends on the operands involved. If both operands have an operand size, a Structure-FieldName appearing as the right hand operand would override the operand size of the left operand and would dictate the operand size of the resulting expression.
- Constraints
Only one of the operands may specify a relocatable value.
- Examples
Number STRUC
One DB 1
Two DW 2
Number ENDS
; The following line is only allowed in MASM 5.10 mode ( OPTION OLDSTRUCTS )
MOV AX,[BX] .Two ; BX points to a "Number", get the "Two" entry
; In other modes, "Two" is private to the "Number" structure type, so
; one of the following methods are required :
MOV AX,(Number PTR[BX]).Two ; Explicit override
MOV AX,[BX] + Number.Two ; Fully qualified reference
ASSUME BX:Number ; Associate BX with "Number"
MOV AX,[BX].Two ; then original syntax is allowed
Unary Arithmetic Expression
- Description
A Unary Arithmetic Expression is one that optionally alters the sign of its operand and returns the result.
- Syntax
Sign-Expression:
- Primary-Expression
- -Primary-Expression
- +Primary-Expression
Unary Minus (- Operator)
- Syntax
- Primary-Expression
- Description
The - operator makes its operand into a negative number and returns the result.
- Constraints
The operand must evaluate to a Constant-ExpressionType.
- Examples
Value EQU 1
MOV AX, -Value ; move -1 into AX
Unary Plus (+ Operator)
- Syntax
+ Primary-Expression
- Description
The + operator returns its operand.
- Constraints
The operand must evaluate to a Constant-ExpressionType.
- Examples
Value EQU 1
MOV AX,+Value ; move 1 into AX
Primary Expression
- Description
A Primary Expression is one that returns an expression operand.
- Syntax
Primary-Expression:
- Literal-Operand
- Record-Constant
- Identifier-Operand
- Register-Operand
- Integral-TypeName-Operand
- Value-Substitution-Operand
- LENGTH Identifier-Operand
- LENGTHOF Identifier-Operand
- MASK Identifier-Operand
- SIZE Element-Selection-Expression
- SIZEOF Element-Selection-Expression
- WIDTH Identifier-Operand
- Parenthesized-Expression
- Indirected-Expression
- Compound-Initializer
Literal Operand
- Syntax
Literal-Operand:
- Floating-Point-Literal
- Integer-Literal
- String-Literal
- Description
The assembler accepts several types of literal values as operands within expressions. Literal-Operands are converted to #ExpressionTypes according to the following table:
Floating-Point-Literal
|
Floating-Point-ExpressionType
|
Integer-Literal
|
Absolute-ExpressionType
|
String-Literal
|
Absolute-ExpressionType if the string length is less than or equal to the current Address Size; a String-ExpressionType otherwise.
|
The context where the expression is used determines whether or not a particular type of literal is legal.
- Constraints
Arithmetic operations cannot be performed on #Floating-Point-Literals, thus they cannot be the operand of a unary or binary operator.
Value Substitution Operand
- Syntax
Value-Substitution-Operand:
- Anonymous-Label-Alias
- Location-Counter-Alias
- Indeterminate-Value-Alias
- FLAT
- Description
These operands are used to retrieve specialized values that are calculated internally by the assembler.
The FLAT operator returns an expression whose #Relative Frame is set to that of the predefined FLAT pseudo-group.
- Constraints
The FLAT operand is only active when a 32-bit processor has been selected.
Record Constant Operand
- Syntax
Record-Constant:
- Identifier-Operand < Field-List >
- Identifier-Operand { Field-List }
Field-List:
- Attribute-Expression
- Field-List , Attribute-Expression
- Description
A Record-Constant provides a method of calculating a single numeric result value from a list of Record-FieldName values, and combining them together according to the definition of the Record-TypeName given by the Identifier-Operand. The result value is a Constant-ExpressionType suitable for use as an instruction operand, or for assigning to a record variable.
The Record-TypeName given by the Identifier-operand determines how the Field-List will be evaluated. The Attribute-Expression entries are position-dependent, and are matched with the corresponding Record-FieldName entries from the Record-TypeName definition to determine their width and shift values. Attribute-Expression entries may be omitted, in which case the default values from the record definition are used in the calculation.
- Constraints
The Identifier-Operand must resolve to a Record-TypeName.
- Examples
DATE_T record Year : 7 = 0, ; 0 is 1980
Month : 4 = 1, ; January
Day : 5 = 1 ; 1st
CODE SEGMENT
mov AX,DATE_T < > ; January 1st, 1980
mov AX,DATE_T < 1996 - 1980, 12, 25 > ; Christmas, 1996
mov AX,DATE_T < 10h, 0Ch, 19h > ; equivalent values in hex
mov AX,DATE_T < 10000y, 1100y, 11001y > ; equivalent values in binary
mov AX,2199h ; equivalent value manually coded
mov AX,0010000110011001y ; and in binary
; YYYYYYYMMMMDDDDD
CODE ENDS
Register Operand
- Syntax
Register-Operand:
- Processor-Register
- Description
Processor registers are valid expression operands. The context where the expression is used determines the allowable register operands.
- Constraints
The currently selected processor dictates whether or not a register is visible to the expression evaluator.
Identifier Operand
- Syntax
Identifier-Operand:
- Identifier
- Description
When an Identifier is used in an expression, it returns a value according to its Identifier-Type, as shown in the following table:
Identifier-Type
|
VALUE RETURNED
|
Numeric-EquateName
|
The value originally assigned to the equate.
|
Structure-FieldName
|
The offset in bytes from the beginning of the structure.
|
Union-FieldName
|
The offset in bytes from the beginning of the union (always 0).
|
Record-FieldName
|
The shift-count required to reach the field within the record.
|
Record-TypeName
|
The mask-value that isolates defined record fields from undefined fields.
|
Structure-TypeName
|
Zero if mode is M510, otherwise the size of the structure in bytes (the operand size of the structure type).
|
Union-TypeName
|
The size of the union in bytes (the operand size of the union type).
|
Typedef-TypeName
|
The operand size of the underlying data-type represented by the Typedef-TypeName.
|
GroupName
|
A Relative Frame attribute that represents the group, and a Displacement value of zero.
|
SegmentName
|
A Relative Frame attribute that represents the segment (or the group to which it belongs), and a Displacement value of zero if the mode is M510, or the current segment offset otherwise.
|
LabelName
|
The Relative Frame attribute where the label is defined, and the segment offset value of the label.
|
- Constraints
The Identifier must resolve to one of the following Identifier-Types:
- Numeric-EquateName
- FieldName
- GroupName
- LabelName
- SegmentName
- UserDefined-TypeName
Integral Type-Name Operand
- Syntax
Integral-TypeName-Operand:
- Scalar-TypeName
- Distance-TypeName
- Description
When an Integral-TypeName-Operandis used in an expression, it is converted to a Type-ExpressionType. If used in a numeric context, the following numeric values are returned:
Integral-TypeName-Operand |
VALUE RETURNED
|
Scalar-TypeName |
The operand-size of the type in bytes.
|
Distance-TypeName |
If mode is M510, NEAR returns FFFF, and FAR returns FFFE. Otherwise, NEAR and FAR are resolved and the values returned are: NEAR16=FF02, NEAR32=FF04, FAR16=FF05, FAR32=FF06.
|
- Constraints
The NEAR32 and FAR32 keywords are only valid if a 32-bit processor has been selected.
Number of Data Elements (LENGTH Operator)
- Syntax
LENGTH Identifier-Operand
- Description
The LENGTH operator returns the number of data elements allocated to the operand. When applied to a variable initialized with a series of comma-separated expressions (elements), only the length of the first element is considered.
- Constraints
The operand must evaluate to a Data-LabelName.
Number of Data Elements (LENGTHOF Operator)
- Syntax
LENGTHOF Identifier-Operand
- Description
The LENGTHOF operator returns the number of data elements allocated to the operand.
- Constraints
The operand must evaluate to a Data-LabelName.
This operator is not available in M510 mode.
- Examples
<none>
Record or Field Bit-Mask (MASK Operator)
- Syntax
MASK Identifier-Operand
- Description
The MASK operator returns the bit mask required to isolate a field within a record.
- Constraints
The Identifier-Operand must resolve to a Record-TypeName or Record-FieldName; otherwise the result is zero.
Size of Variable in Bytes (SIZE Operator)
- Syntax
SIZE Element-Selection-Expression
- Description
The SIZE operator returns the number of bytes allocated to the operand. When applied to a variable initialized with a series of comma-separated expressions (elements), only the size of the first element is considered.
- Constraints
None
Size of Variable in Bytes (SIZEOF Operator)
- Syntax
SIZEOF Element-Selection-Expression
- Description
The SIZEOF operator returns the number of bytes allocated to the operand.
- Constraints
This operator is not available in M510 mode.
Record or Field Width (WIDTH Operator)
- Syntax
WIDTH Identifier-Operand
- Description
The WIDTHoperator returns the width of a record or a record field name.
- Constraints
The Identifier-Operand must resolve to a Record-TypeName or Record-FieldName; otherwise the result is zero.
Precedence (() Operator)
- Syntax
Parenthesized-Expression:
- ( Attribute-Expression )
- Description
Parentheses forces the Attribute-Expression operand to be evaluated at a higher precedence level.
- Examples
Value = 2 + 3 * 4 ; Value = 14
Value = ( 2 + 3 ) * 4 ; Value = 20
Indirection ([] Operator)
- Syntax
Indirected-Expression:
- [ Attribute-Expression ]
- Description
During evaluation of the Attribute-Expression, the [](indirection) operator will convert a Register-ExpressionType to a Indexed-ExpressionType by moving the Register Value attribute to either the Base Register or Index Register attribute field as appropriate for the register(s) referenced in the expression. This operation allows values contained in the processor registers to be used during effective address calculation at application run time.
- Constraints
See the Indexed-ExpressionType section for information on registers that are valid for use in this context.
- Examples
CODE SEGMENT
ASSUME CS : CODE , DS : CODE
Value DW 0
MOV BX , offset Value ; load the address of Value into BX
MOV [ BX ] , BX ; store the contents of BX into the
; memory location addressed by [BX]
CODE ENDS
Compound Initializer List (<> Operator)
- Syntax
Compound-Initializer:
- < Initializer-List >
- { Initializer-List }
Initializer-List:
- Duplicative-Expression
- Initializer-List , Duplicative-Expression
- Description
The <> (or {}) operator provides a way of specifying a list of expressions to be used for initializing complex (multi-field) variables such as records or structures.
The <> operator encloses a list of comma-separated expressions; individual expressions are optional, but are also positional with respect to the record or structure fields they are intended to initialize. Commas must therefore be used to maintain field positions if empty expressions are encountered in the list.
The initializer list itself may also be left out entirely for those cases where a variable allocation will use the default initializers provided in the record or structure definition (the <>or {} themselves are still required).
- Examples
Numbers STRUCT
One DB 0
Two DW 0
Three DB 0
Four DD 0
Numbers ENDS
First Numbers < > ; empty initializer list
Second Numbers < 1, 2, 3, 4 > ; override all defaults
Third Numbers < 1 > ; override first entry only
Fourth Numbers < 1, , , 4 > ; override first and last entries
Expression Evaluation
After an expression is parsed and checked for syntax errors, it is evaluated. During evaluation, all calculations and conversions are performed on the operands according to the operators that are applied to them. The final result is a collection of #Expression-Attributes, to which an ExpressionType is assigned.
Expression Attributes
This section describes the Expression-Attributesthat are associated with an expression after it is evaluated.
Address Size
If an expression refers to an effective address, then it also has an associated #address size. The following #ExpressionTypes normally reference an effective address, and thus have an associated address size:
- Immediate-ExpressionType
- Direct-ExpressionType
- Indirect-ExpressionType
- Indexed-ExpressionType
The address size can be either 2 (USE16) or 4 (USE32). For an expression that references a label, the address size of the segment where the label is defined determines the address size of the expression.
Operand Size
The Operand Size of an expression can be set explicitly using the #Type Conversion (PTR Operator), or it may be a side-effect inherited from the type of data referenced in the expression. The following table describes the operand sizes that will be assigned when an identifier is referenced in an expression:
REFERENCE |
OPERAND SIZE
|
8-Bit-Register |
1
|
16-Bit-Register |
2
|
32-Bit-Register |
4
|
Segment-Register |
2
|
Control-Register |
4
|
Debug-Register |
4
|
Test-Register |
4
|
MMX-Register |
8
|
Floating-Point-Register |
10
|
BYTE |
1
|
SBYTE |
1
|
WORD |
2
|
SWORD |
2
|
DWORD |
4
|
SDWORD |
4
|
REAL4 |
4
|
FWORD |
6
|
QWORD |
8
|
REAL8 |
8
|
TBYTE |
10
|
REAL10 |
10
|
NEAR |
2 or 4
|
NEAR16 |
2
|
NEAR32 |
4
|
FAR |
4 or 6
|
FAR16 |
4
|
FAR32 |
6
|
Numeric-EquateName |
Inherited from equate expression
|
GroupName |
2
|
SegmentName |
2
|
Code-LabelName |
SIZE (TYPE Code-LabelName)
|
Data-LabelName |
SIZE (TYPE Data-LabelName)
|
Structure-FieldName |
SIZE Structure-FieldName
|
Record-TypeName |
SIZE Record-TypeName
|
Structure-TypeName |
SIZE Structure-TypeName
|
Union-TypeName |
SIZE Union-TypeName
|
The Operand Size is 0 for all other identifier types.
Displacement
The Displacement value in an expression is the final calculated value of all numeric quantities, and must be a scalar value. It may also be a reference to a relocatable address, in which case the expression will also have a Relative Frame and/or an External Reference attribute. A Displacement may be used in the calculation of an effective address, either alone or in combination with a Base Register and/or an Index Register.
Relative Frame
The Relative Frame attribute will be present if the expression contains a direct or indirect reference to any of the following #Identifier-Types:
- GroupName
- LabelName
- SegmentName
The Relative Frame attribute indicates that the expression is relocatable, and specifies the GroupName or SegmentName to which the expression is relative.
External Reference
The External Reference attribute will be present if the expression references any external identifiers.
Register Value
The Register Value attribute specifies the value of the Processor-Register referenced in a Register-ExpressionType.
Base Register
The Base Register attribute specifies the value for the base register used in an Indexed-ExpressionType.
Index Register
The Index Register attribute specifies the value for the index register used in an Indexed-ExpressionType.
Scale Factor
The Scale Factor attribute specifies the scaling value used (if any) in an Indexed-ExpressionType.
Type Declaration
The Type Declaration attribute specifies the type of data referenced in the expression. This is the value extracted from the expression when it is used as the left operand of the #Type Conversion (PTR Operator).
Expression Types
- Description
An ExpressionType is assigned to every expression during evaluation. The ExpressionType is used to determine whether or not an expression is legal for the context in which it is used. The type of an expression is influenced primarily by the operands that are used, but the use of expression operators also play an important part in determining the type of an expression.
- Definition
ExpressionType:
- Absolute-ExpressionType
- Constant-ExpressionType
- Direct-ExpressionType
- Floating-Point-ExpressionType
- Immediate-ExpressionType
- Indirect-ExpressionType
- Indexed-ExpressionType
- Register-ExpressionType
- String-ExpressionType
- Type-ExpressionType
- Duplicated-ExpressionType
- Compound-ExpressionType
Absolute Expression Type
An Absolute-ExpressionType is an expression that evaluates to an integer quantity. Its value must be representable using one of the following types of scalar data:
- BYTE
- SBYTE
- WORD
- SWORD
- DWORD
- SDWORD
- FWORD
- QWORD
- TBYTE
The following restrictions apply to an Absolute-ExpressionType:
- It cannot be relocatable (it may not contain references to a GroupName, SegmentName or LabelName).
- It cannot reference any external symbols.
- It cannot contain any forward references.
Constant Expression Type
A Constant-ExpressionType is an Absolute-ExpressionType with the following restrictions relaxed:
- It may contain forward references to identifiers defined later in the source stream.
- It may reference a single external symbol, provided that the symbol was declared in an EXTERN directive with the ABS attribute.
Immediate Expression Type
An Immediate-ExpressionType has all the properties of a Constant-ExpressionType with the following restrictions relaxed:
- It may contain references to a GroupName, SegmentName or LabelName(it may be relocatable).
- It may reference a relocatable external symbol.
An Immediate-ExpressionType must not be larger than 32 bits in magnitude; its value must be representable using one of the following types of scalar data:
- BYTE
- SBYTE
- WORD
- SWORD
- DWORD
- SDWORD
Direct Expression Type
A Direct-ExpressionType is an expression that references a Code-LabelName. It can be used directly in code-relative instructions without conversion. There is no data type associated with the address that a Direct-ExpressionType represents, therefore It may not be used in a data-relative instruction without first being explicitly converted to another expression type.
Indirect Expression Type
An Indirect-ExpressionType is an expression that references a Data-LabelName. It can be used directly in data-relative instructions without conversion to another expression type.
Indexed Expression Type
An Indexed-ExpressionType is an expression that calculates an effective memory address using the contents of a Base-Register, an Index-Register, or both. A Processor-Register must first be converted to a Base-Register or Index-Register by specifying it as the operand of the [[#Indirection ([] Operator)]]before the expression can be converted to an Indexed-ExpressionType.
When calculating a 16-bit effective address, only the BP and BX registers may be used as Base-Registers, and only the DI and SI registers may be used as Index-Registers.
When calculating a 32-bit effective address, only the EAX, EBX, ECX, EDX, EDI, ESI, EBP, and ESP registers may be used as Base-Registers, and only the EAX, EBX, ECX, EDX, EDI, ESI, and EBP registers may be used as Index-Registers.
Note: Only a single Base-Register and a single Index-Register may be used in a given expression.
On 80386 (and higher) processors, the #Multiplication (* Operator) may be used with an Index-Registeroperand and an Absolute-ExpressionType operand to establish a scaling factor that is applied to the Index-Register during effective address calculation. The scaling factor effectively causes the Index-Register to be multiplied by a fixed value at run time. The scaling Expression must evaluate to 1 (no scale factor), 2, 4, or 8.
A Direct-ExpressionType or an Indirect-ExpressionType may be a sub-expression of an Indexed-ExpressionType.
Register Expression Type
A Register-ExpressionType is an expression that specifies a single Processor-Register.
String Expression Type
A String-ExpressionType is an expression that specifies a single String- Literal.
Floating-Point Expression Type
A Floating-Point-ExpressionType is an expression that specifies a single Floating-Point-Literal.
Type Expression Type
A Type-ExpressionTypeis an expression that specifies one of the following:
- A Scalar-TypeName
- A Distance-TypeName
- A UserDefined-TypeName
Compound Expression Type
A Compound-ExpressionType evaluates to a list of (possibly nested) expressions collected together as a unit by the #Compound Initializer List ( <> Operator). A Compound-ExpressionTypeis used to initialize #aggregate data types (such as records, structures, and unions) and #vector data types (arrays).
Duplicated Expression Type
A Duplicated-ExpressionType evaluates to an expression that is to be duplicated (repeated) a specified number of times. This type of expression is created using the #Duplicative Initialization (DUP Operator).
Operand Expression Type
An Operand-ExpressionType consists of those #ExpressionTypes that are valid for use as operands in processor instructions. The following ExpressionTypes are not valid for use as an Operand-ExpressionType:
- Compound-ExpressionType
- Duplicated-ExpressionType
- A String-ExpressionType is only valid as an Operand-ExpressionType if it is short enough to be converted to an Absolute-ExpressionType having an Operand Size less than or equal to the current Address Size setting.
Operand-ExpressionType:
- Absolute-ExpressionType
- Constant-ExpressionType
- Immediate-ExpressionType
- Direct-ExpressionType
- Indirect-ExpressionType
- Indexed-ExpressionType
- Register-ExpressionType
- String-ExpressionType
- Floating-Point-ExpressionType
- Type-ExpressionType
- Description
An Operand-ExpressionTypeconsists of those #ExpressionTypes that are valid for use as operands in processor instructions. The following ExpressionTypes are not valid for use as an Operand-ExpressionType:
- Compound-ExpressionType
- Duplicated-ExpressionType
A String-ExpressionType is only valid as an Operand-ExpressionType if it is short enough to be converted to an Absolute-ExpressionType having an Operand Size less than or equal to the current Address Size setting.
- Definition
Operand-ExpressionType:
- Absolute-ExpressionType
- Constant-ExpressionType
- Immediate-ExpressionType
- Direct-ExpressionType
- Indirect-ExpressionType
- Indexed-ExpressionType
- Register-ExpressionType
- String-ExpressionType
- Floating-Point-ExpressionType
- Type-ExpressionType
Initializer Expression Type
An Initializer-ExpressionType consists of those #ExpressionTypes that are valid for use in initializing variables. The following ExpressionTypes are not valid Initializer-ExpressionTypes:
- Indexed-ExpressionType
- Register-ExpressionType
Initializer-ExpressionType:
- Scalar-Initializer-ExpressionType
- Compound-ExpressionType
- Duplicated-ExpressionType
Scalar-Initializer-ExpressionType:
- Absolute-ExpressionType
- Constant-ExpressionType
- Immediate-ExpressionType
- Direct-ExpressionType
- Indirect-ExpressionType
- String-ExpressionType
- Floating-Point-ExpressionType
- Type-ExpressionType
- Description
An Initializer-ExpressionType consists of those #ExpressionTypes that are valid for use in initializing variables. The following ExpressionTypes are not valid Initializer-ExpressionTypes:
- Indexed-ExpressionType
- Register-ExpressionType
- Definition
Initializer-ExpressionType:
- Scalar-Initializer-ExpressionType
- Compound-ExpressionType
- Duplicated-ExpressionType
Scalar-Initializer-ExpressionType:
- Absolute-ExpressionType
- Constant-ExpressionType
- Immediate-ExpressionType
- Direct-ExpressionType
- Indirect-ExpressionType
- String-ExpressionType
- Floating-Point-ExpressionType
- Type-ExpressionType
Text Preprocessor
The text preprocessor is a functional unit within the assembler that performs the text preprocessing translation phase. During text preprocessing, the following actions are performed:
- Language Elements are recognized.
- Text equates and macros are expanded.
- Macro directives and conditional assembly directives are recognized and processed.
- The preprocessed output is passed on to the assembler for final processing.
This section also describes the various types of preprocessor directives:
Type
|
Function
|
Directives
|
Conditional Assembly
|
Tests for a specified condition and assembles a block of statements if the condition is true.
|
IF IFB IFDEF IFDIFI IFE IFIDN IFNB IFNDEF IF1 IF2 ELSE ENDIF
|
Text Equate
|
Allows assignment of simple text strings to a symbolic name. Provides functions for expanding and operating on the values.
|
CATSTR EQU INSTR SIZESTR SUBSTR
|
Macro
|
Provides text processing that is done sequentially at assembly time. By the end of assembly, ALP expands all macros and assembles the resulting text into object code.
|
ENDM EXITM FOR FORC IRP IRPC LOCAL MACRO PURGE REPEAT REPT
|
Miscellaneous
|
Miscellaneous text processing functions.
|
COMMENT ECHO %OUT INCLUDE
|
Text Operators
- Description
The #Text Preprocessor recognizes certain punctuator characters as text operators. The programmer may use these operators to force the Text Preprocessor to perform various operations such as delineating text, expanding arguments, and converting expressions into their text representations.
- Syntax
Text-Operator:
- Literal-Character-Operator
- Literal-Text-Operator
- Text-Expansion-Operator
- Text-Substitution-Operator
Literal Character Operator (!)
- Syntax
Literal-Character-Operator:
- ! any printable character
- Description
When you use an exclamation point (!) in an operand, ALP treats the next character literally. (!) is typically used to prevent the assembler from recognizing and acting upon special characters such as the semicolon (;) or the ampersand (&), forcing them to appear as normal data characters.
- Constraints
The Literal-Character-Operator has no effect when used inside of a String-Literal.
- Examples
In this example, use of the ! in the second macro argument prevents the assembler from interpreting the rest of the line as a comment:
MACRONAME First, !; NonComment, Third ; Comment
Literal Text Operator (<>)
- Syntax
Literal-Text-Operator:
- < Char-Sequence >
Char-Sequence
- any printable character
- Char-Sequence any printable character
- Description
The literal-text operator directs the assembler to treat Char-Sequence as a single literal element regardless of whether it contains commas, spaces, or other separators. The operator is most often used with macro calls and the FOR directive to ensure that values in a parameter list are treated as a single parameter.
The literal-text operator can also be used to force ALP to treat other special characters such as the semicolon (;) or the ampersand (&) literally. For example, the semicolon inside angle brackets (<>) becomes a semicolon, not a comment indicator.
ALP removes one set of angle brackets each time the parameter is used in a macro. When using nested macros, you will need to supply as many sets of angle brackets as there are levels of nesting. The assembler recognizes nested occurrences of text literals.
- Examples
The following example illustrates how to pass arbitrary text to a macro as a single parameter:
MACRONAME First, <Second Argument>, <Third, <Nested>, Argument>
The macro will receive three separate arguments:
- First
- Second Argument
- Third, <Nested>, Argument
Notice that the outermost set of angle brackets were removed from the second and third arguments.
Text Expansion Operator (%)
- Syntax
Text-Expansion-Operator:
- % 2nd through Nth token on line
- % Text-EquateName
- % Expression
- Description
The % Text-Expansion-Operator has different effects depending upon the context in which it is used. Its primary purpose is convert various sources of information into text literals that may in turn be passed to macros as arguments.
The % Text-Expansion-Operator causes the following types of conversions:
- Line Expansion
When used as the first token on the line, the % operator forces expansion of Text-EquateNames in contexts where they would otherwise be left unexpanded. Text-EquateNames passed as arguments to macros are not automatically expanded; this is one context where the % operator is useful.
- Expansion of a Text Equate Operand
As with Line Expansion, the % operator may be used within the body of a line to expand individual Text-EquateNames. This can be useful when expansion of all Text-EquateNames on the line is not desired.
- Conversion of Numeric Expression to Text
If the Text-Expansion-Operatoris not the first token on the line or immediately followed by a Text-EquateName, then the argument of the % operator is assumed to be an Expression, which is evaluated and converted to the text representation of its value. This is useful when the need arises to pass the text representation of a number to a macro.
- Constraints
When the % Expression form of the expansion operator is used, the Expression must evaluate to an Immediate-ExpressionType.
- Examples
MakErr MACRO X
LB = 0
REPEAT X
LB = LB + 1
MakLib % LB
ENDM ; ; End of REPEAT
ENDM ; ; End of MACRO
MakLib MACRO Y
Err & Y : DB ' Error & Y ' ,0
ENDM
MakErr 3
Err1 : DB ' Error 1 ' ,0
Err2 : DB ' Error 2 ' ,0
Err3 : DB ' Error 3 ' ,0
Text Substitution Operator (&)
- Syntax
Text-Substitution-Operator:
- Macro-ParameterName &
- & Macro-ParameterName
- Description
An ampersand (&) is used in the body of a macro to force the substitution of a Macro-ParameterName with the value of its argument during expansion of the macro.
- Constraints
The assembler does not substitute a Macro-ParameterName that is in a quoted string or not preceded by a delimiter in the expansion unless it is immediately preceded by an ampersand (&).
It is necessary to separate a Macro-ParameterName from other Identifer-Characters with an ampersand (&) before any substitution or paste operations are performed.
- Examples
ErrGen MACRO X
Error &X: push bx
ABX mov BX, "A";
AB &X mp ERROR
ENDM
The statement ErrGen A produces this code:
ErrorA : push bx
ABX mov BX , "A";
ABA jmp ERROR
Preprocessor Tokens
- Syntax
Preprocessing-Token:
- Identifier
- Text-Literal
- FileName
- Comment
- Description
During the text preprocessing translation phase, certain conditions will cause the preprocessor to convert raw #Language Elements (#Tokens) into Preprocessing-Tokens. The act of text preprocessing typically causes Preprocessing-Tokens to either be removed from the input stream or converted back into Tokens before being passed on to the assembler for final processing.
Text Literals
- Syntax
Text-Literal:
- operand of Literal-Character-Operator
- operand of Literal-Text-Operator
- Description
A Text-Literal is a single unit of text that is used by the #Text Preprocessor in many different text handling contexts. In some contexts ( such as the processing of arguments to be passed to a macro), normal language #Tokens are implicitly treated as Text-Literals, provided they are not a delimiter character such as a comma or a blank. In other contexts, it may be necessary to explicitly convert a unit of text to a Text-Literal using the Literal-Text-Operator.
- Constraints
A normal language Token is never implicitly considered to be a Text-Literal if a Text-Literal is explicitly required in the syntax of the construct being parsed.
File Names
- Syntax
FileName:
- FileName-Text
- Text-Literal
FileName-Text:
- FileName-Character
- FileName-Text FileName-Character
FileName-Character:
- any printable character except blank (ASCII 32)
- Description
FileName arguments may be coded as an arbitrary sequence of printable characters, or as a Text-Literal; use the Text-Literal form if the FileName is to contain embedded spaces or other special characters.
If path information is included in the FileName, you can separate the individual directory names with either the back slash (\) or the forward slash (/) and they will be treated identically by the assembler.
- Examples
INCLUDE <inc\macros.inc>
INCLUDELIB os2386.lib
Comments are language elements that have significance only to the programmer and not to the assembler. Comments are effectively removed from the input stream during the text preprocessing phase.
There are two classes of comments recognized by ALP:
- Comments that start with a character sequence and continue to the end of the line (EndOfLine-Comment)
- Comments that start with a character sequence and continue until the occurrence of another character sequence (Block-Comment). See the #COMMENT directive for a description of #Block-Comments.
There are two types of EndOfLine-Comments:
Macro-Comment
Macro-Comments (beginning with two semicolons) do not appear in the listing output even when the .LALL directive is used. Use of Macro-Comments can significantly reduce the amount of memory workspace used by the definition of a macro. As a macro definition is read, Macro-Comments are discarded and not entered into the macro definition, whereas NonMacro-Comments are treated as normal text and are retained.
NonMacro-Comment
NonMacro-Comment (beginning with a single semicolon) are preserved in macro definitions and appear in the listing output during macro expansions.
- Syntax
Comment:
- EndOfLine-Comment
- Block-Comment
EndOfLine-Comment:
- NonMacro-Comment
- Macro-Comment
NonMacro-Comment:
- ; Char-Sequence
Macro-Comment:
- ;; Char-Sequence
Char-Sequence:
- any printable character
- Char-Sequence any printable character
#Block-Comment:
- See the #COMMENT directive
- Description
Comments are language elements that have significance only to the programmer and not to the assembler. Comments are effectively removed from the input stream during the text preprocessing phase.
There are two classes of comments recognized by ALP:
- Comments that start with a character sequence and continue to the end of the line (EndOfLine-Comment)
- Comments that start with a character sequence and continue until the occurrence of another character sequence (Block-Comment). See the #COMMENT directive for a description of #Block-Comments.
There are two types of EndOfLine-Comments:
Macro-Comment
Macro-Comments (beginning with two semicolons) do not appear in the listing output even when the .LALL directive is used. Use of Macro-Comments can significantly reduce the amount of memory workspace used by the definition of a macro. As a macro definition is read, Macro-Comments are discarded and not entered into the macro definition, whereas NonMacro-Comments are treated as normal text and are retained.
NonMacro-Comment
NonMacro-Comment (beginning with a single semicolon) are preserved in macro definitions and appear in the listing output during macro expansions.
- Example
The following are examples of EndOfLine-Comments:
; Comments may be on a line all by themselves. They can be empty ...
;
; They don't have to start in the first column
BumpCount MACRO Amount ; They can appear to the right of statements
Count = Count + Amount ; This appears in macro expansions
$Total = $Total + Amount ;; This does not, discarded during definition
ENDM
Text Arguments
Many preprocessing directives operate on sequences of raw text characters called Text-Arguments. A Text-Argumentmay be specified using any one of several methods:
- Specifying the text directly using a raw Text-Literal.
- Using the Text-Expansion-Operator to convert a numeric expression to its text representation.
- Using a Text-EquateName in those contexts where a Text-Argumentis expected. In this case the preprocessor will automatically resolve the Text-EquateName and use its value as the Text-Argument.
Text-Argument:
- Text-Literal
- % Expression
- Text-EquateName
- Description
Many preprocessing directives operate on sequences of raw text characters called Text-Arguments. A Text-Argumentmay be specified using any one of several methods:
- Specifying the text directly using a raw Text-Literal.
- Using the Text-Expansion-Operator to convert a numeric expression to its text representation.
- Using a Text-EquateName in those contexts where a Text-Argument is expected. In this case the preprocessor will automatically resolve the Text-EquateName and use its value as the Text-Argument.
- Syntax
Text-Argument:
- Text-Literal
- % Expression
- Text-EquateName
Conditional Assembly Directives
At assembly time, ALP evaluates conditional assembly directives, assembling if the conditions are true. You can use conditional assembly directives when you want to test for a specified condition and assemble a block of statements if the condition is true. The #IFxx and #ENDIF directives enclose the statements to be considered for conditional assembly. The optional #ELSEIFxx and #ELSE blocks follow the #IFxx directive. There are many forms of the #IFxx and #ELSEIFxx directives.
This section describes the following conditional assembly directives:
- #IF
- #IFB
- #IFDEF
- #IFDIF
- #IFDIFI
- #IFE
- #IFIDN
- #IFIDNI
- #IFNB
- #IFNDEF
- #IF1
- #IF2
- #ELSE
- #ENDIF
IFxx (Begin Primary Conditional Block)
You can use each IFxxconditional directive with the #ELSExx, #ELSE and #ENDIF directives to provide the statements to be considered for conditional assembly. ALP assembles the statements following the #IFxx directive only if this condition is true.
Syntax
IFxx operand
.
.
.
[ ELSEIFxx ] ( optional )
.
.
.
[ ELSE ] ( optional )
.
.
.
ENDIF
Remarks
The following directives are members of the IFxx family:
- IF
- IFB
- IFDEF
- IFDIF
- IFDIFI
- IFE
- IFIDN
- IFIDNI
- IFNB
- IFNDEF
- IF1
- IF2
You can nest the conditional directives to any level. They are not limited to use within a macro. The assembler must know any operand to a conditional on pass one to avoid errors and incorrect evaluation.
IF (If Expression is True)
IF starts a conditional assembly statement, which is ended by the corresponding #ENDIF conditional assembly directive. Each IF directive must be ended by a matching ENDIF directive.
Syntax
IF Expression
.
.
.
[ ELSEIFxx ] (optional)
.
.
.
[ ELSE ] (optional)
.
.
.
ENDIF
Remarks
If the #IFxx conditional assembly statement is not ended by an #ENDIF directive, an unterminated conditional message is produced by the assembler. An ENDIF without a matching IF causes an error. ENDIF does not have an operand.
Note: The conditional directives can be nested to any level. They are not limited to use within a macro. Any operand to a conditional must be known on pass 1 to avoid errors and incorrect evaluation.
Example
IF debug
EXTERN dump:FAR
EXTERN trace:FAR
EXTERN breakpoint:FAR
ENDIF
IFB (If Argument is Blank)
This is true if #Text-Argument is blank (contains no characters).
- Syntax
IFB Text-Argument
- Remarks
A #Text-Argument must be specified, the contents of which are checked for the presence of characters. An error is generated if a Text-Argument is not supplied.
IFDEF (If Identifier is Defined)
This is true if #Identifier has been defined as a label, variable, or symbol.
- Syntax
IFDEF Identifier
IFDIF (If Arguments Are Different)
This is true if #Text-Argument-1 and Text-Argument-2 are different in a case-sensitive comparison.
- Syntax
IFDIF Text-Argument-1, Text-Argument-2
- Remarks
Both Text-Argument arguments must be specified. An error is generated if a either argument is not supplied.
- Example
In the following example:
IFDIF <EAGLES>,<Eagles>;
value = 1
ENDIF
the condition would be true; the arguments are different because they are compared with a case-sensitive algorithm.
IFDIFI (If Arguments Are Spelled Differently)
This is true if #Text-Argument-1 and Text-Argument-2 are different in a case-insensitive comparison.
- Syntax
IFDIFI Text-Argument-1, Text-Argument-2
- Remarks
Both Text-Argument arguments must be specified. An error is generated if a either argument is not supplied.
- Example
In the following example:
IFDIFI <EAGLES>, <Eagles>
value = 1
ENDIF
the condition would be false; the arguments are not different because they are compared using a case-insensitive algorithm.
IFE (If Expression is Not True)
This is true if expression is 0.
Syntax
IFE Expression
IFIDN (If Arguments Are Identical)
This is true if #Text-Argument-1 and Text-Argument-2 are identical in a case -sensitive comparison.
Syntax
IFIDN Text-Argument - 1, Text-Argument - 2
Remarks
Both Text-Argument arguments must be specified. An error is generated if a either argument is not supplied.
Example
In the following example:
IFIDN <EAGLES>, <Eagles>;
value = 1
ENDIF
the condition would be false; the arguments are not identical because they are compared using a case-insensitive algorithm.
IFIDNI (If Arguments Are Spelled Identically)
This is true if #Text-Argument-1 and Text-Argument-2 are identical in a case -insensitive comparison.
Syntax
IFIDNI Text-Argument - 1, Text-Argument - 2
Remarks
Both Text-Argument arguments must be specified. An error is generated if a either argument is not supplied.
Example
In the following example:
IFIDNI <EAGLES>, <Eagles>
value = 1
ENDIF
the condition would be true; the arguments are identical because they are compared using a case-insensitive algorithm.
IFNB (If Argument is Not Blank)
This is true if Text-Argument is not blank (characters are present).
Syntax
IFNB Text-Argument
Remarks
A Text-Argument must be specified, the contents of which are checked for the presence of characters. An error is generated if a Text-Argument is not supplied.
IFNDEF (If Identifier is Not Defined)
This is true if symbol has not yet been defined as a label, variable, or symbol.
Syntax
IFNDEF symbol
IF1 (If Assembling On Pass 1)
This is true on pass one.
Syntax
IF1
Remarks
IF1 does not have an operand.
IF2 (If Assembling On Pass 2)
This is true on pass two.
Syntax
IF2
Remarks
IF2does not have an operand.
ELSEIFxx/ELSE (Begin Alternate Conditional Block)
Each conditional directive can be used with the ELSE directive to provide the statements to be considered for conditional assembly. The ELSE directive allows the assembly of the statements following it when the #IFxx condition or intervening ELSEIFxx conditions are false.
Syntax
IFxx
.
.
.
[ ELSEIFxx ] ( optional )
.
.
.
[ ELSE ] ( optional )
.
.
.
ENDIF
Remarks
There is a corresponding ELSEIFxx directive to match all forms of the #IFxx family of directives:
For information about the meaning of the conditional tests performed by the ELSEIFxx directives, refer to the definitions for the corresponding #IFxx directives.
Any number of ELSEIFxx blocks may be used within a given IFxx statement. Only one ELSE block is permitted for a given IFxx. A conditional directive with more than one ELSE or an ELSE without a conditional directive causes an error. ELSE does not have an operand.
Note: The conditional directives can be nested to any level. They are not limited to use within a macro. Any operand to a conditional must be known on pass 1 to avoid errors and incorrect evaluation.
Example
IF DEFBUF
BUF DB 100 DUP(0)
ELSE
EXTERN BUF:BYTE
ENDIF
ENDIF (End a Conditional Assembly Statement)
ENDIF ends the conditional assembly statement begun by the corresponding #IFxx conditional assembly directive. Each IFxx directive must be ended by a matching ENDIF directive.
Syntax
IFxx
.
.
.
[ ELSEIFxx ] ( optional )
.
.
.
[ ELSE ] ( optional )
.
.
.
ENDIF
Remarks
If the #IFxx conditional assembly statement is not ended by an ENDIF directive, an unterminated conditional message is produced by the assembler. An ENDIF without a matching IFxx causes an error. ENDIF does not have an operand.
Note: The conditional directives can be nested to any level. They are not limited to use within a macro. Any operand to a conditional must be known on pass 1 to avoid errors and incorrect evaluation.
Example
IF debug
EXTERN dump:FAR
EXTERN trace:FAR
EXTERN breakpoint:FAR
ENDIF
Text Equate Directives
A Text Equate is a symbolic name you give to a series of characters. Text equates are used to expand text within a source statement. The directives described in this section create and manipulate text equates.
EQU
CATSTR
INSTR
SIZESTR
SUBSTR
CATSTR (Concatenate Strings)
CATSTR concatenates a list of text values specified by string into a single text value and assigns it to Name.
Syntax
Name CATSTR string[, string] ...
EQU Directive (Assign Text to a Symbolic Constant)
The EQU directive assigns the contents of a text literal to Name.
Syntax
Name EQU Text - Literal
Remarks
The value of the Text-Literal is assigned to the Name entry. In normal contexts, subsequent references to Name will cause the preprocessor to replace Name with the value specified by the Text-Literal entry. This is a simple text substitution operation.
The Name entry is a globally-scoped Identifier that is converted to a Text-EquateName. The Name cannot have been previously defined as a different Identifier-Type. However, the Name entry can be redefined as many times as desired with different values for the Text-Literal entry.
See also #EQU and #=.
Example
A EQU < BP + > ; explicit text literal, A is a text equate
A EQU < 3 > ; redefinition of A with different value
INSTR (Search In String For Value)
INSTRsearches a specified String for an occurrence of a given Sub-String and assigns its position (1-based) to Name. The search is case sensitive. Startis the position in String to start the search for Sub-String. If Startis not given, it is assumed to be 1 (the start of the string). If Sub-String is not found, the position assigned to Name is 0.
Syntax
Name INSTR [ Start , ] String , Sub-String
Remarks
INSTRassigns the position value to a name as if it were a numeric equate.
Example
pos INSTR < person > , < son >
SIZESTR (Return Size Of String)
Assigns the number of characters given by the Text-Argument to Name.
Syntax
Name SIZESTR Text-Argument
Assigns a substring of Text-Argument starting at Position to the symbol given by Name..
Syntax
Name SUBSTR Text-Argument,Position[,Length]
Remarks
The Position parameter indicates the starting character of the substring to extract from the Text-Argument, and must be 1 or greater. If specified, the Length parameter indicates how many characters are desired, otherwise the remainder of the string is extracted.
Macro Directives
A macro procedure or function, which is comprised of one or more statements.
Macro processing is text processing that is done sequentially at assembly time. By the end of assembly, ALP expands all macros and assembles the resulting text into object code.
This section describes the following types of macros:
- Macro procedures, which expand to one or more complete statements and can optionally take parameters
- Repeat blocks, which generate a group of statements a specified number of times or until a condition becomes true
This section describes the following macro directives:
- ENDM
- EXITM
- FOR/IRP
- FORC/IRPC
- LOCAL
- MACRO
- PURGE
- REPEAT/REPT
ENDM (End Current Macro Definition)
End each #MACRO, #REPEAT/REPT, #FOR/IRP, and #FORC/IRPC directive with the ENDMdirective.
- Syntax
ENDM
- Remarks
If the ENDM directive is not used with the #MACRO, #REPEAT/REPT, #FOR/IRP, and #FORC/IRPC directives, an error occurs. An unmatched ENDM also causes an error.
If the assembler produces an error message stating that it found the end-of -file on the source and cannot find an #END statement when there was an END, the likely cause is a missing ENDM or ENDIF statement. Without ENDM, the assembler treats the rest of the source as part of the #MACRO definition.
Note: The name field is not allowed. Do not confuse the ENDM directive with other ending directives that do require the name of the block being ended, such as ENDP or ENDS.
Example
addup MACRO ad1, ad2, ad3
MOV AX, ad1 ;; first parameter in AX
ADD AX, ad2 ;; add next two parameters
ADD AX, ad3 ;; leave sum in AX
ENDM
EXITM (End Current Macro Expansion)
Use the EXITM directive when a block contains a directive that tests for some condition and you want to end the current macro expansion when the test proves that the remainder of the expansion is not required. When an EXITM directive is run, the expansion is stopped immediately, and any remaining expansion or repetition is not produced.
Syntax
EXITM
- Remarks
Only the block containing the EXITM directive is ended; outer levels of a nested macro expansion continue unaffected.
EXITM is executed at macro expansion time and is not a substitute for the #ENDM directive, which marks the end of the macro body and is recognized at macro definition time.
Example
DSEG SEGMENT
.
.
.
SYM = 0
REPEAT 16
; ; Check for paragraph boundary
IF ( $ - DSEG ) MOD 16 EQ 0
EXITM ; ; quit if padded to boundary
ENDIF
SYM = SYM + 1
DB SYM ; ; produce numbered padding
ENDM
FOR/IRP (Iterative Macro Expansion Using List of Arguments)
The FOR directive, used in combination with the #ENDM directive, designates a block of statements to be repeated, once for each argument in the list enclosed by angle brackets. Each repetition substitutes the next item in the <Argument-List> entry for every occurrence of Parameter in the block.
Syntax
FOR Parameter , < Argument-List >
.
.
.
ENDM
- Remarks
The obsolete spelling for the FOR directive is IRP.
You must enclose the <Argument-List> entry in angle brackets. It has the following format:
< [ Argument [ , Argument . . . ] ] >
If an empty (<>) Argument is found in <Argument-List>, the Parameter name is replaced by a null value. If the argument list is empty, the FORdirective is ignored and no statements are copied. The assembler processes the block once for each Argumentin the <Argument-List>, replacing each occurrence of Parameterin the macro body with the current Argument value.
The #FOR/IRP-#ENDM block does not have to be within a macro definition.
Example
In this example, the assembler produces the code DB1 through DB10.
FOR X , < 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 , 10 >
DB X
ENDM
In the next example:
FOR ARGUMENT , < " first line " , 13 , 10 ,
" second line " , 13 , 10 >
DB ARGUMENT
ENDM
The assembler produces the code:
DB " first line "
DB 13
DB 10
DB " second line "
DB 13
DB 10
FORC/IRPC (Iterative Macro Expansion Using List of Characters)
The assembler repeats the statements in the block once for each character in the string. Each repetition substitutes the next character in the string for every occurrence of Parameterin the block.
Syntax
FORC Parameter , String ( or < String > )
.
.
.
ENDM
Remarks
The obsolete spelling for the FORCdirective is IRPC.
The FORCdirective is similar to the #FOR/IRP directive except that a String is used instead of <Argument-List>, and the angle brackets around the string are optional. The string should be enclosed with angle brackets (<>) if it contains spaces, commas, or other separating characters.
The FORC/IRPC-#ENDM block does not have to be within a macro definition.
Example
In this example, the assembler produces the code DB 1 through DB 8:
FORC X, 12345678
DB X
ENDM
LOCAL (Identify Names Local to a Macro Definition)
The LOCAL directive is used inside the body of a macro definition, and provides a method of automatically generating unique assembler labels each time the macro is expanded. The names appearing in the argument list of the LOCAL directive are known only to the enclosing macro, and each time they are referenced during a macro expansion a unique symbol is created. This prevents the assembler from issuing duplicate definition errors when the macro is expanded more than once and symbols contained therein are being used to create assembler labels.
- Syntax
LOCAL Name [, Name .... ]
- Remarks
The LOCAL directive is recognized only within the body of a macro given by a #MACRO, #FOR/IRP, #FORC/IRPC, or #REPEAT/REPT definition. The symbols created by the preprocessor are of the form ??nnnn, where nnnn is a hexadecimal number in the range 0000 through FFFF. You must avoid using identifiers of this form for your own purposes, because doing so can cause duplicate definition errors.
To insure that they have the proper effect, LOCAL statements should appear in the body of the macro before any other directives are used. It is acceptable for blank lines or comments to precede any LOCAL statements.
You can use multiple LOCAL statements if the argument list is too long to fit on one line, or if you want a vertical list of LOCAL symbols.
- Example
DISPLAY MACRO TT
; Blank lines and comments are ok here
LOCAL AGAIN
;; DOS macro to display message addressed by BX TT times
MOV CX, TT
MOV AH, 9
MOV DX, BX
; Generate a unique label for AGAIN
AGAIN:
INT 21H
LOOP AGAIN
ENDM
MACRO (Assign a Body of Text to a Name)
This directive produces a given sequence of statements from various places in your program, even though different parameters may be required each time you call the sequence.
Macro processing consists of two separate and distinct phases: #Macro Definition and #Macro Expansion.
Macro Definition
A macro definition consists of three essential parts:
- The MACRO directive, defining the Name and the Parameter-List
- The body of the macro, containing the prototypes of statements to produce when you invoke the macro for expansion.
- The #ENDM directive, ending the definition of the macro.
- Syntax
Name MACRO [Parameter [, Parameter ...]]
.
.
.
ENDM
- Remarks
The Name field must be a valid preprocessor identifier and specifies the symbolic name that the user will refer to when invoking the macro for expansion. If Name is already defined, it must be that of a previous macro definition, otherwise an error message is issued. Macros may be redefined to have a different Parameter-Lists or macro body text; doing so causes the previous definition to be lost.
The optional Parameter-List is the complete comma-separated list of all Parameter valuess given in the macro definition statement. A parameter must be a valid symbol name according to the rules for naming preprocessor and assembler identifiers. Each parameter becomes a symbol that is local to the macro being defined and is recognized during macro expansion prior to searching the global name space. Thus, macro parameters need not have names unique from identifiers defined elsewhere in the program.
Macro Expansion
To expand the macro, the macro Name (defined in the Name field of the MACRO definition statement) is coded as you would any other assembler directive, followed by the list of arguments (if any) that you want to pass to the macro.
- Syntax
Name [Argument [, Argument ...]]
- Remarks
The Name field must be the name of a macro defined previously with a MACRO directive.
Each Argument field denotes a text value that you want to pass to the macro. The relative positions of the elements are important, because each Argument is associated in left-to-right fashion with the corresponding Parameter as defined in the Parameter-List during the macro definition.
The number of Argument entries given when the macro is invoked need not be the same as the number of Parameter entries. If you pass extra Arguments to the macro, they are ignored; if too few are supplied, empty text values are associated with the remaining Parameters. You may also associate an empty text value with a Parameter by passing an explicitly empty text literal <> as an Argument.
Commas are normally used to separate arguments, although blanks or tabs are also considered to be argument separators. For this reason, any argument that must contain an argument separator character (commas, blanks, or tabs) should be enclosed in angle brackets <>. For example:
PUSHVEC MACRO PARM1, PARM2
MOV AX, PARM1
PUSH AX
MOV AX, PARM2
PUSH AX
ENDM
.
.
.
PUSHVEC DS, <OFFSET VARNAME>
; PUSH DWORD VECTOR OF VARNAME ONTO STACK
You can also use angle brackets to produce variable lengths of results. For example:
STRING MACRO NUMBERS
DB NUMBERS
ENDM
.
.
.
STRING <1,2,3,4>
; PRODUCE 4 BYTES OF INTEGER NUMBERS
- Remarks
Each time a macro is invoked (expanded) by specifying its name, the preprocessor emits the statements contained in the body of the macro and passes them to the assembler for processing. During the expansion process, any replacement parameters encountered in the macro body (as named in the Parameter-List of the macro definition) are replaced with the corresponding Argument (if any) passed through the argument-list at the time the macro was invoked.
- Example
GEN MACRO XX, YY, ZZ
MOV AX, XX
ADD AX, YY
MOV ZZ, AX
ENDM
When the call is made, for example:
GEN ED, KISER, SUM
The assembler produces the following code:
MOV AX, ED
ADD AX, KISER
MOV SUM, AX
PURGE (Remove Macro Definition)
The PURGE directive deletes the definition of a specified macro entry, letting you reuse space.
- Syntax
PURGE Macro-Name [, ...]
- Remarks
It is not necessary to purge a macro before redefining it. You may use PURGE to recover memory during assembly by deleting the contents of unreferenced macros. An Out of Memory condition can occur if a large, general-purpose macro library is included.
- Example
The directive:
PURGE MACRONAME
performs the same function as redefining the macro with no contents, as in:
MACRONAME MACRO
ENDM
In the following example, assume that MAC1 is a macro included in MACRO.LIB:
INCLUDE MACRO.LIB
PURGE MAC1
MAC1 ; Calls the purged macro
; but produces nothing
REPEAT/REPT (Iterative Macro Expansion Using a Count Expression)
REPEAT specifies the number of times to generate the statements inside the macro.
- Syntax
REPEAT Expression
Statements
ENDM
- Remarks
The Expression field must evaluate to an Absolute-ExpressionType (it cannot contain forward references). Because the repeat block will be expanded at assembler time, the number of iterations must be known then.
ECHO Directive (Display Message on Standard Output Device)
The ECHO directive displays progress through a long assembly or displays the value of conditional assembly parameters.
Syntax
ECHO Text
Remarks
The assembler lists the Text entry on the standard output device during assembly when the assembler encounters the ECHO directive.
ECHO is not available under MASM 5.10 emulation; you must use %OUT, which is the obsolete spelling for the ECHO directive.
Example
Example 1:
IF IBM
ECHO IBM VERSION
ENDIF
IF2
ECHO STARTING SECOND PASS
.
.
.
ENDIF
Example 2:
INNER MACRO TEXT, VAL
ECHO TEXT VAL
ENDM
.
.
.
HERE = $ - CSEG
INNER <CURRENT LOCATION>,%HERE
INCLUDE Directive (Insert File Contents into Input Stream)
The INCLUDE directive "stacks" the current source file and begins reading tokens from the source file given by the FileName argument. If you use the INCLUDE directive, you need not repeat a sequence of statements that are common to several source files.
Syntax
INCLUDE FileName
Remarks
The assembler uses the following search order when attempting to open the INCLUDE file:
- If the FileName argument contains a fully qualified path name (one that begins with a back slash or forward slash), then the assembler attempts to open the file exactly as specified, and no other search is performed if the file is not found.
- If the FileName begins with a relative path name or contains no path information, the assembler begins searching for the INCLUDE file by looking in the directory of the source file that issued the INCLUDE directive.
- The assembler searches for FileName in the list of directories given by any #-Fdi or #-I options found on the command line.
- The assembler searches for FileName in the list of directories given by the <BaseEXE>_INCLUDE environment variable.
- The assembler searches for FileName in the list of directories given by the INCLUDE environment variable.
- Lastly, the assembler searches for FileName in the current directory. If the named file is not found, the assembler issues a fatal error message and the assembler is ended.
In no case does the assembler strip relative path information from the FileName when performing search steps 2 through 6.
When the file named in the INCLUDE directive is located, the assembler opens it and assembles all of the statements contained therein until the end of the file is reached. The file is then closed and assembler resumes in the original module at the line following the INCLUDE directive.
An INCLUDE file should not contain an #END assembler directive to denote the end of the included module; the assembler closes the included module when its physical end of file is reached.
INCLUDE files may be nested to any reasonable level, and is limited only by the operating system's ability to provide the necessary resources.
- Example
INCLUDE OS2.INC
COMMENT lets you enter comments about your program without having to enter semicolons (;) for each line.
- Syntax
COMMENT Delimiter Text Delimiter
- Remarks
The first non-blank character after COMMENT is the first delimiter. The COMMENT directive causes the assembler to treat all Text between Delimiter and Delimiter as a comment. The text must not contain the delimiter character. This directive is used for multiple-line comments. A COMMENT defined in the body of a macro does not appear unless .LALL is requested.
Example
COMMENT *You can enter as many lines
of text between the delimiters
.
.
.
as you need to describe your program.*
Return Codes
When ALP completes, it passes a return code back to the program that invoked it. This return code shows whether ALP completed successfully or with an error.
The return codes are:
- 0 Normal program completion.
- 1 User-specified file not found.
- 2 Unexpected system error.
- 3 Terminated by user or operating system.
- 4 Syntax errors in input file.
- 5 Command line usage error.
- 6 Internal sanity check failure.
- 7 Error accessing ALP messages file.
Notices
October 1997
The following paragraph does not apply to the United Kingdom or any country where such provisions are inconsistent with local law:
INTERNATIONAL BUSINESS MACHINES CORPORATION PROVIDES THIS PUBLICATION "AS IS". WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Some states do not allow disclaimer of express or implied warranties in certain transactions, therefore, this statement may not apply to you.
This publication could include technical inaccuracies or typographical errors. Changes are periodically made to the information herein; these changes will be incorporated in new editions of the publication. IBM may make improvements and/or changes in the product(s) and/or the program(s) described in this publication at any time.
It is possible that this publication may contain reference to, or information about, IBM products (machines and programs), programming, or services that are not announced in your country. Such references or information must not be construed to mean that IBM intends to announce such IBM products, programming, or services in your country.
Requests for technical information about IBM products should be made to your IBM authorized reseller or IBM marketing representative.
(C) Copyright International Business Machines Corporation 1995-1997. All rights reserved. Note to U.S. Government Users -- Documentation related to restricted rights -- Use, duplication or disclosure is subject to restrictions set forth in GSA ADP Schedule Contract with IBM Corp.
The #Processor Reference portion of this manual contains information reprinted with permission from Intel Corporation.
Disclaimers
References in this publication to IBM products, programs, or services do not imply that IBM intends to make these available in all countries in which IBM operates. Any reference to an IBM product, program or service is not intended to state or imply that only IBM's product, program, or service may be used. Any functionally equivalent product, program, or service that does not infringe any of IBM's intellectual property rights or other legally protectable rights may be used instead of the IBM product, program, or service. Evaluation and verification of operation in conjunction with other products, programs, or services, except those expressly designated by IBM, are the user's responsibility.
IBM may have patents or pending patent applications covering subject matter in this document. The furnishing of this document does not give you any license to these patents. You can send license inquiries, in writing, to the IBM Director of Licensing, IBM Corporation, 500 Columbus Avenue, Thornwood NY 10594, U.S.A.
Trademarks
The following terms are trademarks of the IBM Corporation in the United States or other countries:
- IBM
- Operating System/2
- OS/2
- Presentation Manager
The following terms are trademarks of other companies:
- Microsoft - Microsoft Corporation
- Pentium - Intel Corporation Pentium Pro - Intel Corporation
- UNIX - UNIX System Laboratories, Inc.