Linked by Thom Holwerda on Thu 30th Jun 2005 12:26 UTC
General Development For Linux users, HLA is a strong programming tool that allows them to create powerful programs on a variety of different levels. As HLA becomes more feature-rich, additional applications will be written using HLA under Linux. With HLA and Linux, programmers can develop new and exciting applications anyone can use. Read more.
Permalink for comment
To read all comments associated with this story, please click here.
Re: Side Effects?
by Randall Hyde on Fri 1st Jul 2005 16:29 UTC

Nimble asked:>>>>>>>>>>>
How does it deal with side effects of library function calls and higher-level control constructs, e.g. modified registers and flags? Don't they confuse students?
<<<<<<<<<<<<<<<<<&l t;<<<<<<
Let's separate the discussion of library function calls and HLL-like control constructs, as the answers are completely different.

For control structures, HLA adopts a very simple policy, with few exceptions (noted below), HLA does not modify any general-purpose registers. Changing register values behind one's back would be confusing for experienced assembly programmers just as it would for beginners. That's pretty much a no-no.

To achieve this, HLA *does* place some restrictions on the type of boolean expressions one can have in a control structure like IF or WHILE. In particular, when you have an statement like:

if( eax = ebx ) then ... endif;

the components of the expression must contain items that are compatible as operands to the x86 CMP instruction. That is, "xxx = yyy" requires that CMP( xxx, yyy); must be a legal x86 instruction. This means, of course, that you cannot compare the values of two memory locations (and a few other, minor, restrictions), but the end result is that you don't wind up modifying any general purpose registers. Of course, the *flags* do get tweaked, but this is an expected by-product of a comparison operation.

Yes, beginners have to learn what's allowed and what's not allowed in boolean expressions in a control structure. But this is a *GOOD THING*. Because they need to learn these same restrictions as they apply to most native x86 instructions like CMP, ADD, AND, OR, and so on. Later, when they progress beyond using HLL-like control structures, they will be used to the fact that you can't do memory to memory operations (and when they learn about the actual machine instructions, they will learn *why* those restrictions exist).

As for standard library calls, most HLA Standard Library routines preserve all registers unless they actually return some value in a register.

A beginner *can* get into some problems if they're not paying attention. Consider the following HLA statement:

if( str.eq( string1, string2 ) ) then
.
.
.
endif;

str.eq is an HLA standard library routine that compares the two strings you pass it as parameters and returns true or false in the EAX register, depending on the outcome of the comparison (equal or not equal). In the IF statement, HLA substitutes "EAX" for the str.eq procedure call (an activity in HLA known as "instruction composition"). It *is* easy to forget that str.eq returns a value in EAX and, therefore, wipes out the EAX register. This fact is not immediately obvious to someone quickly reading this code. However, the return values (and side effects) of the HLA Standard Library routines *are* documented, so you cannot blame this issue on HLA or the standard library. The same problem would exist if the user wrote their own procedure and used it in this manner.

One of the two places where HLA will change a register (actually two) behind your back is in a call to an object's method. Whenever you invoke an object's method, HLA loads ESI with the address of the object and EDI with the address of the object's virtual method table. Again, this behavior is documented in the HLA documentation, so it shouldn't come as a suprise to anyone using objects in HLA (and, to address the "beginners" portion of your comment, most beginners aren't doing object-oriented programming in assembly language anyway, so this issue generally doesn't apply to beginners).

The other place where HLA will change a register behind your back (at least, by default) is in the code that HLA automatically generates for entry into and exit from a procedure. HLA, by default (you can turn this off easy enough), will emit the code to push EBP and set up the activation record for the procedure. Likewise, HLA emits code to clean up the stack upon exiting the procedure. Beyond being a major convenience (because HLA pretty much emits the same code an advanced programmer would use with most procedures), this also allows beginning programmers to write simple procedures and access things like parameters and local (automatic) variables without having to know about activation records and constructing stack frames. Obviously, those students need to learn this information before completing their assembly education, but by having HLA emit this code automatically, this advanced information can put put off a couple of weeks in the course. The end result is that HLA *does* emit code that modifies the EBP register upon entry/exit in a procecure, but the modifications are pretty much what one would expect anyway.

AFAIR, these are the only two areas where HLA will emit code that modifies the registers behind the programmer's back. The only other place where it would be *nice* to modify a register in the HLA language is when pushing an address for a pass-by-reference variable. To push an address, HLA *must* use a general-purpose 32-bit register (HLA actually uses EAX). However, HLA goes to great lengths to preserve EAX in this case, unless you explicitly tell HLA that it's okay to use some 32-bit register without preserving it.
Cheers,
Randy Hyde