Shop OBEX P1 Docs P2 Docs Learn Events
Arrays in Assembler — Parallax Forums

Arrays in Assembler

pjvpjv Posts: 1,903
edited 2010-10-06 22:09 in Propeller 1
Hi All;

I have wondered -and could not find an answer in the documentation- if one (or more) dimensional Hub Arrays defined at specific locations in a DAT section (prior to any Spin statements), as in the empty array:

Array byte 0[12]

could be referenced in PASM as in: mov Array[4],#17

If this is possible (fantastic!), then its not clear how to do it. The example method does not work.

Cheers,

Peter (pjv)

Comments

  • Mike GreenMike Green Posts: 23,101
    edited 2010-10-06 14:15
    First of all, you can't access hub memory with a MOV instruction. You have to use RDxxxx or WRxxxx. You calculate the hub address of your array element, then read a value from or write a value to the array element like this:
    mov  temp,#17
       wrbyte  temp,address
    
    address  long  0
    

    Somewhere in your initialization code BEFORE the cog is started, you'd have something like:

    address := @array + 4

    If you don't know the array element address before the cog is started, you'd at least use this technique to get the address of the first element of the array, then add the index you want like:
    mov   temp,#17
       mov   temp2,address
       add   temp2,#4
       wrbyte   temp,temp2
    
  • pjvpjv Posts: 1,903
    edited 2010-10-06 15:22
    Hi Mike;

    Thanks for your quick response.

    Oops, I picked a poor instruction to cite in my example.... I'm fully aware of the limitation of accessing HubRam from an assembler cog.

    My question was really about syntax, hoping that a reference to an Array in Hub, already defined and loaded in a DAT section, could be effected with the array name and an index number.

    A better example: rdbyte value,Array[7]

    when the hub address and size (byte/word/long) of each array entry is already known by the assembler.

    Cheers,

    Peter (pjv)
  • Mike GreenMike Green Posts: 23,101
    edited 2010-10-06 15:38
    No, you can't do that. Part of the problem is that the compiler doesn't know the address of the array when the code is assembled. You wouldn't be able to use that notation anyway because the instruction field is only 9 bits and the hub address is 16 bits on the Prop I (and 18 bits on the Prop II). You normally have to set aside a long to hold a hub address. There are some special circumstances where you can guarantee a hub address would fit into 9 bits (like the 1st 16 locations in hub RAM).
  • pjvpjv Posts: 1,903
    edited 2010-10-06 16:24
    Hi Mike;

    Sorry to be difficult or persistent here, but .....

    Well, all the variables in assembler are longs by definition, so containing the Hub Address in one should not be a problem.

    And I don't understand what you mean with "the compiler doesn't know the address of the array when the code is assembled". I define and locate my arrays and variables ahead of any code, and I see no evidence that the assembler does not know the locations by name.... albeit there is a fixed offset that one must account for.

    Now granted, I don't know any Spin (yet), so all my experience has been with assembler, but have never observed an address mismatch, and my code has been all over the map.

    Is there some surprise lurking for me I don't know about? Perhaps with Spin??

    Cheers,

    Peter (pjv)
  • Mike GreenMike Green Posts: 23,101
    edited 2010-10-06 16:31
    The various sections in Spin (VAR / CON / DAT / PRI / PUB) are processed one at a time somewhat separately. Specifically, the DAT sections are assembled without knowing where the VAR sections (or other DAT sections) will be placed in memory. That's determined later in the compilation process. At the time the DAT sections are processed, the CON sections have been processed, so any constant definitions are known and other locations in the current DAT section are known (relative to the start of the DAT section or ORG location), but the absolute address in hub memory of the DAT section is not known.

    Some of this information, like the hub addresses of the various PRI / PUB sections and the starting addresses of the DAT and VAR sections, is stored in internal tables in the object code that are filled in late in the process of constructing the binary program file.
  • pjvpjv Posts: 1,903
    edited 2010-10-06 17:19
    Mike;

    This is most interesting.

    I have only CONs and DAT Hub Global Memory and DAT assembler sections, with the DAT globals defined first.

    I have no VARs; only longs in Assembler.

    I have is a Spin Cognew statement to launch everything, and it matters not where that is located.

    The hundreds of (assembler) programs I have, and tens of thousands of compilations on those, there has never been an unexplained misalignment! So where does this "assembler not know" come from? My experience is totally to the contrary!

    Something unexplained going on here..... for me at least.

    Cheers,

    Peter (pjv)
  • mparkmpark Posts: 1,305
    edited 2010-10-06 18:40
    Wait a sec. Peter, you want to define an array in cog memory, correct? Then the problem Mike alludes to doesn't arise. You do have to use self-modifying code to access a given element of the array, though.
  • Mike GreenMike Green Posts: 23,101
    edited 2010-10-06 20:24
    Again, the compiler goes through several phases. In the main phase, the compiler produces binary fragments for each section (other than CON or OBJ). One fragment for each DAT section and each PRI or PUB method. The VAR sections are not actually converted to binary, but the variables are sorted according to storage class (byte, word, or long) and the total size of the VAR sections in each object is recorded. All of the DAT sections in an object are grouped together end to end, and all of the method code in each object is grouped together.

    Once all the sections are processed, the fragments are assembled to form the binary file. The fragments for all of the VAR sections in the object are combined. In this process, the fragments are NOT changed. There are internal tables added, one for each compiled object containing the absolute hub address of the DAT sections of the object, the absolute hub address of the VAR information for the object, and the absolute hub address of each method in the object.

    Because these are separate phases, the 2nd phase has no way to know where there might be references in the assembled code to the VAR area, so there's no way for the compile to "fix up" these addresses. This can be done at run-time using the @@ and @ operators in Spin, but not in assembler.

    It's possible for the compiler to be redesigned and rewritten to be able to do these "fix up"s. It's not really a limitation of Spin, but it would be a lot of work. All of the existing Spin compilers work essentially the same way.
  • pjvpjv Posts: 1,903
    edited 2010-10-06 20:30
    Hi Michael;

    No, I have created the tables to reside in Hub Ram, and I was hoping to reference them by a somewhat more elegant method of their name together with an index such as Name[element], since one is able to allocate an array that way at compile time.

    It seemed to me that the Hub address locations of the array elements were well behaved, and hence such a scheme should be able to work, but alas, I'm advised otherwise.

    Then the whole issue of Hub based addresses not being defined at compile time just blows me away. Do realize I'm not running any spin codes, so perhaps that makes the difference, as strictly with assembler, I'm able to point at all the right spots in Hub to access data.

    I need to better understand the proposition opposite to my observations, so I will have to do some experimenting. This could have a huge impact on the way I use the Prop.

    Has anyone else experience similar to mine?

    Cheers,

    Peter (pjv)
  • pjvpjv Posts: 1,903
    edited 2010-10-06 20:36
    Mike, we were cross posting, so I had not seen your latest comments. Thank you for those, and as stated, I will need to experiment to better understand what you are saying.

    If I recall correctly, BST has the @@@ operator, and I believe it provides the absolute Hub address at compile time. Will need to investigate.

    Thanks again.

    Peter (pjv)
  • Mike GreenMike Green Posts: 23,101
    edited 2010-10-06 20:41
    Peter,
    You always need a small "stub" of Spin code to at least start up your assembly stuff in a cog with a COGNEW. I would simply allocate my hub variables in a DAT section (so the compiler doesn't rearrange the variables by size) and pass the address of the start of the DAT section as the 2nd parameter to COGNEW (the PAR register). All hub variable access then is relative to the value of PAR. You have to compute all hub addresses to the byte level anyway because of the way the RDxxxx and WRxxxx instructions work.
    DAT
    base  long   ' other variables follow
    ' stuff
    array byte  0[12]
    
    PUB startItAll
       COGNEW(@assembly,@base)
    
    DAT
             ORG    0
    assembly ' code starts here
    ' stuff
             mov    temp2,par
             add     temp2,#array-base ' must be < 512
             add     temp2,index
             rdbyte temp,temp2
    
  • pjvpjv Posts: 1,903
    edited 2010-10-06 22:09
    Hi Mike,

    Thanks, and of course yes I have a starter stub to launch the assembler cog. I will do some experimenting with Spin code to attempt to determine the mechanism by which the addresses become no longer predictable.

    Other than some experimenting many years ago when the Propeller was first introduced, I have been away from that silicon (focusing on SX projects) until this year, and that has been all assembler. Perhaps some day I will need to use Spin, but for now, assembler works great for me, and I'm able to squeeze a lot of performance out of a single cog.

    Thanks for your insight and assistance.

    Cheers,

    Peter (pjv)
Sign In or Register to comment.