When to usee '@' - please point me at the required reading...
pacman
Posts: 327
I'm managed to get myself into a knot over when to pass data with @.
I _though_ I had a handle on it, but my latest code has not been going well....
I've looked at other people's code to try and see the fundamental underling truth, I've read chunks of the 'bible' ("Programming and Customising the ......") , the manual and the Lab book, just when I think I've got it..I get confused and lose my way.
Please explain...Point me to the "make it clear" text and I'll read many many times.
Does an object with and array declared in its VAR section, then need to refer to that object using @ ? Isn't it is a 'gloabl' variable {for this object}?
I (think?) I can understand the need if I'm passing between cogs (or calling the object multiple times, or passing to another object in the same cog), but WITHIN the same object/cog ?
Huge THANKS in advance
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
=================
The future is in our hands.
Which way to the future?
=================
I _though_ I had a handle on it, but my latest code has not been going well....
I've looked at other people's code to try and see the fundamental underling truth, I've read chunks of the 'bible' ("Programming and Customising the ......") , the manual and the Lab book, just when I think I've got it..I get confused and lose my way.
Please explain...Point me to the "make it clear" text and I'll read many many times.
Does an object with and array declared in its VAR section, then need to refer to that object using @ ? Isn't it is a 'gloabl' variable {for this object}?
I (think?) I can understand the need if I'm passing between cogs (or calling the object multiple times, or passing to another object in the same cog), but WITHIN the same object/cog ?
Huge THANKS in advance
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
=================
The future is in our hands.
Which way to the future?
=================
Comments
Me too, but I realized it by just printing the value that I passed to a function in hex (to FullDuplexSerial) and saw I was passing 0!
This applies for local functions/methods as well as for calls into another object.
The @ is always necessary to pass a byte array address, because you can pass nothing but long values. The @ is the address of the array and you can then manipulate it using the byte[noparse][[/noparse]array_ptr][noparse][[/noparse]offs] or word/long accessors.
I must admit that I don't (yet) know when @@ will be required and what the difference between @, @@ and the BST compiler's @@@ is. I think the latter returns the absolute address of a label, while the single @ returns the address relative to some base offset (see the PBASE, VBASE, DBASE info in BST's listing files).
HTH,
Juergen
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
He died at the console of hunger and thirst.
Next day he was buried. Face down, nine edge first.
Post Edited (pullmoll) : 3/25/2010 10:28:14 AM GMT
Whereever you use the name of the variable in the program the content of this RAM is read/written. You don't have to take care where this RAM is inside of the 32kB of available HUB-RAM. Whereever you use the variable name the compiler will generate the right code (containing the right address) to access the value stored there. But as you already know the variable name is only valid inside of the same objects *.spin-file. You don't have access to the same variable (RAM location) from other *.spin files. But sometimes you need to have access to a shared memory. That's where the @ is needed. This operator simply tells your program where to find the variable in RAM, it gives back the RAM-address. Together with byte[noparse][[/noparse] ram-address ], word[noparse][[/noparse] ram-address ], long[noparse][[/noparse] ram-address ] even parts that don't know that variable name can now access the content of the variable if they know the right address.
Sometimes it even makes sense to use RAM-addresses in the same object. That's when you deal with data-structures. You can only pass long-values in function-calls. So, if you have a function that should print a string you can't pass the string directly. That's when you need addresses inside of the same object.
The most confusing thing is propably when you use variables to store the address of another variable. For example: string1 byte "Test",0 is defined in a DAT section. You call printWithDecoration( str ). In printWithDecoration you call the printStr of a library .. for example the FullDuplexSerial. The first call looks like this:
printWithDecoration( @string1 )
the call inside printWithDecoration looks like that:
printStr( str )
Here you DON'T use the @ operator because the variable str already contains the address of the string. Best way to avoid errors in this case (like doing printStr( @str ) ) is that you use a naming convention. If the variable contains data you give it names like usual, but if it contains pointers you name it ptr_name.
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
John R.
Click here to see my Nomad Build Log
But the New York Museum of Modern Art just acquired the @ sign for their collection. See here - http://www.pcmag.com/article2/0,2817,2361777,00.asp
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Whit+
"We keep moving forward, opening new doors, and doing new things, because we're curious and curiosity keeps leading us down new paths." - Walt Disney
Post Edited (Whit) : 3/25/2010 2:10:37 PM GMT
The equivalent to C's *pointer in Spin is:
long[noparse][[/noparse]pointer]
word[noparse][[/noparse]pointer]
byte[noparse][[/noparse]pointer]
depending on the variable size, you use.
In C the pointer is defined with the size to which it points, so C needs only one syntax for all datasizes.
Andy
I'm glad someone got it.
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
=================
The future is in our hands.
Which way to the future?
=================
If the "@name" expression is a DAT block, it is evaluated at compile time and gives the address of "name" relative to the start of the object it's in.
Compile-time @ and run-time @ behave differently because each object is compiled independently. At compile time, the compiler doesn't know where in memory an object is going to end up, so all @ expressions are evaluated relative to the start of the object. At run-time, of course, all objects have specific addresses, so @ gives absolute addresses.
To go from an object-relative address to an absolute address, use the @@ operator in a PUB or PRI. @@ is a unary run-time operator that simply adds the start address of the object. Basically you have to do address fixups yourself instead of having a linker do the work.
However, if you don't mind using non-standard Spin, BST and Homespun will do the work for you. @@@ is a compile-time operator that evaluates to the absolute address of whatever follows. It does what you probably expected compile-time @ to do.
·
There is a separate phase to the compiler that assigns absolute memory addresses to the various sections (code, DAT, VAR for each instance). This occurs at a different time from the actual code and data compilation. It would be possible for the compiler to produce relocatable code with the sort of "fixups" needed to resolve "@" in the case of references to DAT data during this later compilation phase, but that wasn't done in the Propeller Tool's compiler. That's why "@" has different semantics at compile-time and run-time.
I have no means to test this at the moment but for sure the value of a_pointer is not the correct address of a_variable. To correct it one has to add the objects base address to a_pointer or use the @@@ operator in its declaration.
How do you get the objects base address? Use "a_pointer := a_pointer + @[noparse][[/noparse]0]".
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
For me, the past is not over yet.
The answer is x = 0, or in other words, a_pointer <> @a_variable.
To correct a_pointer, do this:
But the purpose of the example is to point out the insanity of @ in Spin/PASM.
As you say a_pointer <> @a_variable in that code.
BUT a_pointer has been initialized to @a_variable in it declaration.
Which implies that @a_variable in Spin is not the same as @a_variable in the DAT section. No wonder @ confuses everyone.
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
For me, the past is not over yet.
Compile-time @ is the troublemaker, and it really only rears its head inside DAT blocks. Just remember: if you use @ inside DAT, you'll have to adjust it at run time with @@.
The declaration:
a_pointer long @a_variable
Just turns out to be wrong. You can correct it at run time by adding the object base to it:
a_pointer := a_pointer + @[noparse][[/noparse]0]
Which is weird and a pain if you have a lot of them.
Or you can give up the Prop Tool and use
a_pointer long @@@a_variable
Which turns out to be correct.
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
For me, the past is not over yet.
Adding the object base is exactly what the @@ operator does. This code:
does what you think this code does:
except that your code isn't legal Spin.
a_pointer := @@a_pointer
Turns out that in the old PropAltair project I was actually "adjusting" a lot of incorrect pointer offsets on the fly by adding the the object base which was initialized from:
object_base := @@0
This is the correct syntax that I was remembering incorrectly in the previous post. It's weird in itself, where @@ gets the address of a literal zero, never was quite sure why that should turn out to be the objects base address.
All in all, I'm grateful for @@@.
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
For me, the past is not over yet.