You can declare an array in two ways: you can specify a list of array elements, or you can use the DUP operator to specify a group of identical elements.
To declare an array, you must supply a label name, a type, and a series of elements separated by commas. You can access each element of an array relative to the first. In the examples below, warray and xarray are arrays.
warray WORD 1, 2, 3, 4
xarray DWORD OFFFh, OAAAh
The assembler stores the elements consecutively in memory, with the first address referenced by the label name.
Summary: Initializer lists can be longer than one line.
Beginning with MASM 6.0, initializer lists of array declarations can span multiple lines. The first initializer must appear on the same line as the data type, all entries must be initialized, and, if you want the array to continue to the new line, the line must end with a comma. These examples show legal multiple-line array declarations:
big BYTE 21, 22, 23, 24, 25,
26, 27, 28
somelist WORD 10,
20,
30
If you do not want to use the new LENGTHOF and SIZEOF operators discussed later in this section, then an array may span more than one logical line, although a separate type declaration is needed on each logical line:
var1 BTYE 10, 20, 30
BYTE 40, 50, 60
BYTE 70, 80, 90
The DUP Operator
You can also declare an array with the DUP operator. This operator can be used with any of the data allocation directives described in Section 4.1.1. In the syntax
count DUP (initialvalue[[,initialvalue]]...)
the count value sets the number of times to repeat the last initialvalue. Each initial value is evaluated only once and can be any expression that evaluates to an integer value, a character constant, or another DUP operator. The initial value (or values) must always be placed within parentheses. For example, the statement
barray BYTE 5 DUP (1)
allocates the integer 1 five times for a total of five bytes.
The following examples show various ways to use the DUP operator to allocate data elements.
array DWORD 10 DUP (1) ; 10 doublewords
; initialized to 1
buffer BYTE 256 DUP (?) ; 256-byte buffer
masks BYTE 20 DUP (040h, 020h, 04h, 02h) ; 80-byte buffer
; with bit masks
three_d DWORD 5 DUP (5 DUP (5 DUP (0))) ; 125 doublewords
; initialized to 0
Referencing Arrays
Once an array is defined, you can refer to its first element by typing the array name (no brackets required). The array name refers to the first object of the given type in the list of initial values.
If warray has been defined as
warray WORD 2, 4, 6, 8, 10
then referencing warray in your program refers to the first word—the word containing 2.
To refer to the next element (in an array of words), use either of these two forms, each of which refers to the array element two bytes past the beginning of warray:
warray+2
warray[2]
This element can be used as you would any data item:
mov ax, warray[2]
push warray+2
When used with a variable name, brackets only add a number to the address. If warray refers to the address 2400h, then warray[2] refers to the address 2402h. The BOUND instruction (80186–80486 only) can be used to verify that an index value is within the bounds of an array.
Summary: Array indexes are not scaled. The index is a distance in bytes.
In assembly language, array indexes are zero-based and unscaled. The number within brackets always represents an absolute distance in bytes. In practical terms, the fact that indexes are unscaled means that if an element is larger than one byte, you must multiply the index of the element by its size (in the example above, 2), and then add the result to the address of the array. Thus, the expression warray[4] represents the third element, which is four bytes past the beginning of the array. Similarly, the expression warray[6] represents the fourth element.
You can also determine an index at run time:
mov si, cx ; CX holds index value
shl si, 7 ; Scale for word referencing
mov ax, warray[si] ; Move element into AX
The offset required to access an array element can be calculated with the following formula:
nth element of array = array[(n-1) * size of element]
LENGTHOF, SIZEOF, and TYPE for Arrays
When applied to arrays, the LENGTHOF, SIZEOF, and TYPE operators return information about the length and size of the array and about the type of the initializers.
The LENGTHOF operator returns the number of items in the definition. It can be applied only to an integer label. This is useful for determining the number of elements you need to process in an array of integers. For an array or string label, SIZEOF returns the number of bytes used by the initializers in the definition. TYPE returns the size of the elements of the array. These examples illustrate these operators:
array WORD 40 DUP (5)
larray EQU LENGTHOF array ; 40 elements
sarray EQU SIZEOF array ; 80 bytes
tarray EQU TYPE array ; 2 bytes per element
num DWORD 4, 5, 6, 7,
8, 9, 10, 11
lnum EQU LENGTHOF num ; 8 elements
snum EQU SIZEOF num ; 32 bytes
tnum EQU TYPE num ; 4 bytes per element
warray WORD 40 DUP (40 DUP (5))
len EQU LENGTHOF warray ; 1600 elements
siz EQU SIZEOF warray ; 3200 bytes
typ EQU TYPE warray ; 2 bytes per element