Theo, I found your posts on checking compiler optimization to be both interesting and instructive. But you did not really tell people about the tools that you used or how you achieved your results. Perhaps you might like to provide an example and either the tools in an archive or a link to where people can get them.
I noted that when using Assembler in PowerBasic, that you can possibly run into
a conflict situation. If you permit PowerBasic to use registers for some variables, using the #REGISTER ALL, #REGISTER DEFAULT, or REGISTER directives and statement. That is, if PowerBasic assigns a variable to a register for faster processing, and you attempt to access that variable from memory using some assembler instructions, you will bypass and defeat the efforts of the compiler to perform optimization there. Further, the compiler will overwrite your changes when it attempts to return the assigned register contents to the same memory location.
Unfortunately, when you use REGISTER, you can designate which variable to assign to an available register, but you are not able to designate which register
to use. The compiler is keeping track of the registers as they are allocated to
different variables, and only it knows which register may represent any given
variable. You should be able to work out which register is involved in a given set of circumstances (by tracking which register reflects the same contents as the variable has), but this is at best an uncertain process.
So the problem is, if you want to improve performance by writing some assembler
code, you may have to use #REGISTER NONE so as to avoid possible conflicts
with the compiler's allocation scheme for variables, and that reduces the amount
of optimization that the compiler will attempt.
Another issue is accessing passed parameters for Subs and Functions that are
placed on the stack. How do you get to them? Well, there are several methods, but first you have to know how those parameters are being passed.
There are generally three ways: BYREF, BYVAL and BYCOPY. BYREF is a
reference to the variable, it is not the variable directly. The reference is
actually a pointer, which is 32-bits long. It points to the variable in memory.
For integers and floating point numbers, it is pointing to the value. For UDTs, it
is pointing to the first byte of that user defined type. But for strings, it equates
to as string reference, which consists of another pointer to the actual place
where the string's first byte is (this pointer is also 32 bits), followed by a 32-bit
length designator for that sequence of bytes (string),
So the BYREF parameter for a string is effectively the same as using VARPTR()
on that string, and the dereference of that pointer, using the first 32 bits, is
the same as STRPTR(), and then using the second 32-bits from that pointer,
we get the same as LEN().
Often, you see people defining LOCAL variables inside a Sub or Function, then
assigning a passed parameter to a given local variable before trying to use it
with assembler code. No harm in that, and in fact it can be beneficial at times.
For instance, you can pass a dynamic variable length string, then assign it to
a local ASCIIZ string with a fixed length, and PowerBasic will automatically
convert from one format to the other. This is handy when calling APIs that
do not support the first string format, or when you want your own code to
loop through a string until it encounters a zero byte ($NUL character).
But if you know how to access the parameters already on the stack from your
assembler code, you gain an edge in speed and cut the amount of code and
memory required. BYVAL actually puts a numeric value on the stack rather than
the pointer reference, so you would not use this for passing a string. BYCOPY
is what the compiler will use when you pass a string constant or string construct, by creating a copy of the string in memory, then passing a pointer
reference to the copy. I've read that you also get BYCOPY if you pass a
numeric expression rather than a number variable, but I would take it that this
means that you requested it be passed BYREF. In other words, PowerBasic
reverts to BYCOPY when you request (or default to) BYREF, and there is no
specific variable to point back to. So the compiler creates a temorary one and
points to it instead.