loading a a string (bytes) into a long in a DAT section
ags
Posts: 386
I'd like to compare an 8-byte-long value (fixed-length string) to a constant string. I'm doing this:
but it fails. The constant values need to be long aligned because I get the variable string one long at a time - so what I compare to has to be long aligned. The standard way I load a string into a DAT location is:
I was hoping that I could use similar syntax to ensure the DAT value is long-aligned, but have it build up the long value one byte at a time using the string notation that works for DAT byte values. I realize I could load the long constant value as a 32 bit value but then it would not be readable or easily maintainable.
Any ideas? Thanks.
Edit: I wonder if this might be useful in the "Tips and Tricks" posting? Is this of use to others (too arcane for general use, or too obvious to bother posting?)
DAT constLongVal long "abcd","efgh" PUB compare(val1,val2) return val1==long[@constLongVal][0] AND val2==long[@constLongVal][1]
but it fails. The constant values need to be long aligned because I get the variable string one long at a time - so what I compare to has to be long aligned. The standard way I load a string into a DAT location is:
DAT constByteVal byte "abcdefg"
I was hoping that I could use similar syntax to ensure the DAT value is long-aligned, but have it build up the long value one byte at a time using the string notation that works for DAT byte values. I realize I could load the long constant value as a 32 bit value but then it would not be readable or easily maintainable.
Any ideas? Thanks.
Edit: I wonder if this might be useful in the "Tips and Tricks" posting? Is this of use to others (too arcane for general use, or too obvious to bother posting?)
Comments
So this could work for you (it does provide the functionality):
a) I didn't know the "empty" long was allowed (Note: I have had experience with this type of construct before, somewhat by accident, and it caused behavior that I could not fully understand so have purposefully stayed away from it. This example provides some more understanding, but I still wouldn't say that I completely understand exactly what the compiler does with something like this.)
b) Knowing that the compiler will not change ordering of DAT symbols in memory (unlike VAR), I thought I had to waste a long to force alignment, then follow with the byte-sized (by definition) and long-aligned (by side-effect of ordering) data immediately following.
So in your example, there is not a wasted long (but there could be padding bytes to achieve long alignment), even if just by coincidence the "empty" long happened to land on a long boundary (e.g. there would not be a full long for padding).
I'm afraid there's no way I can think of making this a short question, the more I think about it. (That's the "I don't completely understand it" aspect of it - to really know exactly how I can use this I need to understand it in complete detail). So here goes:
Using this definition:
Your example code indicates that the memory assigned sym0 will be two longs, and there will be only odd-bytes "wasted" to achieve the long alignment. The value is allowing an easy human-readable format to stuff the byte (character) values into the long symbols. Your example also indicates that the compiler will treat sym0 as having long size, so indexing sym0[0], sym0[1] will increment the address by 4 for each element, not 1.
What happens to the following symbol., sym1? If it is indexed like sym0, will sym1[0], sym1[1] increment the address by 4 or 1? (is it's size long or byte, as it doesn't have an "empty" long alignment directly associated with it as sym0 does.
Sidestepping that issue, with sym2 defined just like sym0 (the compiler will treat it as long-sized and aligned) will the behavior be identical to if it were defined as two separate long-sized entities, e.g. "mnop","qrst"?
Finally, what about sym3? Is sym3[1] == 0, or "\nyzz"?
Sorry for the many questions, but with this level of detail I'll be able to "own" this an add it to my toolkit of tricks to utilize fully.
Thanks.
Yes. You can define a byte array with any split detail you want, whatever is most convenient.
As sym3 is of type long you end up with $7A7A7900 or "\0yzz". If you want a big 0 in there try
this is not legal:
this is legal:
I presume this due to challenges with implementing a more consistent grammar (and parse tree) rather than ease-of-use or quality of design (similar to the @@ issue).
Thank you for clarifying this. I think I now "own" this and will be able to use it creatively and effectively.
One more thought:
Does this:
reserve no space for symLong (in which case referring to @symLong could be a problem), or are symLong and symSome aliases for the same memory location, with different "native" sizes (for indexing using the [] operator, for example)?
I do see some possibility for confusion with the first example: is the intention that the word value $FFFF also be byte-aligned, or does it immediately follow the byte value 'f'?
BTW, intent is not to complain (overall SPIN is pretty clean for what it is, IMO) but I'm wondering if I'm missing something else which the designer(s) needed to take into account.
If the issue is packing encoded chars into a long type, the following DAT declaration will work.
What has me scratching my head, why put yourself in a position to write non-standard string handlers in the first place?
Agreed it might be an unnecessary optimization - but it started out as a "I should be able to do this" and resulted in a better understanding of a syntax that I did not understand (and had caused me a problem in the past with PASM code). In some cases I have a string that I know is long-aligned, and I want to compare it against a string constant. I wanted to define the string constant to be both long-aligned and human-readable (like the standard byte-aligned symName byte "abcdef" syntax). This allows me to compare consecutive long values, a 75% reduction in run time.
But mostly I finally understand how to force alignment, with the minimum wasted space.