Shop OBEX P1 Docs P2 Docs Learn Events
loading a a string (bytes) into a long in a DAT section — Parallax Forums

loading a a string (bytes) into a long in a DAT section

agsags Posts: 386
edited 2013-10-27 14:05 in Propeller 1
I'd like to compare an 8-byte-long value (fixed-length string) to a constant string. I'm doing this:
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

  • kuronekokuroneko Posts: 3,623
    edited 2013-10-25 16:42
    You can prefix your byte array with an empty long, e.g.
    DAT
    odd     byte    1               ' force misalignment
            long
    label   byte    "abcd", "efgh"
    
    The empty long just makes sure that you end up at 4n, no other penalty.

    So this could work for you (it does provide the functionality):
    PUB compare(val1,val2)
    
      return val1 == _constLongVal[0] AND val2 == _constLongVal[1]
    
    DAT
    _constLongVal   long
    [COLOR="#D3D3D3"]{constLongVal}[/COLOR]  byte    "abcd", "efgh"
    
  • agsags Posts: 386
    edited 2013-10-25 18:31
    I did think of this as a fallback option - but was looking for an alternative because:

    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:
    sym0 long
             byte   "abcd","efgh"
    sym1 byte   "ijkl","lkji"
    sym2 long
             byte   "mnopqrst"
    sym3 long
             byte   "uvwx",0,"yzzy"
    

    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.
  • kuronekokuroneko Posts: 3,623
    edited 2013-10-25 18:44
    [COLOR="#FF0000"]sym0 long[/COLOR]
             byte   "abcd","efgh"
    [COLOR="#00FF00"]sym1 byte[/COLOR]   "ijkl","lkji"
    [COLOR="#0000FF"]sym2 long[/COLOR]
             byte   "mnopqrst"
    [COLOR="#FFA500"]sym3 long[/COLOR]
             byte   "uvwx",0,"yzzy"
    
    ags wrote: »
    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.
    sym1 is of type byte so you only get a +1 increment.
    ags wrote: »
    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"?
    Yes. You can define a byte array with any split detail you want, whatever is most convenient.
    ags wrote: »
    Finally, what about sym3? Is sym3[1] == 0, or "\nyzz"?
    As sym3 is of type long you end up with $7A7A7900 or "\0yzz". If you want a big 0 in there try
    sym3 long
             byte   "uvwx", long 0, "yzzy"
    
  • agsags Posts: 386
    edited 2013-10-25 20:06
    So summarizing, this behaves just as I expected it to, except it requires the size/alignment on a separate line from the... "size of data" (for lack of a better term) that follows. This is legal:
    sym0  byte  word 64_000, long 4_000_000, byte 250
    

    this is not legal:
    sym1   long    byte "abcdef", word 64_000
    

    this is legal:
    sym2   long
               byte   "abcdef", word 64_000
    

    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:
    symLong   long
    symByte   byte   "abcde"
    

    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)?
  • kuronekokuroneko Posts: 3,623
    edited 2013-10-25 20:14
    ags wrote: »
    Does this:
    symLong   long
    symByte   byte   "abcde"
    

    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)?
    symLong and symByte refer to the same address (optional/required padding is inserted before symLong and there is no space reserved for it). Just compile this in the PropTool and place the cursor on the labels in question, you'll get all the info you need. Referring to the former will give you a long array so to speak, the latter will represent a byte array.
  • agsags Posts: 386
    edited 2013-10-26 16:57
    Is it just me, or would it have been more intuitive and consistent if this was the syntax supporting this functionality:
    longSymName    long   byte "abcd", "ef", word $FFFF, $A5A5, long $FFFFFFFF, $5A5A5A5A
    
    which is "symmetrical" with this (legal) syntax:
    byteSymName   byte   "abcd", "ef", word $FFFF, $A5A5, long $FFFFFFFF, $5A5A5A5A
    
    In both cases, the contents of memory location *SymName are identical, the only difference being that longSymName is long-aligned while byteSymName is byte-aligned.

    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.
  • Mike GMike G Posts: 2,702
    edited 2013-10-27 06:32
    I read through this thread a couple of times and wrote a test case to understand the dilemma. If I understand correctly,the declaration label LONG "abcd" in the DAT section causes a,b,c, and d to each take up a long. So you end up with
    0x61 0x00 0x00 0x00 0x62 0x00 0x00 0x00 0x63 0x00 0x00 0x00 0x64 0x00 0x00 0x00
    

    If the issue is packing encoded chars into a long type, the following DAT declaration will work.
    DAT
      longArray   long  $6463_6261, $6766_65, $0
    

    What has me scratching my head, why put yourself in a position to write non-standard string handlers in the first place?
  • agsags Posts: 386
    edited 2013-10-27 14:05
    Mike G wrote: »
    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.
Sign In or Register to comment.