How to pass arguments to/from assembly language?

in Propeller 1
Please, could someone give a short, simple explanation of and a simple piece of code for, how to pass several parameters to an assembly-language routine and how to get several values back from that routine? Examples in this Forum are either too complicated to follow or are just an explanation without an example. Show me how to send three values and how to get two back. Seems like this should be an obvious part of the Propeller manual, but it's not. I need to use assembly language for speed. Folks, many of us are new to assembly language on the Propeller, so simplicity and clarity help more than complexity and obscurity. Thanks. --Jon
Comments
1. When you start the PASM cog, send it the address of a long parameter array. This address will appear in PAR at the assembly end. The first parameter should just be a true/false flag.
2. At the beginning of the PASM program, program a loop that waits for the first parameter to become non-zero.
3. When this happens, read the parameters from hub memory, i.e. at PAR + 4, PAR + 8, and PAR + 12.
4. Do your computations, and store the result at PAR + 4.
5. Then clear the hub memory at PAR to zero.
____
6. The calling program must first store the parameters in positions 1..3 in the long array.
7. After that, it must set position 0 to a non-zero value.
8. Then it just has to wait until position 0 becomes zero again.
9. At that point, it can read the result from position 1 in the array.
-Phil
var long command long param1 long param2 dat org 0 entry rdlong hub, par wz ' command? if_z jmp #entry ' wait until !0 mov hub, par ' hub = @command add hub, #4 ' hub = @param1 rdlong val1, hub ' val1 = param1 add hub, #4 ' hub = @param2 rdlong val2, hub ' val2 = param2 mov sum, val1 ' sum = val1 adds sum, val2 ' sum = val1 + val2 mov dif, val1 ' dif = val1 subs dif, val2 ' dif = val1 - val2 mov hub, par ' hub = @command add hub, #4 ' hub = @param1 wrlong sum, hub ' param1 = sum add hub, #4 ' hub = @param2 wrlong dif, hub ' param2 = dif mov val1, #0 wrlong val1, par ' command = 0 jmp #entry hub res 1 val1 res 1 val2 res 1 sum res 1 dif res 1 fit 496
Of course, you have to launch the cog -- do that with:cognew(@entry, @command)
I struggled with this for months trying to find useful examples. I can write the code but to get it into the C code was impossible.
Anyway I figured it out and here is the C code version. I believe C code runs faster than SPIN.
int main() { // Add two numbers. int Total, Parm1, Parm2; Total = 0; Parm1 = 2; Parm2 = 2; __asm__ volatile ( " mov %[T], %[P1] \n\t" // put parameter one into total " add %[T], %[P2] \n\t" // add parameter two to total : [T] "+r" (Total) // declare Total as output and alias it : [P1] "r" (Parm1), // declare Parm1 as input and alias it [P2] "r" (Parm2) // declare Parm2 as input and alias it ); print("Total: %d, Parm1: %d, Parm2: %d\n", Total, Parm1, Parm2); while(1) { // Add main loop code here. } }
Thanks for playing.
Mike
I wrote a simple assembly-language program to turn on two off-board LEDs at pins P8 and P9. I set the DIRA and OUTA pins properly within the AL program. If I end the AL routine with:
jmp $%
the LEDS stay lit because the AL program finishes and remains in an endless loop. It doesn't return to my SPIN code. I have seen examples that use the following instructions to stop execution in the cog:
cog ID
cogstop ID
In this case, the LEDs turn on for 0.5 microseconds and then turn off. I need them to remain on when execution returns to the SPIN code. Again, thanks for any help you can offer. --Jon
cog ID cogstop ID
I appreciate your clarification. But why do the statements above cause the I/O pins to change state, but the statement
jmp $#
does not? That's what baffles me.
Again, thanks. --Jon
the difference is that when you stop a COG it will reset dira and outa and let pins float again, as opposed to stay active and just jump on itself, doing nothing but keeping alive and keeping the pin states.
Mike
pasmcog := cognew(@entry, @command) ' launch pasm cog param1 := 2 ' set parameters param2 := 3 command := 1 ' enable pasm cog repeat while (command) ' wait for pasm to finish cogstop(pasmcog) ' kill pasm cog (if no longer needed)
If you want the pasm cog to maintain the state of IO pins then you must leave it running.Another thing you can do is use the flag as a switch for what you want to do in the pasm cog -- this is why I called it command. In the examples above it's a simple true-false flag, but you could easily compare the value in command with a known set and run a routine within the pasm cog on demand. See attached demo; it illustrates the use of pasm-coded subroutines. Since it contains IO control, it must stay running.
The attached files show my attempt. I need very high-speed serial output with a clock to test other equipment. All I get out is one long (0.5-sec) pulse on the clock like. I have spend days on this code and got nowhere. I'm about to switch to an Atmel or ARM-Cortex and program what I need in C.
Thanks for any assistance you can provide --Jon
In the PropTool library there is an object SPI_Asm.spin that does that.
The code below is an excerpt from that object showing how the spin "calls" the Pasm (which was started earlier). Look at the full code from the library and the corresponding demo.
PUB SHIFTOUT(Dpin, Cpin, Mode, Bits, Value) ''If SHIFTOUT is called with 'Bits' set to Zero, then the COG will shut ''down. Another way to shut the COG down is to call 'stop' from Spin. setcommand(_SHIFTOUT, @Dpin) PUB SHIFTIN(Dpin, Cpin, Mode, Bits)|Value,Flag ''If SHIFTIN is called with 'Bits' set to Zero, then the COG will shut ''down. Another way to shut the COG down is to call 'stop' from Spin. Flag := 1 ''Set Flag setcommand(_SHIFTIN, @Dpin) repeat until Flag == 0 ''Wait for Flag to clear ... data is ready Result := Value PRI setcommand(cmd, argptr) command := cmd << 16 + argptr ''write command and pointer repeat while command ''wait for command to be cleared, signifying receipt
https://www.parallax.com/news/2015-02-26/download-new-book-jon-titus-experiments-propeller-quickstart.
Descriptions start in Experiment 11. Again, thanks for all your help. --Jon