LONG vs RES
Title: | LONG vs RES |
Author: | 72.185.234.76 |
Published: | Sun, 31 May 2009 20:35:30 GMT |
How is RES different from LONG?
This is very difficult to explain, but understanding this is one of those Eureka moments that make you into a real Propeller assembly programmer.
As PropTool is compiling a spin program, with embedded assembler, it is keeping track of two important pointers.
- The Hub RAM pointer. This is the address in Hub RAM that the current code or data is going to be placed. It starts at zero, and keeps getting incremented as spin code is compiled or assembler is assembled. It measures memory as bytes.
- The Cog RAM pointer. This is set by the ORG directive, and is then incremented as assembler instructions and LONG, WORD and BYTE statements are assembled. It represents the eventual Cog address where code and data will live once it have been copied into a cog by a COGNEW or COGINIT. It measures memory as longs.
LONG defines an item of data. It increments the Cog RAM pointer by 1 and the Hub RAM pointer by 4.
RES reserves what will eventually be a space in Cog RAM with undefined content. It just increments the Cog RAM pointer by 1. It leaves the Hub RAM pointer alone.
That is the difference.
Why?
When you have a long that has initialised data, then it must occupy a long in Hub RAM to start with, and then it is copied with the rest of the code to a Cog to be executed. If it doesn't need to be initialised, you could just store any old value (say zero) in the long in Hub RAM and have that copied. But this unnecessarily wastes a long in Hub RAM that isn't needed. RES is a statement that allows you to mark out space with labels at the end of Cog RAM, without that space having to be taken up in Hub RAM.
"I don't get it. Just tell me what I need to do"
- If you need initialised data in your assembler routine, e.g. from constants >$1FF, then use LONG to define them.
- If you don't need data to be initialised, then use RES. But ensure that for a particular block of code and data (between ORG and FIT) that all RES lines comes after everything else.
- If you really don't understand what all this means, just always use LONG and leave RES alone.
Another explanation
Here's what Propeller Tricks and Traps has to say on this issue:
Be sure to place RES statements at the end of any ORG segment that uses them. The following example does it wrong:
//MOV Time,CTR
ADD Time,Offset
...
Time RES 1
Offset LONG 230
Other_value LONG 123
ORG
Another_cog ...//
In this example, Offset will get clobbered when CTR is copied to Time, and 123 will get added to it instead of 230. Why? Because when the assembler encounters a RES, it reserves space in cog memory, but not in hub memory where the program is stored. Consequently, 230 will occupy Time’s address in hub memory, and 123 will occupy Offset’s. Do this instead:
//MOV Time,CTR
ADD Time,Offset
...
Offset LONG 230
Other_value LONG 123
Time RES 1
ORG
Another_cog ...//
In this example, whatever’s assembled at Another_cog will get loaded into Time when the first cog loads. But we don’t care, since Time will get written over anyway.