asm functions
Graham Stabler
Posts: 2,510
If I have two pieces of related asm code that I want to act as functions, so I want an object that sits there waiting for a call, then does one or the other of these two calculations and returns the result(s).
What is the best way of implementing this? In particular how do you handle which asm segment is being called and how best do you handle the returned variables especially if there are more than one?
I'm sorry my question is not more clear, I'm completely happy with an asm loop chugging away updating some global variables with wrlong and then having functions just to read the global variables but in this instance I want to instigate the running of a code section and return more than one variable at a time, I guessed I should probably be passing pointers to global variable space defined in the main spin function but I'm not sure if that's the way to do it.
Graham
What is the best way of implementing this? In particular how do you handle which asm segment is being called and how best do you handle the returned variables especially if there are more than one?
I'm sorry my question is not more clear, I'm completely happy with an asm loop chugging away updating some global variables with wrlong and then having functions just to read the global variables but in this instance I want to instigate the running of a code section and return more than one variable at a time, I guessed I should probably be passing pointers to global variable space defined in the main spin function but I'm not sure if that's the way to do it.
Graham
Comments
An example of this is the module OS_loaderInit in my Propeller OS. This is an assembly routine to do I2C I/O and takes a 2 long parameter block and returns status information in the same block. Although only one bit in the first long is used to signal busy/done, the principle is the same.
Post Edited (Mike Green) : 10/13/2006 11:56:54 PM GMT
I had one asm cog read data from a WAV file stored in an SD card. It writes 4 bytes as a long into one hub variable, then sets another hub variable to "4" to indicate that four bytes are ready. The DAC player asm cog monitors the "ready" hub location, and when it contains "4", the DAC cog reads the data variable, then writes "0" to the "ready" variable.
(The "4" was because I was thinking to maybe transfer more than 4 bytes per "ready" flag, if the player needed the extra speed, but with this single long transfer mechanism, the player can play 16 bit stereo, 44 kHz, which is good enough for now.)
My project manages multiple variables like what you need. As well as the actual file data transfer, the SD card cog and its calling spin code share about 8 or 10 FAT filesystem variables, and the DAC cog and the calling spin share about half a dozen WAV sound parameters. There's no real trick to addressing them; like Mike says, you just add an offet of 4 to PAR for every hub variable away from the original hub address passed in when you start the asm cog.
I'm still trying to work out a clean way to build structures of these variables that can be known to the managing spin code and both asm cog codes, sort of like a separate include file. As things are now, when I add or rearrange the hub variables, I've got to keep both the card asm and the DAC player asm correctly updated, and it's all too easy to mess things up. I've started to play around with sticking a third asm cog to be a data buffer between the SD card cog and the DAC player cog, so it's only going to get harder to manage all the variables.
The only other way I can think to have two cogs communicate would be through doing the same sort of thing through a couple of I/O pins. I looked into that for the WAV player, but after I sketched out all the support code needed to manage the bitwise communication, the time consumed by all the code far exceeded the worst case of communicating through the hub.
David
If you look at 'graphics.spin', then you should see similarities with the code below. Also, the VGA graphics Demo at the link below uses this method.
http://forums.parallax.com/showthread.php?p=606957
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Beau Schwabe
IC Layout Engineer
Parallax, Inc.
Post Edited (Beau Schwabe (Parallax)) : 10/14/2006 4:43:23 AM GMT
I was going to ask another question but I think I might have just answered it myself, I've seen programs where variables used in the asm are set directly by the spin code, I wondered why I couldn't do the same to enter the variables and get the return values. I've just realized that I only ever see that happening in the start function for that object so presumably its OK because the asm cog is begun with those values. However once started its wrlong and rdlong all the way.
Graham
I was curious about one part of your parameter passing routine:
mainloop rdlong t1,par wz 'wait for command
if_z jmp #mainloop
movd :arg,#arg0 'get 8 arguments
mov t2,t1
mov t3,#8
:arg rdlong arg0,t2
add :arg,d0
add t2,#4
djnz t3,#:arg
mov AddressLocation,t1 'preserve address location for passing
In this section, you add "d0" to :arg, an address, where d0 is a constant, $200. Seems like this winds up modifying the rdlong command, by adding 1 to the destination field, thus pointing to the next assembly arguement location. Is that correct?
Thanks,
Jim C
See this recent thread and also check out the definintion of movd and movs
http://forums.parallax.com/forums/default.aspx?f=25&m=148004
Graham
The technique you mentioned, that of setting up constants in the DAT block prior to a COGNEW only works because the COGNEW copies the whole block
of 512 longs into the cog's memory before starting it. The values set by the SPIN start routine get copied along with everything else. As you've noticed,
once they're copied, they're not accessable except to the assembly program running in the cog.