Shop OBEX P1 Docs P2 Docs Learn Events
confusion with data types and accessing the data from memory — Parallax Forums

confusion with data types and accessing the data from memory

pidzeropidzero Posts: 23
edited 2016-08-16 23:30 in Propeller 1
greetings,

Let's cosider this data block:
DAT string_00 byte "Hello world. ", 0
    valueA_01 byte $03
    string_02 byte "This is ", 0
    valueB_03 byte $2A
    string_04 byte "a test.", 0
    { in reality, the data continues in this fashion for many lines }
Instead of this:
PRI handle_string ( stringptr )
    terminal.str ( stringptr )
PRI handle_valueA ( value ) ' this method expects a value from $00 to $FF
    repeat value
      beep
PRI handle_valueB ( value ) ' this method expects a value from $00 to $FF
    repeat value
      blink
PRI my_method
    handle_string ( @string_00 )
    handle_valueA ( valueA_01 )
    handle_string ( @string_02 )
    handle_valueB ( valueB_03 )
    handle_string ( @string_04 )
    { in reality, my_method continues like this for many lines, in many different methods }
i wanted to try something like this:
DAT process word $FF00, @string_00, $FF10, @valueA_01, {
               } $FF00, @string_02, $FF20, @valueB_03, {
               } $FF00, @string_04, $FFFF
PRI my_method | pointer
    repeat until process[pointer]==$FFFF
      case process[pointer]
        $FF00 : handle_string ( process[pointer+1] )
        $FF10 : handle_valueA ( {something here} )
        $FF20 : handle_valueB ( {something here} )
      pointer+=2
I'm having some confusion about how to get a byte out of a memory location stored in an array of word sized data. I know this is a no-brainer, but I keep working in circles, never getting the data I expect. what goes in {something here}?

Comments

  • shouldn't it be something like
            $FF10 : handle_valueA ( byte[process[pointer+1] ] )
    
  • pidzeropidzero Posts: 23
    edited 2016-08-17 01:15
    David Betz wrote: »
    shouldn't it be something like
            $FF10 : handle_valueA ( byte[process[pointer+1] ] )
    
    No, sorry, byte [ process[pointer+1] ] does not produce the byte of data in valueA_01...

  • David BetzDavid Betz Posts: 14,516
    edited 2016-08-17 01:20
    pidzero wrote: »
    David Betz wrote: »
    shouldn't it be something like
            $FF10 : handle_valueA ( byte[process[pointer+1] ] )
    
    No, sorry, byte [ process[pointer+1] ] does not produce the byte of data in valueA_01...
    Hmmm... Maybe the addresses are actually 32 bit values? Or maybe it's an issue with the @ operator which never seems to work the way you expect. I suggest you try C. It handles pointers a lot better. :-)

  • That tricky @ operator!

    I'm happy to try C (a.k.a. learn C from zero C coding experience)... on the next project! It does seem like a worthwhile endeavor. However... this project is being developed for the Spinneret. Too bad the Spinneret's code resources are scarce... I've finally got a stable (and sexy, if i do say so myself) web server. I think porting the entire code base to C, not having any C experience yet, would be biting off more than I can chew... Seems SPIN will also be available on the Propeller 2. That's encouraging.

    Can SPIN and C be used in a mixed fashion? (i.e. C top level with a few SPIN objects, or SPIN top level with a few C objects) Maybe a complete rewrite isn't necessary!


  • ElectrodudeElectrodude Posts: 1,657
    edited 2016-08-17 03:07
    pidzero wrote: »
    David Betz wrote: »
    shouldn't it be something like
            $FF10 : handle_valueA ( byte[process[pointer+1] ] )
    
    No, sorry, byte [ process[pointer+1] ] does not produce the byte of data in valueA_01...

    I believe you want byte[@@process[pointer+1]]. The Spin compiler doesn't link the code it produces - all pointers are relative to the beginning of the current object. When you use the @ operator in a PUB or PRI block, the compiler emits code that adds the object base to the offset at runtime, but when you use @ in a DAT block, it can't do it at runtime, so it does the best it can: it leaves the unlinked address there, which is usually not what you want. The @@ operator adds the current object base to an offset to get the final runtime pointer that you want.
  • pidzeropidzero Posts: 23
    edited 2016-08-17 04:13
    I believe you want byte[@@process[pointer+1]]. The Spin compiler doesn't link the code it produces - all pointers are relative to the beginning of the current object. When you use the @ operator in a PUB or PRI block, the compiler emits code that adds the object base to the offset at runtime, but when you use @ in a DAT block, it can't do it at runtime, so it does the best it can: it leaves the unlinked address there, which is usually not what you want. The @@ operator adds the current object base to an offset to get the final runtime pointer that you want.
    BINGO! <-- i'd make that blink, if i could! THANKS!

    I didn't fully understand the explanation, but I think I'll get it with some more hands on. It turns out the @@ was also necessary on the handle_string method; should read: handle_string ( @@process[pointer+1] )

    So, here is the fully working implementation of this method:
    PRI my_method | pointer
        pointer~
        repeat until process[pointer]==$FFFF
          case process[pointer] 
            $FF00 : handle_string ( @@process[pointer+1] )
            $FF10 : handle_valueA ( byte[@@process[pointer+1]] )
            $FF20 : handle_valueB ( byte[@@process[pointer+1]] )
            $FFFF : quit
          pointer+=2
    
    PRI handle_string ( stringptr )
        terminal.str ( stringptr )
    
    PRI handle_valueA ( value ) ' this method expects a value in the range of byte
        repeat value
          beep
    
    PRI handle_valueB ( value ) ' this method expects a value in the range of byte
        repeat value
          blink
    
    DAT process word $FF00, @string_00, $FF10, @valueA_01, {
                   } $FF00, @string_02, $FF20, @valueB_03, {
                   } $FF00, @string_04, $FFFF
    
    DAT string_00 byte "Hello world. ", 0
        valueA_01 byte $03
        string_02 byte "This is ", 0
        valueB_03 byte $2A
        string_04 byte "a test.", 0
    

  • pidzero wrote: »
    David Betz wrote: »
    shouldn't it be something like
            $FF10 : handle_valueA ( byte[process[pointer+1] ] )
    
    No, sorry, byte [ process[pointer+1] ] does not produce the byte of data in valueA_01...

    I believe you want byte[@@process[pointer+1]]. The Spin compiler doesn't link the code it produces - all pointers are relative to the beginning of the current object. When you use the @ operator in a PUB or PRI block, the compiler emits code that adds the object base to the offset at runtime, but when you use @ in a DAT block, it can't do it at runtime, so it does the best it can: it leaves the unlinked address there, which is usually not what you want. The @@ operator adds the current object base to an offset to get the final runtime pointer that you want.
    It's odd that the Spin compiler doesn't make a second pass to fixup things like this. After all, it's running on a PC with basically limitless resources. It could even buffer the entire program in memory to avoid having to read the source a second time.

  • Dave HeinDave Hein Posts: 6,347
    edited 2016-08-17 12:59
    The use of the Spin @ operator is inconsistent between PUB/PRI sections and DAT sections. Within a Spin method, the @ operator gives the absolute address of a variable. In a DAT section it produces the relative address within an object. In Spin code, the @@ operator will add the address of the beginning of an object to a value. It can even be used with constants. As an example, the value of @@0 is just the address of the object.

    One advantage to storing object offsets in the DAT sections is that it makes an object completely relocatable. This makes it easy to link compiled objects together. They just have to be concatenated, and only the object addresses in the method table need to be adjusted to complete the linkage. This also allows for relocating the entire linked binary in memory just by adjusting 5 values in the Spin header. The main drawback is that you have to adjust the addresses read from a DAT table using the @@ operator. In some of my Spin programs I use an initialization method to adjust the addresses once when the program first starts up.

    BST and Homespun have added the @@@ operator that is used in the DAT section to produce absolute addresses. However, this is not supported in the Prop Tool or OpenSpin. For the top object you can generate absolute addresses by adding 16, such as @variable+16. I use the "+16" technique in the pfth Forth interpreter so that it can be compiled using the Prop Tool.
Sign In or Register to comment.