Assembly Language Style Guidelines - Program Organization


2.0 Program Organization

A source program generally consists of one or more source, object, and library files. As a project gets larger and the number of files increases, it becomes difficult to keep track of the files in a project. This is especially true if a number of different projects share a common set of source modules. This section will address these concerns.

2.1 Library Functions

A library, by its very nature, suggests stability. Ignoring the possibility of software defects, one would rarely expect the number or function of routines in a library to vary from project to project. A good example is the "UCR Standard Library for 80x86 Assembly Language Programmers." One would expect "printf" to behave identically in two different programs that use the Standard Library. Contrast this against two programs, each of which implement their own version of printf. One could not reasonably assume both programs have identical implementations[8]. This leads to the following rule:

Rule:
Library functions are those routines intended for common reuse in many different assembly language programs. All assembly language (callable) libraries on a system should exist as ".lib" files and should appear in the "/lib" or "/asmlib" subdirectory.
Guideline:
"/asmlib" is probably a better choice if you're using multiple languages since those other languages may need to put files in a "/lib" directory.
Exception:
It's probably reasonable to leave the UCR Standard Library's "stdlib.lib" file in the "/stdlib/lib" directory since most people expect it there.

The rule above ensures that the library files are all in one location so they are easy to find, modify, and review. By putting all your library modules into a single directory, you avoid configuration management problems such as having outdated versions of a library linking with one program and up-to-date versions linking with other programs.

2.2 Common Object Modules

This document defines a library as a collection of object modules that have wide application in many different programs. The UCR Standard Library is a typical example of a library. Some object modules are not so general purpose, but still find application in two or more different programs. Two major configuration management problems exist in this situation: (1) making sure the ".obj" file is up-to-date when linking it with a program; (2) Knowing which modules use the module so one can verify that changes to the module won't break existing code.

The following rules takes care of case one:

Rule:
If two different program share an object module, then the associated source, object, and makefiles for that module should appear in a subdirectory that is specific to that module (i.e., no other files in the subdirectory). The subdirectory name should be the same as the module name. If possible, you should create a set of link/alias/shortcuts to this subdirectory and place these links in the main directory of each of the projects that utilize the module. If links are not possible, you should place the module's subdirectory in the "/common" subdirectory.
Enforced Rule:
Every subdirectory containing one or more modules should have a make file that will automatically generate the appropriate, up-to-date, ".obj" files. An individual, a batch file, or another make file should be able to automatically generate new object modules (if necessary) by simply executing the make program.
Guideline:
Use Microsoft's nmake program. At the very least, use nmake acceptable syntax in your makefiles.

The other problem, noting which projects use a given module is much more difficult. The obvious solution, commenting the source code associated with the module to tell the reader which programs use the module, is impractical. Maintaining these comments is too error-prone and the comments will quickly get out of phase and be worse than useless -- they would be incorrect. A better solution is to create a dummy file using the module's name with a ".elw" (elsewhere) suffix and placing this file in the main subdirectory of each program that links the module. Now, using one of the venerable "whereis" programs, you can easily locate all projects that use the module.

Guideline:
If a project uses a module that is not local to the project's subdirectory, create a dummy file (using "TOUCH" or a comparable program) that uses the module's main name with a ".elw" suffix. This will allow someone to easily search for all the projects that use a common object module by using a "whereis" program.

2.3 Local Modules

Local modules are those that a single program/project uses. Typically, the source and object code for each module appears in the same directory as the other files associated with the project. This is a reasonable arrangement until the number of files increases to the point that it is difficult to find a file in a directory listing. At that point, most programmers begin reorganizing their directory by creating subdirectories to hold many of these source modules. However, the placement, name, and contents of these new subdirectories can have a big impact on the overall readability of the program. This section will address these issues.

The first issue to consider is the contents of these new subdirectories. Since programmers rummaging through this project in the future will need to easily locate source files in a project, it is important that you organize these new subdirectories so that it is easy to find the source files you are moving into them. The best organization is to put each source module (or a small group of strongly related modules) into its own subdirectory. The subdirectory should bear the name of the source module minus its suffix (or the main module if there is more than one present in the subdirectory). If you place two or more source files in the same directory, ensure this set of source files forms a cohesive set (meaning the source files contain code that solve a single problem). A discussion of cohesiveness appears later in this document.

Rule:
If a project directory contains too many files, try to move some of the modules to subdirectories within the project directory; give the subdirectory the same name as the source file without the suffix. This will nearly reduce the number of files in half. If this reduction is insufficient, try categorizing the source modules (e.g., FileIO, Graphics, Rendering, and Sound) and move these modules to a subdirectory bearing the name of the category.
Enforced Rule:
Each new subdirectory you create should have its own make file that will automatically assemble all source modules within that subdirectory, as appropriate.
Enforced Rule:
Any new subdirectories you create for these source modules should appear within the directory containing the project. The only excepts are those modules that are, or you anticipate, sharing with other projects. See "Common Object Modules" on page 13 for more details.

Stand-alone assembly language programs generally contain a "main" procedure - the first program unit that executes when the operating system loads the program into memory. For any programmer new to a project, this procedure is the anchor where one first begins reading the code and the point where the reader will continually refer. Therefore, the reader should be able to easily locate this source file. The following rule helps ensure this is the case:

Rule:
The source module containing the main program should have the same name as the executable (obviously the suffix will be different). For example, if the "Simulate 886" program's executable name is "Sim886.exe" then you should find the main program in the "Sim886.asm" source file.

Finding the souce file that contains the main program is one thing. Finding the main program itself can be almost as hard. Assembly language lets you give the main program any name you want. However, to make the main procedure easy to find (both in the source code and at the O/S level), you should actually name this program "main". See "Module Organization" on page 15 for more details about the placement of the main program.

Rule:
The name of the main procedure in an assembly language program should be "main".

2.4 Program Make Files

Every project, even if it contains only a single source module, should have an associated make file. If someone want to assemble your program, they should have to worry about what program (e.g., MASM) to use, what command line options to use, what library modules to use, etc. They should be able to type "nmake"[9] and wind up with an executable program. Even if assembling the program consists of nothing more than typing the name of the assembler and the source file, you should still have a make file. Someone else may not realize that's all that is necessary.

Enforced Rule:
The main project directory should contain a make file that will automatically generate an executable (or other expected object module) in response to a simple make/nmake command.
Rule:
If your project uses object modules that are not in the same subdirectory as the main program's module, you should test the ".obj" files for those modules and execute the corresponding make files in their directories if the object code is out of date. You can assume that library files are up to date.
Guideline:
Avoid using fancy "make" features. Most programmers only learn the basics about make and will not be able to understand what your make file is doing if you fully exploit the make language. Especially avoid the use of default rules since this can create havoc if someone arbitrarily adds or removes files from the directory containing the make file.

  Return to Assembly Language Style Guidelines Index.

  Formatting assembly code with strange coding style?  Use SourceFormatX Asm Formatter to indent all asm code files for your team!