How does ORG work?

Over on the Kye SD thread I have posted a rather long question regarding building self contained cog code that can be loaded off an sd card and which can exist separately from its supporting high level code in Spin/C/Basic.
The 'standard' way to pass variables to a cog is with PAR and that usually points to a list of variables and/or arrays.
Kye is doing something different and is using Spin to poke variable values into the hub ram that contains the cog code, prior to loading a cog.
This has an intriguing advantage in that it saves a lot of moving PAR data around in the cog. Because there is more hub memory for spin than cog memory for pasm, memory in cog is more precious than in hub.
So I thought I would take this a bit further and write some cog code that has the program at the bottom of memory, and the data at the top of cog memory.
but using F8, this does not seem to produce a whole lot of blank space in the middle of the program. Am I using ORG correctly?
And, going off on a tangent, if this is not possible, is it possible to put all the variables at the beginning of a program, so their location ends up in a known place?
This does seem to work, and it also pads out longs so that the 7 bytes above occupy 2 full longs.
But the disadvantage of this method is that it is more standard to put variables at the end of the program.
Thoughts would be most appreciated.
The 'standard' way to pass variables to a cog is with PAR and that usually points to a list of variables and/or arrays.
Kye is doing something different and is using Spin to poke variable values into the hub ram that contains the cog code, prior to loading a cog.
This has an intriguing advantage in that it saves a lot of moving PAR data around in the cog. Because there is more hub memory for spin than cog memory for pasm, memory in cog is more precious than in hub.
So I thought I would take this a bit further and write some cog code that has the program at the bottom of memory, and the data at the top of cog memory.
CON
_clkfreq = 80_000_000
_clkmode = xtal1 + pll16x
PUB Main
coginit(1,@cogstart,0) ' cog 1, cogstart, dummy value
DAT
org 0
cogstart wrbyte testvalue, testvariable ' test value A
jmp #cogstart
org 400
testvariable long 5000 ' test memory location 5000
testvalue long 65 ' ascii A
fit 496
but using F8, this does not seem to produce a whole lot of blank space in the middle of the program. Am I using ORG correctly?
And, going off on a tangent, if this is not possible, is it possible to put all the variables at the beginning of a program, so their location ends up in a known place?
CON
_clkfreq = 80_000_000
_clkmode = xtal1 + pll16x
PUB Main
coginit(1,@cogstart,0) ' cog 1, cogstart, dummy value
DAT
org 0
jmp cogstart
v1 byte 65
v2 byte 66
v3 byte 67
v4 byte 68
v5 byte 69
v6 byte 70
v7 byte 71
cogstart wrbyte testvalue, testvariable ' test value A
jmp #cogstart
testvariable long 5000 ' test memory location 5000
testvalue long 65 ' ascii A
fit 496
This does seem to work, and it also pads out longs so that the 7 bytes above occupy 2 full longs.
But the disadvantage of this method is that it is more standard to put variables at the end of the program.
Thoughts would be most appreciated.
Comments
-Phil
I guess I grew up with ORG in 8080 and Z80 where it then started compiling from that location. I had a look through other instructions but I am not sure there is a way to put the variables at a known offset from the beginning of the assembly code.
So there is still plan B where the variables go at the beginning and the code comes after?
Plan B where the variables go at the beginning and the code comes after.
Yep, you mean like this:
1) Put the variables that must be initialized prior to COG loading at the beginning of your DAT section. Except location 0.
2) Follow those variables with your PASM instructions.
3) Make the location zero a JMP to the start of your code.
For example something like this:
PUB startMyCog(parParams) P0 := 1234 'Set up parameter variables in DAT for loading with COG code P1 := 5678 P2 := 0912 P3 := 3456 cognew(@enter, parParams) 'Start a COG for this object with PAR params DAT org 0 enter useMeLater jmp #start 'This location can be used as a variable when running P0 long 0 'These variables are "parameters" to to be set prior to COG load. P1 long 0 P2 long 0 P3 long 0 start 'PASM code goes here 'Start fetching PAR params maybe
All you really need to know is the start of the variable list. And it does help if all the variables are grouped together.
A problem that might arise is that you change the pasm program and add one line of code. If the variables come after the pasm code, that changes the location (ie the offset from org 0).
I had an idea that you could always put the variables at a known location, eg at 400. Or maybe count down from the top if that is possible. But putting them at the beginning might be the best answer - then you know that however much you change the pasm code, the variables start at long number 1.
This concept could become useful for Andreys IDE, where you might use the same PASM binary for C, Spin and Basic, and all that changes is the supporting code.
That is correct.
To be extremely precise: ORG does not affect anything on the Prop side, ORG just specifies the offset that the assembler uses to calculate address in the resulting machine code.
org 0 start jmp #next org 16 next jmp #start
In other assemblers the second ORG changes where the code is placed in RAM. Thus the code would assemble to a jump instruction at address 0 and a jump instruction at address 16 with a bunch of zeros or FFs in between. Not true for the Prop Tool, which would generate the following:HUB[+0] COG[0] jmp #16 HUB[+4] COG[1] jmp #0
So the second instruction is stored immediately after the first instruction in HUB RAM, thus gets loaded into register 1 in COG RAM. But the ORG 16 means the "next" label gets translated to 16.Therefore, unless you are doing dynamic overlays, there is no reason to use anything other then ORG 0.
I love this forum - thanks++ to everyone for the prompt help!
long 0[number]:
org 0 'code long 0[$400-$] 'an "org $400" with right address in cog var1 res 1 var2 res 1 ...
But this needs more HubRam than putting the variables at begin.Andy
What are you doing there - is $ a pointer to the current program counter?
No problem with taking more hub ram - I've actually made all 'cogjects' 496 longs in size so even short programs are this long.
There is no real cost in terms of hub ram, because the data comes off the sd card and is put in a temporary array which ends up on the stack, and this array is discarded when the function ends. That is the C solution, and an equivalent Spin solution could poke the data to a common 2k space in hub ram and load all 7 cogs through that one common code space.
I need to check out your $ code!
here long 0[$400-here]
Andy
I haven't quite got the code on post #16 working - I need to test the numbers.
CON _clkfreq = 80_000_000 _clkmode = xtal1 + pll16x PUB Main coginit(1,@cogstart,0) ' cog 1, cogstart, dummy value DAT org 0 cogstart wrbyte testvalue, testvariable ' test value A ' nop ' nop ' nop ' nop jmp #cogstart long $FFFFFFFF[494-$] ' pad with FF, n=494 which is 496 minus the two variables below testvariable long 5000 ' test memory location 5000 testvalue long 65 ' ascii A fit 496
F8, note that the variables start at hex $7D0, uncomment the NOPs and F8 again and the variables are still at $7D0.
Uses 494 because this is 496 minus the two longs at the end. So just add up the number of longs and this is the number.
With loading a self-contained object directly from the SD card, there is no problem about filling unused cog space as there would be if it resided in hub.
Don't you need a #?
here long 0[$400-#here]
I've never used a # this way but I thought you needed one if you're referring the location and not what's in the location.
Duane
-Phil