[RESOLVED] SPIN stub code for learning ASM
Mightor
Posts: 338
hey there,
I am trying to learn ASM for the Prop but the one thing I keep running into is how to make use of these bits of ASM code that I create. For example, I copied the Divide algorithm from deSilva's ASM guide:
However, I am not sure how I could write some SPIN code that could get the results back from this kind of routine. I have figured out how to pass stuff to it using the cognew and passing an address to an array of longs, for example. This is what I did for my PWM code.
I'd like to be able to use something like FullDuplexSerial to display the results of my little ASM programs so I can see what tweaking this, that or the other does to a result. Right now I have no idea how to do something like that. If some of the gurus could shed some light on this, that would be great! There is no way to call the ASM code (and get the return value) from inside SPIN code without calling cognew, is there?
Gr,
Mightor
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
| To know recursion, you must first know recursion.
| I'm afraid I might be phobophobic.
Post Edited (Mightor) : 9/9/2007 11:49:56 AM GMT
I am trying to learn ASM for the Prop but the one thing I keep running into is how to make use of these bits of ASM code that I create. For example, I copied the Divide algorithm from deSilva's ASM guide:
' Divide x[noparse][[/noparse]31..0] by y[noparse][[/noparse]15..0] (y[noparse][[/noparse]16] must be 0) ' on exit, quotient is in x[noparse][[/noparse]15..0] and remainder is in x[noparse][[/noparse]31..16] ' divide shl y,#15 'get divisor into y[noparse][[/noparse]30..15] mov t,#16 'ready for 16 quotient bits :loop cmpsub x,y wc 'if y =< x then subtract it, set C rcl x,#1 'rotate c into quotient, shift dividend djnz t,#:loop 'loop until done divide_ret ret 'quotient in x[noparse][[/noparse]15..0], rem. in x[noparse][[/noparse]31..16]
However, I am not sure how I could write some SPIN code that could get the results back from this kind of routine. I have figured out how to pass stuff to it using the cognew and passing an address to an array of longs, for example. This is what I did for my PWM code.
I'd like to be able to use something like FullDuplexSerial to display the results of my little ASM programs so I can see what tweaking this, that or the other does to a result. Right now I have no idea how to do something like that. If some of the gurus could shed some light on this, that would be great! There is no way to call the ASM code (and get the return value) from inside SPIN code without calling cognew, is there?
Gr,
Mightor
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
| To know recursion, you must first know recursion.
| I'm afraid I might be phobophobic.
Post Edited (Mightor) : 9/9/2007 11:49:56 AM GMT
Comments
The simplest way is to store addresses of the variables you want to communicate through into DAT cells (as I did it with "patternAddr").
You can use as many as you like.
The good thing is, that you need not go through incrementing PAR all the time!
There is a special technique for ADVANCED users: you can also use the DAT cells "remaining" in the COG as commucation cells themselves. But wait until the COG is loaded before using them
See my example for.... (searching...)
Edit: It's here http://forums.parallax.com/showthread.php?p=669873 the 9th posting or so...
Post Edited (deSilva) : 9/1/2007 9:31:37 PM GMT
I really kept it as simple as I possibly could. I must be doing something wrong, obviously, or the program would be printing "answer: 16" all the time. Could someone please tell me? I'm quite lost. I am sure the answer to this problem will result in a very loud "DOH!" from my side.
Gr,
Mightor
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
| To know recursion, you must first know recursion.
I did look at it and for the first cog, it passes "0" as the argument and uses RDLONG DIRA, patternAddr (it's in the ex02a section). patternAddr has been assigned the address of aCounter as its value. So why would it work here and not in my example? I am storing the address of the answer variable in aAddr in much the same way. I'm not quite following this.
Gr,
Mightor
This is the code I was looking at:
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
| To know recursion, you must first know recursion.
I think I agree with Mightor in that in ex02A the variable patternaddr exists in both spin and dat space and is initialized in spin with the address of aCounter, so within asm we should have knowledge of aCounters location and should be able to use wrlong to write to it. does the address of aCounter have to be a multible of 4? how can we ensure that?
my code isn't working so I don't want to argue that I'm right, I just don't see yet where I'm not correct.
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
I'd rather have a bottle in front of me than a frontal labotomy
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
I'd rather have a bottle in front of me than a frontal labotomy
for example say I have a var long buffer[noparse][[/noparse]7000] and when a new cog is started, par contains the first location of buffer. In asm will there ever be a problem with writing back to all 7000 locations?
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
I'd rather have a bottle in front of me than a frontal labotomy
Your last situation is never a problem. The assembly code can calculate any address in HUB memory and then can read and write to it. Remember that HUB addresses are byte addresses, so you'd have to multiply your buffer index by 4 (shift it left by 2), then add PAR to it. The result can be used with a RDLONG/WRLONG.
It's been mentioned before that RDWORD/WRWORD ignores the least significant bit of the address and RDLONG/WRLONG ignores the least significant 2 bits of the address.
(1) The COG is not loaded correctly You have to provide the ADDRESS of "assign" (= @assign) as parameter to COGNEW
(2) The COG just starts at its address 0, there is no "call" or whatever, so there can be no RET! Use either an endless loop, or kill the COG
Mike, this is confusing what you were saying. "aAddr" has been set quite correctly by Mightor in the first line of his main routine.
I am not a friend of using PAR, as it creates an additional level of indirection, that can be useful, but in most cases is not
I was running into roadblocks with instructions not taking any more than 9 bits. I should not have been surprised I guess but in the back of my mind I was thinking, "32 bit processor should be able to mov 32 bits", such as the decimal value 7000 from an initialized var in DAT to t1 for example for decrementing and testing at th end of a loop. I ended up splitting it up into two eight bit sections and shifting the MSBs up and adding the lower.
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
I'd rather have a bottle in front of me than a frontal labotomy
As to one of your other questions: When stating something as LONG, whether in DAT or in VAR it will always be aligned correctly. When you are not in real need for space I should not recommend using WORD, as there are too many peculiarities with it. They can be confusing, and in most cases LONG will do fine. There is no penalty for it, as you might expect from your knowledge of other processors.
BTW my code is at another computer and I need to go look at it again with fresh eyes. The main symptom is this (trying to remember from last night). the code is a take off of the IR_kit, In spin I simply sampled the input connected to an IR 38KHz receiver and put ones or zeroes in successive locations in a buffer after the first input pulse was detected.
Then I thouhgt why not convert it to asm and learn something useful. So I ported it to asm and now when I first hit the input with my IR remote it spits out serial data but it should not. The serial dump should not take place until I see a byte in my serial receive variable. The receive variable is what I declared as a byte after the buffer of 7000 longs that I used as a destination for the ir input bits. (one per long) I'm afraid that the asm code is writing to my serial input byte somehow.
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
I'd rather have a bottle in front of me than a frontal labotomy
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
I'd rather have a bottle in front of me than a frontal labotomy
No longer am I using PAR to find my buffer's address. The method of declaring the var in DAT using SPIN to initialize a pointer works well. don't know why PAR did not work for me.
I had to change my DAT var from a reserved word to a long (the buffer pointer). What is the difference? Looks like the RES is only viewabe in the asm ie cog and the "var_name long value" declaration is available to the whole object. Spin and asm. or at least a copy is sent to the new cog with the address that SPIN put there before spawning the new cog.
The SPIN variable for receiving serial data is still a byte and it is declared before the variables that are used by the asm. All asm vars are declared with one "LONG" and seperated with commas.
Also learned that cnt cannot be used directly as source data with wrlong since it is the address to the cnt register. mov ing it to a local var first then using wrlong does the job.
can you tell I'm new at asm? Since SPIN is not compiled and does run rather slowly I thouht it was a good enough excuse to spend some time learning asm. I did it once in school for the 8088, this seems better than what I remember. I appreciate the enthusiastic help! thanks.
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
I'd rather have a bottle in front of me than a frontal labotomy
RES takes no space in the HUB! When defining it, it is just a bookkeeping remainder for the assembler which cell number (!) to put into an instruction or DAT preset when used. There is no reason why SPIN shall not "know" of this number, but it is NOT a HUB variable, and the simple minded user could be confused...
RES is usefull to save HUB memory, when you use COG vectors of - say - length 256 in 8 different COGs which otherwise would lead to 8kByte absolutly redundant HUB!
Right!
Always remember: VAR is re-sorted (LONG, WORD, BYTE) - DAT is padded
This is just fine
No, not exactly! All "special registers" have a "shadow" (=last 16 cells in each COG). Only "dest" is wired to these cells, not "source". This becomes aware to you only in case of CNT, INA, INB, PHSA and PHSB -- just thinking: PAR as well?? I'll check! So the general rule is: Never READ a special register from "dest" position "READING" happens in case of all read-modify-write instructions, which are many. The COG is a Two-Address-Machine and so the name "dest" is a little bit confusing - it is ALSO the destination
Post Edited (deSilva) : 9/2/2007 9:53:06 AM GMT
It's not printing out "16" like it should. What am I missing here?
Gr,
Mightor
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
| To know recursion, you must first know recursion.
As far as the RES vs. declare long in DAT, I was made aware that I was doing something wrong because the compiler complained apparently because Spin was trying to access a RES declaration and it looked like an uninitialized variable error.·
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
I'd rather have a bottle in front of me than a frontal labotomy
Could you attach some of the code you've written so I can have a look at it?
Thanks,
Mightor
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
| To know recursion, you must first know recursion.
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
I'd rather have a bottle in front of me than a frontal labotomy
Except MOV nearly all instructions have "dest" as source data
It says it just does not know this name; that will happen also when you use the name of a local variable of another routine..
Gr,
Mightor
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
| To know recursion, you must first know recursion.
I was referring to the FIRST PARAMETER of COGNEW, which is the address where it loads the COG from. You have to state "@assign" here, not "assign"!
Do I here: "Oh what an idiot I have been"?
Thanks for your seemingly inexhaustible patience!
Gr,
Mightor
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
| To know recursion, you must first know recursion.
take a look at your wrlong instruction, it accesses PAR directly and it is not allowed, move Par to a local first and try that, I did the same thing.
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
I'd rather have a bottle in front of me than a frontal labotomy
PAR behaves as expected as a "typical" shadowed special register
Study this test program ... It's always the same program btw, variants of which I certainly posted 4 or 5 times now...