Re: HLA suggestions

From: Beth (BethStone21_at_hotmail.NOSPICEDHAM.com)
Date: 10/30/03


Date: Thu, 30 Oct 2003 02:50:48 -0000

T.M. Sommers wrote:
> Randy wrote:
> > This is only true if you compile a PROGRAM. If you compile
> > a UNIT it all goes away. Check out:
> > http://webster.cs.ucr.edu/Page_hla/WhitePapers/DoingUnits.html
> > For more details on controlling the code that HLA generates.
>
> According to that paper, units cannot run, and I wanted something to
> run in order to test the compiler. Or perhaps I misunderstand about
> units.

"Units" _can_ run...

Basically, with a "program", HLA automatically calls the main
procedure (between "begin" and "end" for the "program" at the lowest
lex level :) as the "_HLAMain" entry point...and the linker response
file issues a "-entry:HLAMain" to tell the linker to set the entry
point to this main procedure...

This, though, is really a "convenience" thing...a means to make HLA
programs have a "main procedure" so that it operates in a similar way
to HLLs (and gives us an opportunity - as we have a _known_ entry
point - to insert the code for setting up exceptions for the standard
library :)...

If you create a "unit" then there is no "main procedure"...it merely
spits out what you type...no code is generated for exceptions or
anything here because there is "no known entry point" for a
"unit"...use a "unit" and then set the "?@ noframe:=true; ?@
nodisplay:=true;" (as usual, spaces inserted merely to stop OE turning
them into Email hyperlinks because it sees the "@" sign in the middle,
remove in real code ;)...and, hey presto, there is absolutely no
automatic code generation whatsoever...

Then, to make it "run", simply create a procedure called
"_HLAMain"...this is the default that the linker is told is the "entry
point" by the response file that HLA spits out, so it'll set that to
your entry point...also, of course, you can employ HLA's "alias"
facility here too (something like "procedure Start;
@external("_HLAMain");" which'll allow this procedure to be called
"Start" - or some other name - internally in the HLA program but it's
"_HLAMain" externally...namely, it's "_HLAMain" in the eyes of the
linker :)...or, alternatively, you can call it whatever name you like
and just edit the linker options to have a different "-entry:Name"
option, where "Name" is the procedure you want as the entry point
(note, though, that MASM's "LINK" automatically prepends an underscore
because it's expecting C convention names ;)...

Obviously, for HLA under Linux, the "-entry:" option and so forth are
different but the same basic principles should apply...the basic sole
difference between a "unit" and a "program" is that a "progam" has a
_known_ "main procedure" which acts as an "entry point" (and HLA spits
out the code for exceptions here, ready for use of the standard
library because that's where it has to go, prior to any standard
library calls being made :)...when you're creating a "unit" instead,
though, HLA has actually no idea where the entry point is, really, so
it can't insert any code (though, this is good...this is why we _want_
"units" to remove this code generation and let the whole "entry point"
thingy be handled by the programmer...including, in fact, a case of
_NO_ entry point, perhaps, for something like a big DLL of procedures
that has no "initialisation" or "exit" ("WEP") procedure (sorry,
"WEP"'s Win3.x terminology...that is, there's no "DllEntryPoint" with
either DLL_XXX_ATTACH or DLL_XXX_DETACH, which would be the modern way
to cover these two in a DLL...nevermind, the issue is just that the
DLL may simply have no "entry point" nor "exit code" nor anything
similar so "units" also work for this situation too ;)...

Actually, in reply to Frank on the "review of AoA" thread, I've posted
up some (very unfinished) "unit"-based HLA code which does things
directly with the Windows API (so, Windows only, unfortunately)...this
code is about 500 bytes and does everything itself...no "automatic
code generation" at all...it's all about the "units", they do magic
stuff :)

> >>program HelloWorld;
> >> ...
> >>end HelloWorld;
> >
> > And it also describes how to create a really small
> > Hello World program.
>
> I was not aiming for the smallest size possible, just something to
run
> and to try out some HLA features.

Well, yes...but the "smallest size" program doesn't have "automatic
code" inserted to initialise exceptions with calls to the standard
library...hence, ignore the objective of "smallest program" because
there's still useful information about how HLA links things up and how
to use "units" and that sort of thing in the article too...

Here's a very simple example of a "unit" that does nothing but return
to Windows...if you check out the MASM code that is generated by this
example, there's no "automatic code" at all...it's literally just the
two machine instructions in the "Start" procedure and that's it...

Watch out for any stupid thing Outlook may do with the lines that
include an "@" sign in them...these are obviously NOT really Email
addresses but your newsreader might choose to decide to turn them into
hyperlinks regardless (OE does)...also, I've NOT actually compiled
this to see if it works myself...but I've coded something like this a
few times before and this is pretty simple that I'm going to stick my
neck out that I can be lazy and not bother to compile it to check
it...Hopefully not "famous last words" there ;)...

--------------- 8< -------------------

unit Example;

   // Tell HLA to generate no "automatic" code
   // for procedures...
   //
   ?@noframe := true;
   ?@nodisplay := true;

   // prototype for "Start", that is referred to as "_HLAMain"
   // in the MASM code and this is the "default entry point"
   // for HLA code that LINK will presume to set...
   //
   procedure Start; @external("_HLAMain");

   // Import used Windows API...just "ExitProcess" in this case...
   //
   static

      ExitProcess: procedure; @external("__imp__ExitProcess@4");

   endstatic;

   // Main program:
   // only the machine instructions you actually see
   // below will be in the final program...
   //
   procedure Start;
   begin Start;

      pushd (0);
      call (ExitProcess);

   end Start;

end Example;

--------------- >8 -------------------

[ Note, for non-HLA people, I use "pushd" rather than "push" simply
because it avoids any silly "dword ptr" type casting on the zero
(although, in HLA, that's done with "(type dword 0)" but it's the same
problem in other assemblers...having to specify the size of the
immediate constant :)...by using "pushd", which is automatically "push
dword" then I can stuff "0" straight in, no problem...also of interest
is that the zero won't actually take up a dword of space because MASM
does some "optimising" of using the opcode where an 8-bit immediate is
specified and it just zero extends it to 32-bits before pushing...

If you actually want to get an appreciation of this sort of thing then
it's actually very easy to do...include "-aFl" on the HLA command line
which passes through "/Fl" to MASM and it'll spit out a listing file
which shows both the MASM output from HLA and its corresponding hex
bytes...if you _were_ interested in "smallest size" or just needed to
know the hex bytes for some other reason then this is a simple but
cool command to stick onto the HLA command line ;) ]

Note that, with Linux, the same basic things apply - using "unit" and
"noframe" and "nodisplay" - the difference is all, of course, to do
with calling Linux API rather than Windows API, as you might imagine
;)...

Beth :)