2.3 The Anatomy of an HLA Program
An HLA program typically takes the following form:
Figure 2.1 Basic HLA Program Layout
The pgmID in the template above is a user-defined program identifier. You must pick an appropriate, descriptive, name for your program. In particular, pgmID would be a horrible choice for any real program. If you are writing programs as part of a course assignment, your instructor will probably give you the name to use for your main program. If you are writing your own HLA program, you will have to choose this name.
Identifiers in HLA are very similar to identifiers in most high level languages. HLA identifiers may begin with an underscore or an alphabetic character, and may be followed by zero or more alphanumeric or underscore characters. HLA's identifiers are case neutral. This means that the identifiers are case sensitive insofar as you must always spell an identifier exactly the same way in your program (even with respect to upper and lower case). However, unlike other case sensitive languages, like C/C++, you may not declare two identifiers in the program whose name differs only by the case of alphabetic characters appearing in an identifier. Case neutrality enforces the good programming style of always spelling your names exactly the same way (with respect to case) and never declaring two identifiers whose only difference is the case of certain alphabetic characters.
A traditional first program people write, popularized by K&R's "The C Programming Language" is the "Hello World" program. This program makes an excellent concrete example for someone who is learning a new language. Here's what the "Hello World" program looks like in HLA:program helloWorld; #include( "stdlib.hhf" ); begin helloWorld; stdout.put( "Hello, World of Assembly Language", nl ); end helloWorld; Program 2.1 The Hello World Program
The #include statement in this program tells the HLA compiler to include a set of declarations from the stdlib.hhf (standard library, HLA Header File). Among other things, this file contains the declaration of the stdout.put code that this program uses.
The stdout.put statement is the "print" statement for the HLA language. You use it to write data to the standard output device (generally the console). To anyone familiar with I/O statements in a high level language, it should be obvious that this statement prints the phrase "Hello, World of Assembly Language". The nl appearing at the end of this statement is a constant, also defined in "stdlib.hhf", that corresponds to the newline sequence.
Note that semicolons follow the program, BEGIN, stdout.put, and END statements1. Technically speaking, a semicolon is not necessary after the #INCLUDE statement. It is possible to create include files that generate an error if a semicolon follows the #INCLUDE statement, so you may want to get in the habit of not putting a semicolon here (note, however, that the HLA standard library include files always allow a semicolon after the corresponding #INCLUDE statement).
The #INCLUDE is your first introduction to HLA declarations. The #INCLUDE itself isn't actually a declaration, but it does tell the HLA compiler to substitute the file "stdlib.hhf" in place of the #INCLUDE directive, thus inserting several declarations at this point in your program. Most HLA programs you will write will need to include at least some of the HLA Standard Library header files ("stdlib.hhf" actually includes all the standard library definitions into your program; for more efficient compiles, you might want to be more selective about which files you include. You will see how to do this in a later chapter).
Compiling this program produces a console application. Running this program in a command window prints the specified string and then control returns back to the command line interpreter (or shell in Unix terminology).
Note that HLA is a free-format language. Therefore, you may split statement across multiple lines (just like high level languages) if this helps to make your programs more readable. For example, the stdout.put statement in the HelloWorld program could also be written as follows:stdout.put ( "Hello, World of Assembly Language", nl );
Another item worth noting, since you'll see it cropping up in example code throughout this text, is that HLA automatically concatenates any adjacent string constants it finds in your source file. Therefore, the statement above is also equivalent to:stdout.put ( "Hello, " "World of Assembly Language", nl );
Indeed, "nl" (the newline) is really nothing more than a string constant, so (technically) the comma between the nl and the preceding string isn't necessary. You'll often see the above written as:stdout.put( "Hello, World of Assembly Language" nl );
Notice the lack of a comma between the string constant and nl; this turns out to be perfectly legal in HLA, though it only applies to certain symbol string constants; you may not, in general, drop the comma. The chapter on Strings, later in this text, will explain in detail how this works. This discussion appears here because you'll probably see this "trick" employed by sample code prior to the formal discussion in the chapter on Strings.
2.4 Some Basic HLA Data Declarations
HLA provides a wide variety of constant, type, and data declaration statements. Later chapters will cover the declaration section in more detail but it's important to know how to declare a few simple variables in an HLA program.
HLA predefines three different signed integer types: int8, int16, and int32, corresponding to eight-bit (one byte) signed integers, 16-bit (two byte) signed integers, and 32-bit (four byte) signed integers respectively2. Typical variable declarations occur in the HLA static variable section. A typical set of variable declarations takes the following form
Figure 2.2 Static Variable Declarations
Those who are familiar with the Pascal language should be comfortable with this declaration syntax. This example demonstrates how to declare three separate integers, i8, i16, and i32. Of course, in a real program you should use variable names that are a little more descriptive. While names like "i8" and "i32" describe the type of the object, they do not describe it's purpose. Variable names should describe the purpose of the object.
In the STATIC declaration section, you can also give a variable an initial value that the operating system will assign to the variable when it loads the program into memory. The following figure demonstrates the syntax for this:
Figure 2.3 Static Variable Initialization
It is important to realize that the expression following the assignment operator (":=") must be a constant expression. You cannot assign the values of other variables within a STATIC variable declaration.
Those familiar with other high level languages (especially Pascal) should note that you may only declare one variable per statement. That is, HLA does not allow a comma delimited list of variable names followed by a colon and a type identifier. Each variable declaration consists of a single identifier, a colon, a type ID, and a semicolon.
Here is a simple HLA program that demonstrates the use of variables within an HLA program:Program DemoVars; #include( "stdlib.hhf" ); static InitDemo: int32 := 5; NotInitialized: int32; begin DemoVars; // Display the value of the pre-initialized variable: stdout.put( "InitDemo's value is ", InitDemo, nl ); // Input an integer value from the user and display that value: stdout.put( "Enter an integer value: " ); stdin.get( NotInitialized ); stdout.put( "You entered: ", NotInitialized, nl ); end DemoVars; Program 2.2 Variable Declaration and Use
In addition to STATIC variable declarations, this example introduces three new concepts. First, the stdout.put statement allows multiple parameters. If you specify an integer value, stdout.put will convert that value to the string representation of that integer's value on output. The second new feature this sample program introduces is the stdin.get statement. This statement reads a value from the standard input device (usually the keyboard), converts the value to an integer, and stores the integer value into the NotInitialized variable. Finally, this program also introduces the syntax for (one form of) HLA comments. The HLA compiler ignores all text from the "//" sequence to the end of the current line. Those familiar with C++ and Delphi should recognize these comments.
2.5 Boolean Values
HLA and the HLA Standard Library provides limited support for boolean objects. You can declare boolean variables, use boolean literal constants, use boolean variables in boolean expressions (e.g., in an IF statement), and you can print the values of boolean variables.
Boolean literal constants consist of the two predefined identifiers true and false . Internally, HLA represents the value true using the numeric value one; HLA represents false using the value zero. Most programs treat zero as false and anything else as true, so HLA's representations for true and false should prove sufficient.
To declare a boolean variable, you use the boolean data type. HLA uses a single byte (the least amount of memory it can allocate) to represent boolean values. The following example demonstrates some typical declarations:static BoolVar: boolean; HasClass: boolean := false; IsClear: boolean := true;
As you can see in this example, you may declare initialized as well as uninitialized variables.
Since boolean variables are byte objects, you can manipulate them using eight-bit registers and any instructions that operate directly on eight-bit values. Furthermore, as long as you ensure that your boolean variables only contain zero and one (for false and true, respectively), you can use the 80x86 AND, OR, XOR, and NOT instructions to manipulate these boolean values (we'll describe these instructions a little later).
You can print boolean values by making a call to the stdout.put routine, e.g.,stdout.put( BoolVar )
This routine prints the text "true" or "false" depending upon the value of the boolean parameter ( zero is false, anything else is true). Note that the HLA Standard Library does not allow you to read boolean values via stdin.get.
2.6 Character Values
HLA lets you declare one-byte ASCII character objects using the char data type. You may initialize character variables with a literal character value by surrounding the character with a pair of apostrophes. The following example demonstrates how to declare and initialize character variables in HLA:static c: char; LetterA: char := `A';
You can print character variables using the stdout.put routine. We'll return to the subject of character constants a little later.
1Technically, from a language design point of view, these are not all statements. However, this chapter will not make that distinction.
2A discussion of bits and bytes will appear in the next chapter if you are unfamiliar with these terms.