From SPIN to PASM - Code Documentation Style - Just curious
Beau Schwabe
Posts: 6,568
I realize that this can't be done in every case because of the complexities of the program, but on occasion when the initial program you write starts in Spin and you later convert portions of it to PAsm, would the type of documentation I have included below be helpful from an educational perspective for someone trying to learn PAsm?
...code on the left is PASM, code on the right is a descriptive SPIN equivalent. The single remark stroke is the literal translation from Spin for that 'block'. A 'block' defined by the group of PASM instructions NOT separated by a space. A double remark referring to an implied translation from Spin for that 'block'. Squiggle brackets indicate where in the PASM block a Spin conditional (i.e. IF/THEN/ELSE) takes place.
RepeatLoop1 'repeat mov temp, _ProgramMemoryAddress ' characterbyte := ProgramMemory[offset] add temp, _offset rdbyte _characterbyte, temp add _offset, #1 ' offset += 1 add _ColumnIndex, #1 ' ColumnIndex +=1 mov temp, #text#cols ' if ColumnIndex > (text#cols -2) or characterbyte == 13 sub temp, #2 cmp temp, _ColumnIndex wc { if ColumnIndex > (text#cols -2) } 'C flag is clear if V1 => V2 'C flag is set if V1 < V2 cmp _characterbyte, #13 wz { if characterbyte == 13 } 'Z flag is set if V1 = V2 if_c_or_z add _LineIndex, #1 ' LineIndex += 1 if_c_or_z mov _ColumnIndex, #0 ' ColumnIndex := 0 cmp _LineIndex, _Index wc ' if LineIndex => Index 'C flag is clear if V1 => V2 'C flag is set if V1 < V2 if_c jmp #RepeatLoop1 ' quit '' Jump to RepeatLoop1 if above condition is false '' cmp _characterbyte, #13 wz ' if characterbyte <> 13 ''(redundant code, Z flag previously set with same compare in above code) if_nz sub _offset, #1 ' offset -= 1
...code on the left is PASM, code on the right is a descriptive SPIN equivalent. The single remark stroke is the literal translation from Spin for that 'block'. A 'block' defined by the group of PASM instructions NOT separated by a space. A double remark referring to an implied translation from Spin for that 'block'. Squiggle brackets indicate where in the PASM block a Spin conditional (i.e. IF/THEN/ELSE) takes place.
Comments
It all depends on the quality of the original code and its comments. In the case you've posted, the Spin code and its comments are pretty good in terms of understandability. I can well imagine another program with cryptic variable names and useless comments that is converted to assembly with the comments being the original Spin code and the converted code being even less understandable than the original Spin code.
I can also imagine assembly code that's not a direct translation of Spin code, that's optimized in some fashion where using the Spin code as comments may make it less understandable than well crafted comments that apply to the actual assembly code.
It all comes down to trying to comment as if you're telling a story about the code and what it does. Sometimes it's useful to tell part of the story literally with lots of details and sometimes it's useful to tell other parts of the story metaphorically using the meaning of the actions rather than the actions themselves.
Understood, ... this is more of an exercise for someone wanting to learn PASM that has a good grasp with SPIN. ...and agreed, there are some things that are difficult at best to describe with comments because the translation from one to the other is implied more so that it is followed in a literal step-by-step or line-by-line architecture. So heavy commenting can be more cumbersome trying to convey what's implied sometimes.
Below is a whole section where original SPIN code was converted to PASM with comments in the style mentioned above. I just wonder if this helps or confuses anybody more ...
Here's how I like to do it: I find vertical scrolling easier to consume than horizontal, but that's just me.
Each SPIN statement is followed by the block of code that aligns with it. That does not always happen, but when it does, it's kind of nice. Other more elemental comments then run along side the code, in conversational style, detailing the sub-operations necessary to reproduce the SPIN program element in the block.
Overall, doing this is a help, no matter the style. After looking at the code Kye has done, I think lots of comments is always better, unless the comments are just Smile. Even then, if there is a chance that something good is in those comments, I'll take it. For my own code, I find the block style above readable, and the most valuable part of it is seeing the little "chunk tasks" to combine with the whole. It's not always clear to me what the progression of thinking was, and often that's important. I sometimes go long periods of time between being able to build on a project. Lots of little things get forgotten. The blocks tend to help me reconstruct where I was at on things, or if looking at another persons code, where they were headed as well.
There is also a difference between a learning code example, and just comments on code that is just code, authored for whatever reason. Once a person begins to grok how PASM is going to work, I'm sure they will move to the next level, just doing the kinds of things Eric mentions below.
One thing I'm still not clear about is which characters are 'special'. @ seems to be special in Spin. Ditto ~. So is #. Using the same logic, is _ special? ie is _offset different to offset, or is it just a variant on my_variable?
A style of commenting that I find very helpful is to comment excessively the first instance of something that a reader might find confusing. Later instances of that code could have briefer comments.
Several times I have looked at pasm and thought it was spin, due to some similarities. I believe they mesh together and it would be beneficial to know how to put small sections of pasm in spin and call it into play. This fits well with what you are doing. We could have a place to consult with lots of these routines, especially the ones that are small, easily called and used.
Right now, there's information all over the place. Only those guys working with the prop chip for years seem to have put it all together in their minds. Just starting out, its a challenge. So a place with converted routines would be welcomed for spin programmers wanting to incorporate some pasm into their code, for gains of speed and less code overhead.
Humanoido
'
Sounds like the start of an awesome project!
'
I think you would both get carpal tunnel before you had to many REM's for me, But I do agree that some times the end result is more important then the code that got it there.
Its kind of a paradox I guess.
'
I find what both of you have posted to be very informative and easy to understand.
'
I wish I had more time to do this sort of thing, oddly I sorta like mundane, tedious translations like this ... :-) ... I'll see what I can do during longer LVS (Layout Versus Schematic) runs with Propeller II if I can fit something like this in as I'm writing objects.
Dr_Acula,
The @, @@, ~, ~~, # aren't necessarily any more special in Spin than they are in Pasm. One big difference is that Pasm has specific fields such as Instruction, Destination, Source, Conditional, Flags, etc. that aren't always conducive to using those 'shortcuts' that are actually easier to use in Spin.
The _ is something that I use, especially when converting something from Spin to Pssm. The reason is that during the 'migration' and testing the same variable name can't be used in both Spin and Pasm simply because it's already been declared. Adding a _ to the beginning tells me that it possibly has a duplicate. This method also has a way of keeping the meaning of the variable intact when I see it visually.
ALL
Here is a kick-start of the type of vision I have... This is basically a step-by-step approach to converting a Spin PUB routine into a callable Pasm routine.
Suppose we have a program like the one below and we want to convert the SpinSimple
routine to Assembly...
...The first thing that we are going to want to do is create an Assembly header
that can be called from SpinSimple.
...next we need to asses the variables we are using in Spin and create duplicates
in Pasm.
... now we need to call the Pasm from Spin and copy the necessary variables from
Spin into Pasm.
...next we want to take the first equation 'C := A + B' and incorporate that within Pasm.
at this point we can remove or remark the Spin version of this equation.
... but why doesn't this program work? ... Welcome to Parallel processing and one of the first gotchas!!
The program does exactly what you told it to do, but there are no LED's lit? with the example numbers 1 and 2,
C should equal 9, and LED's 0 and 3 should be lit. Why not?
The answer is because when you launch the cognew, the Pasm program loads and starts the process of Adding
A and B, but at the 'same time' (or at least after the cog has been loaded) the original cog that
called the Pasm has already started evaluating the answer of _C from C + C + C and arives at an answer of
zero BEFORE the cog that was called has time to finish.
What to do? There are a couple of things that can be done. One is to insert a delay after the new cog
has been started. This is wasteful as far as idle cpu time.
...another method is to use another variable as a 'flag' within Pasm that can be cleared when it's job is
complete.
Now, the last two programs should work, one uses a delay (<- ok) , and the other uses a flag (<- better). What we
want to do now is move the remaining portion of Spin into PAsm also. Right now all we have is a hybrid PUB routine.
So moving C := C + C + C into Asm would look like this ...
...So that's basically a step-by-step for creating a custom Pasm PUB routine.
Beau Schwabe
This is outstanding!
It's like you were reading my mind and know what we need for our projects.
Humanoido
Ok so the general consensus, I gather ... not only from this thread, but several people that I talked to at the EXPO ... Is that I will try to adopt and/or adapt this method of commentary to my future objects where this type of commentary is applicable. This way if you at least understand Spin you get a good idea of what the Pasm code equivalent is doing.
At the same time I will try to compile various snippets, tricks, shortcuts that I may discover and learn along the way. And who knows, at some point maybe a book will form out of the debris ... "101 ways to PASM your SPIN" :-)
Thanks & keep up the good work!
OT - is there a "rumored" date on the release of the Prop II? I do hope its 32bit with 64 i/o's
MPLAB has a View/Disassembly Listing which is quite handy. Like the following...
128: if (character >= '0' && character <= '9')
0070 0E30 MOVLW 0x30
0072 5CDF SUBWF 0xfdf, W, ACCESS
0074 E336 BNC 0xe2
0076 50DF MOVF 0xfdf, W, ACCESS
0078 0839 SUBLW 0x39
007A E333 BNC 0xe2
The 128: line is a line from your C program, then below that is the assembly code for that one line. You can see that the assembly code is using ASCII 0 (30) and ASCII 9 (39) [as it should in this case].
And you can see how the same line in your higher level language program is translated by the compiler into assembly.
Then you can look up one assembly line at a time (MOVLW, SUBWF, etc.) and learn what each is doing.
And along with that read the processor data sheet and learn what each command is doing "inside" the processor.
I think one of the first tools of this nature I used was DDT or Dynamic Debugging Tool. With that I could "peek inside" programs and see how they worked. Here is a bit on that...
http://www.iso.port.ac.uk/~mike/interests/chistory/documents/cpm-22-manual/ch4.html
FYI - ASCII codes...
http://en.wikipedia.org/wiki/ASCII
This is also how I learned Assembly and sort of where I would like to see this go as a teaching tool. Not necessarily a symbolic compiler from Spin to Pasm, but a text translator instead.
Using your example the output might look like this...
The latter is hopeless when displayed in the forums code boxes as you have to scroll left and right all the time to follow it. Even when opened in a wide text editor window its hard work to read. The example in Beau's last post is much easier on the eyes.
Like Beau I got into assembler this way however in my day it was:
1) Write what you want to do in ALGOL. This was never compiled but just used as a pseudo code, like Spin or C in the examples here.
2) Write your 6809 assembler code from the above pseudo code.
3) Manually translate the assembly language to hex bytes for the EPROM programmer.
It was some years later that I first had the luxury of a real compiler and could see what it produced.
Beau:
Well of course that is what a lot of compilers do. High level language text in, low level assembly language text out. You then use an assembler and linker to get the final binary.
So that teaching tool would be a real compiler. It's PASM output could be compiled into a binary with the Prop Tool.
... I guess that means ... Hmmm, time to go to the think tank. :smilewinkgrin:
1. In my Zero footprint debugger, it is possible to see (by tracing) exactly what spin code translates to in pasm. Of course, all the overheads of spin are present including all the pushes and pops.
2. A much easier way is to look at the optional listing that bst and homespun create.
Now of course, both these are bytecode expansions and not the original spin code.
I wonder if a tool to list the pasm equivalent of a line of Spin code could be useful??? Or will it generate just too much 'fluff' to be useful ???
I think that would be wonderful!
It is very difficult to "think" in assembly. Everything goes so slow and one small step at a time. (Slow as in all the lines of code you need to write to do something simple.)
If a person learning this can see how a line from spin translates into many lines of assembly, then look at it and think huhhhh?????
Then figure out what the first assembly line is doing.
Then the next line.
And the next...
Then suddenly... :idea:
FYI - I learned how things worked when I was young by taking things apart and seeing what was inside.
And that was what I was doing too when I learned assembly. I had a simple working program to examine. Then a tool to look inside and see what was there (the disassembled code). Then a book to look up what each assembly command did.
Yes, but the topic here is about imparting PASM, not byte code, skills to beginners by documenting PASM code with spin syntax comments.
This has led Beau to the natural conclusion of, why not a translator Spin to PASM? Which is actually a compiler anyway.
I'm also concerned about the "fluff" problem here. The interesting techniques in PASM cannot even be represented in Spin, at least not in any concise sensible way. For example:
1) The heavy use of JMP in a non structured ways.
2) The difference between variables in COG or in HUB.
3) The distinction between signed and unsigned arithmetic.
4) How would you represent the coroutines of FullDuplexSerial?