Defining and Using Complex Data Types

The following is based on the Programmer's Guide, Microoft MASM, 1992, Microsoft Corporation.

Arrays and Strings

An array is a sequential collection of related, homogenous data types stored at sequential addresses. A string is an array of chracters (or bytes) and usually uses a NULL terminator, showing the end of the data in the string.
warrayWORD1, 2, 3, 4; declares a four-element array of 16-bit values
dwarrayDWORD0FFFFFFFFh, 789ABCDEh; declares a two-element array of 32-bit values
myStringdb"Hello, World!",0; declares a null-terminated string

Since these are sequential declarations, they would appear in memory as collection of bytes arranged in the following order (assuming the data is stored starting at address 0000H):

Value At Each Byte0100020003000400 FFFFFFFFDEBC9A78 'H''e''l''l''o'','' ''W' 'o''r''l''d''!'00
Address Of Each Byte 0 1 2 3 4 5 6 7 8 9 A B C D E F 1011121314151617 18191A1B1C1D

VariableAddressC NotationAssembly Notation
warray00warray[ 0 ]warray
02warray[ 1 ]warray + 2
04warray[ 2 ]warray + 4
06warray[ 3 ]warray + 6
dwarray08dwarray[ 0 ]dwarray
0Cdwarray[ 1 ]dwarray + 4
myString10myString[ 0 ]myString
12myString[ 1 ]myString + 1
13myString[ 2 ]myString + 2
14myString[ 3 ]myString + 3
15myString[ 4 ]myString + 4
16myString[ 5 ]myString + 5
17myString[ 6 ]myString + 6
18myString[ 7 ]myString + 7
19myString[ 8 ]myString + 8
1AmyString[ 9 ]myString + 9
1BmyString[ 10 ]myString + 0AH
1CmyString[ 11 ]myString + 0BH
1DmyString[ 12 ]myString + 0CH

NOTE: Notice that the word and double word values are stored in little-endian order. The characters are one-byte units and stored as given.

Initializing Arrays

You can initialize an array with values:
array1   dd   1, 2, 3, 4, 5       ; This declares and initializes a 5-element array with the 
                                  ; values 1, 2, 3, 4 and 5
array2   dd   5 dup ( 0 )         ; This declares and initializes a 5-element array with zeroes.
array3   dd   5 dup( ? )          ; This declares a 5-element array but does not initialize it.

Structures

A structure is a group of possibly dissimilar data types and variables that can be accessed as a unit or by any of its components. The fields within the structure can have different sizes and data types. Each field in a structure has an offset relative to the first byte of the structure.

Examples

The Windows API makes extensive use of structures. The following is one example of the declaration and usage.

Follow these steps when using structures:

  1. Declare a structure type
  2. Define one or more variables having that type
  3. Reference the fields directly or indirectly with the filed (dot) operator

The fields are declared and initialized in exactly the same manner as simple variables are. Structures can be nested inside other structures.

Example From windows.inc

WNDCLASSEX STRUCT
  cbSize            DWORD      ?
  style             DWORD      ?
  lpfnWndProc       DWORD      ?
  cbClsExtra        DWORD      ?
  cbWndExtra        DWORD      ?
  hInstance         DWORD      ?
  hIcon             DWORD      ?
  hCursor           DWORD      ?
  hbrBackground     DWORD      ?
  lpszMenuName      DWORD      ?
  lpszClassName     DWORD      ?
  hIconSm           DWORD      ?
WNDCLASSEX ENDS

Example Of Usage From generic.asm

WinMain proc hInst     :DWORD,
             hPrevInst :DWORD,
             CmdLine   :DWORD,
             CmdShow   :DWORD

        ;====================
        ; Put LOCALs on stack
        ;====================

        LOCAL wc   :WNDCLASSEX
        LOCAL msg  :MSG

        LOCAL Wwd  :DWORD
        LOCAL Wht  :DWORD
        LOCAL Wtx  :DWORD
        LOCAL Wty  :DWORD

        szText szClassName,"Generic_Class"

        ;==================================================
        ; Fill WNDCLASSEX structure with required variables
        ;==================================================

        mov wc.cbSize,         sizeof WNDCLASSEX
        mov wc.style,          CS_HREDRAW or CS_VREDRAW \
                               or CS_BYTEALIGNWINDOW
        mov wc.lpfnWndProc,    offset WndProc      ; address of WndProc
        mov wc.cbClsExtra,     NULL
        mov wc.cbWndExtra,     NULL
        m2m wc.hInstance,      hInst               ; instance handle
        mov wc.hbrBackground,  COLOR_BTNFACE+1     ; system color
        mov wc.lpszMenuName,   NULL
        mov wc.lpszClassName,  offset szClassName  ; window class name
		
        invoke LoadIcon,hInst,500    ; icon ID   ; resource icon
		
        mov wc.hIcon,          eax
		
        invoke LoadCursor,NULL,IDC_ARROW         ; system cursor
		
        mov wc.hCursor,        eax
        mov wc.hIconSm,        0

        invoke RegisterClassEx, ADDR wc     ; register the window class

Records

Records are similar to structures, except that field in records are bit strings. Each bit field in a record variable can be used separately in constant operations or expressions. The processor cannot access bits individually at run time, but it can access bit field with instructions that manipulate bits.

Records are bytes, words, or doublewords in which the individual bits or groups of bits are considered fields. In general, the three steps for using record variables are the same as those for using other complex data types:

  1. Declare a record type
  2. Define one or more variables have the record type
  3. Reference variables using shifts and masks.

The fields are given a size in number of bits. Once it is defined, you can use the record variable as an operand in assembler statements. The WIDTH operator (used only with records) returns the width in bits of a record or record field. The MASK operator reutrns a bit mask for the bit positions occupied by the given record field. A bit in the mask contains a 1 if that bit corresponds to a bit field. Bits are initialized by putting the values for each field inside the < and > symbols.

Record Layout

Example

 
  .DATA    
COLOR RECORD blink:1, back:3, intense:1, fore:3  
message COLOR <1, 5, 1, 1>  
wblink EQU WIDTH blink ;"wblink" = 1
wback EQU WIDTH back ;"wback" = 3
wintens EQU WIDTH intense ;"wintens" = 1
wfore EQU WIDTH fore ;"wfore" ; = 3
wcolor EQU WIDTH COLOR ;"wcolor" = 8
       
  .CODE    
  mov ah, message ;load initial          1101 1001
  and ah, NOT MASK back ;Turn off    AND 1000 1111
      ;"back"           --------------
      ;                          1000 1001
  or ah, MASK blink ;Turn on        OR 1000 0000
      ;"blink"            --------------
      ;                          1000 1001
  xor ah, MASK intense ;Turn off     XOR 0000 1000
      ;"intense"         --------------
      ;                          1000 0001