Wrlong, use ram defined in spin in assembly
TransistorToaster
Posts: 149
Hello,
I am trying to use WRLONG in assembly to write to main memory. My code below is supposed to copy from a register (I put INA for figuring out how to do this) into main RAM.
VAR
bufferInMainRam[noparse][[/noparse]256]
PUB
cogstart(@asmStart,0)
DAT
org
mov pMainRam, #bufferInMainRam
movs :transferToMainRamLoop, pMainRam
:transferToMainRamLoop wrword ina,0
res pMainRam 4
I could not figure out how to specify a block of ram already defined in SPIN to the assembly section of the code. The compiler would flag an error at "mov pMainRam, #bufferInMainRam". What is the correct way?
This is a stupid question, but I have to be sure: Is it correct to say that the "res pMainRam 4" command allocated the ram in cog ram space?
I am trying to use WRLONG in assembly to write to main memory. My code below is supposed to copy from a register (I put INA for figuring out how to do this) into main RAM.
VAR
bufferInMainRam[noparse][[/noparse]256]
PUB
cogstart(@asmStart,0)
DAT
org
mov pMainRam, #bufferInMainRam
movs :transferToMainRamLoop, pMainRam
:transferToMainRamLoop wrword ina,0
res pMainRam 4
I could not figure out how to specify a block of ram already defined in SPIN to the assembly section of the code. The compiler would flag an error at "mov pMainRam, #bufferInMainRam". What is the correct way?
This is a stupid question, but I have to be sure: Is it correct to say that the "res pMainRam 4" command allocated the ram in cog ram space?
Comments
LONG myBuffer[noparse][[/noparse]256]
...
cognew(@asmCode, @myBuffer)
...
'ASM CODE:
asmCode rdlong cogRamVar, par
...
cogRamVar res 1
The idea is that the second argument of cognew (and the third parameter of coginit) appears in the read-only par register. So you can pass one pointer or value to your asm code using that.
Also, there is no cogstart function, only coginit and cognew. The res has also to be AFTER the label. And if you're reserving a long, use "res 1", not "res 4", the number is number of longs, not number of bytes here. Also, RES directives must be the last thing in your asm code - they can't be followed by asm code or long/word/bytes.
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Paul Baker
Propeller Applications Engineer
Parallax, Inc.
Yes, I remember debugging at least one hour a problem like that. INA can't be a destination register. eg. "test ina, #1 wz" won't work, a temporary copy has to be made... Paul, are INA registers the only ones that are like this? Can FRQA, CNT etc. be used as destination?
not permit this, or complain about it? Yes, existing code will need to be modified, but my claim is
that code needs to be modified anyway; if you really want to use a shadow register you should be
forced to declare that explicitly (using ina_shadow or some such). This is such a common trap.
The obvious problems here are:
1. djnz samplesCounter,:transferToMainMemLoopV1
should be
djnz samplesCounter,#:transferToMainMemLoopV1
Otherwise it jumps to the memory address stored in :transferToMainMemLoopV1, and would be equivalent to djnz samplesCounter, #pMainRam, which is obviously a bug.
2. jmp asmStart
same bug, should be jmp #asmStart
3. Adding a number won't help with the alignment - the end result is still not divisible by 4. Instead, I'd suggest declaring samples as
long samples[noparse][[/noparse]64]
This makes it long aligned. If you'd want to access it as bytes in Spin (it's no problem in asm, in ASM it doesn't matter if it's declared long or byte or whatever), use samples.BYTE[noparse][[/noparse]index] instead of samples[noparse][[/noparse]index].
4.The nop is unnecessary. It is needed only with self-modifying code, where movd or movs instructions or something similar are involved, like
movd readData, #register
readData mov r1, 0
won't work, but
movd readData, #register
nop
readData mov r1, 0
will work.
5. I'm not exactly sure what you're trying to do - currently you are writing longs into the array that contain numerical values from 62 to 1.
EDIT: If you're trying to move stuff from Cog memory to Hub memory, you have to use self-modifying code. The wrbyte/word/long instructions write the value of the destination into Hub memory, destination is not a pointer there.
Post Edited (Jasper_M) : 3/20/2007 10:01:26 PM GMT
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
--Jeff Martin
· Sr. Software Engineer
· Parallax, Inc.
Nonetheless, when it is intended it should be clearly written as such. For every
person who trips over this and posts it on the forum, there are probably a hundred
who trip over it and just figure one of:
1. The propeller is broken.
2. I can't get this stupid program to work; I am so stupid.
I mean, do we want to be an elite priesthood where you need to pay your dues
(trip over these issues and study enough until you understand them) before you
can even write a simple assembly language program? Or do we simply want our
programming language to be explicit in these issues, and require you to acknowledge
the different semantics of these shadow registers if and only if you use them?
Letting a neophyte "access" shadow registers using the name of the "normal"
registers, when he or she probably does not know of (nor wants to know of)
the shadow registers at all in this point, is doing them, and all of the rest of us,
a grave disservice.
Accessibility is Parallax's stock in trade. Let's not give it up here guys.
To the question: "I mean, do we want to be an elite priesthood where you need to pay your dues (trip over these issues and study enough until you understand them) before you can even write a simple assembly language program?"
I would say "Make it easier". There is so much to learn, and mistakes are so easy to make, it would be nice for the Tool to assist and guide.
Jim C
you just use jmpr (or something similar) with an unadorned label (or whatever other operand you want). We
already have call and ret which are just variants of jmp, so it's not like we're totally minimally orthogonal
anyway.
It's just like in Java. There's no difference between overriding a method and declaring a brand new method.
So if you make the tiniest error (order of arguments, type of arguments) when you intend one, you get the
other, and the compiler helps you not at all, and you spend the day debugging. C# got that one right.
you can use POD to debug your assembly program. Currently you cannot show main memory but I have it on the list for the next release.
If need assistance to prepare your file for debugging I can help you.
I'll check out the POD.
Jasper, rokiki
>I like this (the # thing). So jmp (and call) would require the #
It was a discovery for me to learn that here, the jump is absolute(with #) or indexed (without #). In general, most assembly languages have a different jump instruction identifier for an indexed jump so that's why I never bothered with the #.
>3. Adding a number won't help with the alignment -
That was to safeguard against writing on data before the array of bytes.
>5. I'm not exactly sure what you're trying to do - currently you are writing longs into the array that contain
>numerical values from 62 to 1.
>EDIT: If you're trying to move stuff from Cog memory to Hub memory, you have to use self-modifying code.
>The wrbyte/word/long instructions write the value of the destination into Hub memory, destination is not a pointer there.
You probably caught on that this was a baby step to understand how come my code was not working. It was erroneous in the branching, which I didn't know at that time. After learning the mistake I successfully implemented the self modifying code to work for the cogram to mainram copy.
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Paul Baker
Propeller Applications Engineer
Parallax, Inc.
Jim C
would you mind to post the final working code? I'm reading now different discussions trying to learn assembler.
This was is very instructive
Thanks
Jan
Here you go: