CHAPTER 8

DATA STRUCTURES.

THE NATURE AND USE OF DATA STRUCTURES:

In order to work with the code for a windows program, it is necessary for the reader to understand the structured organisation of data into what is known as a 'data structure', as data structures are regularly used in the Windows operating system. Since this topic requires a discussion at some length, I have given it a chapter of its own.

We already know that parameters belonging to a Windows API function are pushed onto the stack, and that each parameter is a dword in size. The individual parameters, however, can be of different kinds. An API function might require a set of parameters that include memory addresses, the contents of memory addresses, the contents of registers, numerical values, and even text strings.

Suppose, for example, it was necessary to pass a text string as one of the parameters to an API function! The text string might be much longer than a dword in length and, if this is the case, it cannot be passed as a parameter directly. Instead, the text string is put into a block of memory and the dword address of the start of that memory block is passed to the API function as a dword parameter. In this way, dword parameters can be used as a means of passing parameters of other sizes.

I already mentioned that a program, and the Windows operating system, each do not have straightforward access to the data of the other in memory, in the sense that neither knows how memory is being used by the other. That, however, doesn't mean that neither can be given such information about the other at all. The operating system and a program's code can each inform one another of the address of a particular memory block in their own address space.

In this context, we can naturally encounter the concept of a data structure, because a data structure is a particular, structured use of a memory block, and Windows API functions often use data structures and ask for a data structure address to be passed as a parameter in the same way as the starting address of a text string might be passed as a parameter.

In the above example of the string, only the string starting address (the address of the first string character) is passed as the parameter, and the other string characters are at other memory locations, as offsets from the starting address. Thus, it is possible for an API function parameter to be the starting address of an entire block of memory locations, and not merely one location only.

In the simple case of the text string, only the starting address need have a name. A data structure, however, is a block of memory in which a whole series of memory locations, or addresses, within the memory block, are given names. This is because such a memory block is used to contain a whole series of named parameters, at different locations within it, even though only the starting address of the entire block is actually passed as a parameter to the API function.

Unlike normal parameters, parameters within a data structure don't have to be a dword in size, and can be dwords, words, bytes, or strings of bytes. In addition to this, a data structure can serve as a collection of named parameters that describe one particular

object, like a collection of parameters that describe a bitmap and its dimensions, or a particular font, etc. The parameters within a data structure are identified as offsets from its starting address - hence the concept of a 'structure'.

The Windows API function documentation contains numerous data structures, with each being described in terms of a list of such named internal parameters.

The fact that a named parameter within a data structure is always also an offset from the beginning of the structure brings us naturally to the consideration of the usefulness in data structures of a programming device we have encountered already, that is the 'equate'.

As we already know, an equate is a device whereby the assembler replaces a word or label with a number. Now if, for example, you had a data structure called Name, this being also the starting address of its memory block, and it contained named parameters, or elements, called Element0, Element1, Element2, etc., it would be possible, with the use of equates, to write, for example, Name+Element1, rather than Name+10, as the address of Name1, or Name+Element2 as the address of Element2, and so on, which makes it much easier for the programmer to immediately understand what is the nature of the particular element.

An even more convenient way of achieving the same result, however, is to create equates in which Name.Element1 is Name+10, and similarly with Name.Element2, Name.Element3 etc. The corresponding equates would be written as

Name.Element1 equ Name+10

This kind of notation is most useful in that it indicates both the name of the data structure itself and the particular element named within it. Thus, you could have, for example, a bitmap data structure with elements named BITMAP.X, BITMAP.Y, BITMAP.Width, BITMAP.Height, etc., in which the element names indicate the bitmap structure name to which they belong, which can also be the name of the object they describe.

The above example of an equate incidentally shows that equates can be used with algebraic expressions like Name+10, which is interpreted by the assembler as a number, computed as

Equate number = (Address value) + 10

An example of an actual data structure, for bitmaps, as used by Windows, is as follows:

DATA STRUCTURE MACROS:

The foregoing data structure, like all those used in this text, is constructed by means of macros. Strct and el are macros that work together as follows:

The macro Strct creates a memory block called BITMAPINFO, with a size (428h) that is the total of the sizes of all the elements listed. The macro el uses an equate to set up an element of the macro so that the name of the element is the equivalent of a normal memory address name. Thus, BITMAPINFO is the memory address of the start of the data structure, and the macro el sets up an element, BITMAPINFO.BitCount, for example, as a memory address, by using the equate

BITMAPINFO.BitCount equ BITMAPINFO+0eh

Thus, BITMAPINFO+(the number in the first column of numbers to the right of it) is the address of a data structure element. Each number in the second column of numbers is the third parameter of the macro el, but it is not actually used in the macro code, and is there only as a convenience, in order to remind the programmer, if rereading the code, what is the size of the particular element of the data structure. BITMAPINFO.Rect.Width, for example, is given a dword size, or 4 bytes, at an offset of 4 bytes

from the start of the structure, so that the next element (BITMAPINFO.Rect.Height), must be given an offset of 4+4 = 8. BITMAPINFO.Rect.Height is a dword in size, so that BITMAPINFO.ColourPlanes, the next element, must have 8+4 = 0ch as its offset from the start of the data structure.

BITMAPINFO.ColourPlanes is only a word or two bytes in size so that the next element, BITMAPINFO.BitCount, must have an offset of 0ch+2 = 0eh from the start of the data structure. And so on for the other elements.

Note that the values here are written as hexadecimal numbers, but you could write them as decimal numbers if you wanted to.

Thus, in the design of a data structure, as implemented by the macros, the original Strct macro actually sets up, or declares, the whole memory block, and the el macros merely give names to addresses within the memory block by means of equates.

end.strct is a macro which terminates the data structure, and has to do with clearing the macro context stack.

                  Part I: Part I Introduction
                  Chapter 1: Binary numbers, code, and procedures
                  Chapter 3: Assembly Language
                  Chapter 4: Assembly Language Code example
                  Chapter 5: Macros and HLA
                  Chapter 6: HLA code example
                  Chapter 7: The Windows operating system
                  Chapter 8: Data Structures
                  Chapter 9: How to Create a Windows Program
                  Chapter 10: How to Create an Exe File
                  Chapter 11: Structured Programming and OOP
                  Part II: Part II Introduction
                  Chapter 12: Debugging a Windows Program Code
                  Chapter 13: Painting the Window Client Area
                  Chapter 14: Creating Window Menus
                  Chapter 15: How to Create Toolbars
                  Chapter 16: How to Create Popup Menus
                  Chapter 17: About the Windows Clipboard
                  Chapter 18: How to Create Bitmaps
                  Chapter 19: Icons and the Ico Format
                  Chapter 20: Common Dialog Boxes
                  Chapter 21: Working with Files
                  Chapter 22: Scrollbars and Scrolling
                  Chapter 23: How to Send Data to the Printer
                  Chapter 24: Miscellaneous Topics

© Alen, June 2014
alen@alenspage.net


Material on this page may be reproduced
for personal use only.