How to use MOVD?
Mightor
Posts: 338
Hey peeps,
I have yet another ASM question...
I was looking at Beau's FunctionEngine code (Click ->here<- for thread, and ->here<- for attachment) and I tried very hard to figure out what it is that movd does. Here's a little snipped of the relevant code:
Well, at least I hope this is all of the relevant code, in any case both the thread and attachment are up ^ there. So my question is, what does this movd do and more importantly what does it cause?
I am basically trying to graft the setcommand code into my own to allow for more control over the PWM signals generated by my code. However, rather than trying to copy this stuff verbatim, I'd much rather have at least a basic grasp of what it does (in case it's not working as I want/need it to).
Gr,
Mightor
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
| To know recursion, you must first know recursion.
| I'm afraid I might be phobophobic.
I have yet another ASM question...
I was looking at Beau's FunctionEngine code (Click ->here<- for thread, and ->here<- for attachment) and I tried very hard to figure out what it is that movd does. Here's a little snipped of the relevant code:
' Function Engine - main loop ' loop rdlong t1,par wz 'wait for command if_z jmp #loop 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
Well, at least I hope this is all of the relevant code, in any case both the thread and attachment are up ^ there. So my question is, what does this movd do and more importantly what does it cause?
I am basically trying to graft the setcommand code into my own to allow for more control over the PWM signals generated by my code. However, rather than trying to copy this stuff verbatim, I'd much rather have at least a basic grasp of what it does (in case it's not working as I want/need it to).
Gr,
Mightor
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
| To know recursion, you must first know recursion.
| I'm afraid I might be phobophobic.
Comments
MOVED exactly and only replaces bits 9 to 17 in the "dest" with the lowest 9 bits of the "source"; this is similar to MOVS which does it with bits 0 to 8 and MOVI with bits 23 to 31. Can you guess why it's called D, S, or I respectively
It is handy (and one could even say: neccessary!) for modifying addresses in instructions.
Yeah, I can understand what you do in example ex08A, but what I don't get is what that label :arg is doing in that movd in the FunctionEngine code. The same applies that what you do in ex07C in your tutorial. I am missing something, no coin is dropping for me [noparse]:)[/noparse] Instead of nice brightly lit bulb over my head, I get a slight short, some smoke and not much else.
Gr,
Mightor
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
| To know recursion, you must first know recursion.
| I'm afraid I might be phobophobic.
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
| To know recursion, you must first know recursion.
| I'm afraid I might be phobophobic.
When you don't know the address where to read from/ write to , then you have to compute it and put it into the appropriate position INSIDE AN INSTRUCTION.
Gr,
Mightor
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
| To know recursion, you must first know recursion.
| I'm afraid I might be phobophobic.
There is no such thing as a "label name's inner value". A label is nothing but a number the compiler has learnt by heart - when it has encountered it at the start of a line - and uses every time you write down that "label".
When you use that label in the dest position of a MOV it will be interpreted as the cell number to be totally changed.
When yu use the label in the dest position of a MOVD, only the bits 9 to 17 in that cell will be changed.
So when it happens this label is a label in front of an instruction, this instruction will be changed.
In our case, the "addresses" (= cell numbers) of cells "arg0", "arg0+1",.... "arg0+7" are stored into the RDLONG instruction so that it will exactly read into that COG cells.
There is no other way to do it! (Sorry, no Perl )
Gr,
Mightor
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
| To know recursion, you must first know recursion.
| I'm afraid I might be phobophobic.
I'd really love a HOWTO/Tutorial on this self-modifying code stuff with some heavily commented code and real-life examples and pointers to when and when not to use those 'tricks'. I can't be the only one who struggles with this stuff.
Thanks!
Gr,
Mightor
PS: deSilva, not sure if I told you already, but my PWM code now works like a charm, I've been testing it with LEDs and a L293D dual H bridge. The point of this setcommand stuff is to allow me to set pins for direction from inside ASM, based on commands sent from SPIN. I'd like to have commands like setDirR and setDirL, setSpeedR and setSpeedL.
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
| To know recursion, you must first know recursion.
| I'm afraid I might be phobophobic.
Your feedback on the tutorial is especially valuable, as I have not foreseen such difficulties....
There have been good reasons I warned the "total beginner".. I think (no, I am sure!) the reader I imagined was someone having already some experience with machine coding from another micro...
Gr,
Mightor
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
| To know recursion, you must first know recursion.
| I'm afraid I might be phobophobic.
I'll jump in here to comment that the self modifying code is not just "better than just adding an offset to the start address...", because that might imply that there is some other way to do it. No, the only way to do it on the Prop, AFAIK, is via self-modifying code. So because indexing is such a basic operation, the self-modifying code should not be considered advanced, and once you get used to it, it is not that complex either. It's just different.
To clarify it further, note that the destination field of any MOV (or any instruction that writes to a destination register) can only be a direct reference to a specific register from 0 to 511. The only way to index it is to stuff a new value into the destination field of the instruction itself. It works on the Prop because code is always executing from RAM.
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Tracy Allen
www.emesystems.com
Mightor, there's one trap here: you can't change an source or destination of the code immediately after your current instruction. Not that they won't change, but because
they have already been fetched to the instruction pipeline. (2 deep, I think. Current and next instruction)
Wonder if this behavior could (has been) exploited for a auto-incrementing stack?
And no, this behaviour cannot be exploited, because you always need a second instruction, and that would not be called "auto".
Neither can I imagine a situations where you should need such a specific "post-increment".
4 is added to addr because rdlong takes a byte address as its argument and a long is 4 bytes big?
In the following piece of code:
you only add one to the src address because it refers to a register between 0-511?
I think if this is really the only way to indexed addressing in ASM in the Cog RAM then it really warrants a bit more explanation in all the documents I've come across. deSilva, I know you mentioned the fact that you can't change the next operation but you never explicitly say why that is. Perhaps you can add that to your tutorial as well. I didn't realise it was because of the way instructions are fetched. Now that I do know, it makes sense, but before it was just a rule with no (apparent) reason.
Gr,
Mightor
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
| To know recursion, you must first know recursion.
| I'm afraid I might be phobophobic.
There is a difference between the move and math instructions on one hand and the branch and hub access commands on the other. In the move and math instructions, the source and destination arguments (0-511) point to a register and it is the value from that register that is used in the operations. (Also, of course the source can be a literal value that is used directly in the operation.) There is no redirection, where the value in the register is in turn used as a pointer to somewhere else. Thus, indirect addressing and indexing require self-modifying code tricks.
On the other hand, an exception, in hub access commands like RDLONG, a reference is made to a register that contains a pointer to a location in hub ram. So the routine you started with only has to increment a variable by 4 to move through a block of addresses of longs in the hub. No fancy self-modification there. The RDLONG can also use an immediate source argument, but that is only capable of accessing 512 bytes at the low addresses in the hub.
Another sort of exception is the branch commands like jmp. An immediate source argument like {jmp #loop} points directly to the jump destination, while a register reference like {jmp hoops} is a pointer to a pointer, that is, the value contained in the register, hoops, points to the jump destination. Things get interesting with subroutinish instructions like jmpret and call,. The Prop can use self-modifying code for returns, or it can use indirect pointers through registers to keep several threads running, as seen in fullduplexserial.
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Tracy Allen
www.emesystems.com
That explanation in Sidetrack F is fine, I think I misunderstood it at first and never looked at it again. I just had a problem with ex07C. Maybe if you could mention explicitly that "MOVS :access, #X" puts the address of X into the source of the "ADDS sum, 0-0" instruction. Also maybe explain what 0-0 means. I was also a little confused about why you'd only add #1 to the address, instead of 4, like you would for the addresses in the HUB. If you could mention that a little more explicitly, that'd be great.
Now that I know what is going, it makes a lot more sense and I can see how it's a fairly simple mechanism, but it's not so obvious if you're stumbling across it for the first time. There is a lot of info coming at you when you're starting out with ASM and it can be quite overwhelming. When I look at it with the knowledge I have now I'm like "Why didn't I get it before?".
I think it would be a real boon to this guide if you could take that code of Beau's and add it to the guide with a very thorough explanation of what happens in it. It's something that people will definitely need for more complex ASM programs. ex08A is nice but it's only manipulating a variable, not an instruction. It might also be a good thing to mention that for cog-memory indexed stuff, this self-modifying code is the ONLY way to do it and that TIMTOWTDI does not apply here [noparse]:)[/noparse]
Assuming your reader can figure out a lot of the implicit (and seemingly obvious) things may lead to the reader wrongly assuming he understood what you wrote [noparse]:)[/noparse] Being explicit may be a little boring at times, especially for the author, but it can really reduce confusion.
Gr,
Mightor
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
| To know recursion, you must first know recursion.
| I'm afraid I might be phobophobic.