Passing multiple variables to asm
Ok, someone else's turn. Mike has had enough for a week or two.
Say I want to pass three variables to asm. One of those variables is a very long byte array. How is this done?
I have read the tutorials about passing one variable, but can't find anything about passing a byte array.
Also with this much data, I'm worried about getting it all mixed up.
Any help would be appreciated.
James L
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
James L
Partner/Designer
Lil Brother SMT Assembly Services
Say I want to pass three variables to asm. One of those variables is a very long byte array. How is this done?
I have read the tutorials about passing one variable, but can't find anything about passing a byte array.
Also with this much data, I'm worried about getting it all mixed up.
Any help would be appreciated.
James L
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
James L
Partner/Designer
Lil Brother SMT Assembly Services

Comments
Ziggy,
How do I know if the Variables are in successive order?
This is where I am confused.
Will they come in the order of how the cognew statement is configured?
One variable seems pretty easy, but I don't understand how a person knows how every other variable is ordered.
James L
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
James L
Partner/Designer
Lil Brother SMT Assembly Services
Longs are laid into memory in the order you define them, so if you stick with longs your PASM code can pick them up by knowing the address of the first. Let's say you have two longs and an array of longs that you want to share with PASM.
You PASM code might look something like this:
DAT org 0 asm mov tmp1, par ' start of structure mov p1Addr, tmp1 ' save param1 address add tmp1, #4 ' point to param2 address mov p2Addr, tmp1 ' save it add tmp1, #4 ' point to param3[noparse][[/noparse]0] address mov p3Addr, tmp1 ' save itTo start the Assembly section you pass pointers to the Assembly code and the param1 variable:
One the address of the first (param1) is known the others are easily calculated.
Ah, I see. What if the variables are bytes.
If I declare them all in order, they should be in memory in order as well I'm assuming. I can't remember off the top of my head if they are all bytes. I believe they are.
I don't remember reading that anywhere.
I'll give that a shot.
James L
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
James L
Partner/Designer
Lil Brother SMT Assembly Services
long param1
word param2[noparse][[/noparse]10]
byte param2[noparse][[/noparse]10]
Effectively you can access all the above using rdbyte/wrbyte by getting par and adding #1. Just remember the ordering is not as you might expect "little endian".
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Links to other interesting threads:
· Home of the MultiBladeProps: TriBladeProp, SixBladeProp, website (Multiple propeller pcbs)
· Single Board Computer:·3 Propeller ICs·and a·TriBladeProp board (ZiCog Z80 Emulator)
· Prop Tools under Development or Completed (Index)
· Emulators: Micros eg Altair, and Terminals eg VT100 (Index)
· Search the Propeller forums (via Google)
My cruising website is: ·www.bluemagic.biz·· MultiBladeProp is: www.bluemagic.biz/cluso.htm
See the attached demo: it uses two longs and an array of bytes and demonstrates the Spin/Asm interface.
PUB start | i cogwait := 60_000 + CNT repeat i from 1 to 7 COGNEW( @cogstart, @cogstart ) COGINIT( COGID, @cogstart, @cogstart ) DAT ORG 0 cogstart COGID cogstart WAITCNT cogwait, #0 { other PASM code } cogwait LONG 0The PASM code figures out a CNT value which all the cogs will wait on and then stores that value into cogwait. As long as cogwait is part of the 498 LONGs which are copied to the COG, then the value is accessible to the COG code. Note: the 60_000 values is sufficient for this example but is not optimized.
Don't forget that PAR is designed to be an address of a LONG in HUB RAM as it is only 14 bits.
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Composite NTSC sprite driver: http://forums.parallax.com/showthread.php?p=800114
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Nyamekye,
That is, if you have:
LONG myLong1
LONG myLong2
BYTE myByte1
WORD myWord1
LONG myLong3
BYTE myByte2
WORD myWord2
.... you will have in memory:
myLong1, myLong2, myLong3, myWord1, myWord2, myByte1, myByte2...
... in that order. Kind of annoying since I don't think any of this is plainly stated in any official (or even unofficial) documentation...
... so you can't reference myByte1 by offsetting the base address of myLong1 by 8, because there are other LONGs and WORDs that are magically sandwiched in there with absolutely no hint of where they are... unless you keep track of it yourself and/or are careful when you declare the variables and know where they are. Because of this memory re-ordering magic, you can't have quasi data structures in memory that hold different data types in a particular order that is continuous in memory (unless you are tricky about it). So you'll just have to take note or care of your variable declarations!
Hope this helps and keeps you away from a day's worth of headaches!
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Links to other interesting threads:
· Home of the MultiBladeProps: TriBladeProp, SixBladeProp, website (Multiple propeller pcbs)
· Single Board Computer:·3 Propeller ICs·and a·TriBladeProp board (ZiCog Z80 Emulator)
· Prop Tools under Development or Completed (Index)
· Emulators: Micros eg Altair, and Terminals eg VT100 (Index)
· Search the Propeller forums (via Google)
My cruising website is: ·www.bluemagic.biz·· MultiBladeProp is: www.bluemagic.biz/cluso.htm
*** Produces :
Otherwise pointers to the different parameter types can be used.
Note: HUB addresses can only be resolved at run time. So don't try to embed "ptr WORD @data" 'cause it won't work.
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Composite NTSC sprite driver: http://forums.parallax.com/showthread.php?p=800114
Ah, Now there is an answer that is useful.
I wanted to ask about this, but didn't know how to go about asking the question.
So I can take the known address, and make a pointer to the first location. That will suffice to what I need to do.
I need to compare 2 variables (check equality) and when they are equal, I need to perform one of two possible instructions based on the third variable.
With the pointers addressed as above, this procedure will be much easier.
Thanks Mag,
James L
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
James L
Partner/Designer
Lil Brother SMT Assembly Services
but keep in mind, what I wrote is only necessary if you have different types of variables. If you only have one type it's enough to pass the adress of the first variable. SPIN compiler is only reordering typewise. The order of the variables within the same type is not changed.
I want criticism of the code. Please tell me any problems you guys see with this.
This code is designed for a 128 byte array.
The passing of parameters and addresses is still a uneasy task for me to perform. I'm not sure if I'll ever get to understand it.
{{ Object created to compare two variables and pass back a number based on where the maching variable falls within a byte array.}} VAR byte note1, cuelist_addr1 PUB start(note,cuelist_addr) cognew(@entry, @note) '** NOTE: we send the cog the address to the hub ram variables used ** PUB LEDdrivercall(note,cuelist_addr) ' Used by spin programs to set parameters note1 := @note ' Put note in HUB ram cuelist_addr1 := @cuelist_addr ' Put the cutelist pointer in HUB ram DAT entry ' When the cog starts par is initialized with the address passed in the coginit command ' in this case it was passed @note org 0 mov ptr,par ' load parameter pointer into ptr (points to global variables) ' ptr is just a copy and keeps par unchanged for later. rdbyte note_val,ptr ' load first parameter into sch_para (cog ram) add ptr,#1 ' Increment address to next global variable, the address is in bytes so ' it needs 1 adding to get to the next byte rdbyte list,ptr ' get the first byte of the byte array (cuelist) :loop andn list,sch_para wz if_z jmp #:output_on add count,#%0_0000_0001 andn count,#%0_0111_1111 wz if_z jmp entry add ptr,#1 'move to the next byte (of the array) and test it rdbyte list,ptr jmp #:loop :output_on movd par,count entry_ret ' These variables are in cog ram! ' Uninitialized data val_test byte 0 outputval byte 0 count byte 0 list byte 0 note_val byte 0 ptr byte 0 fitEdit, had to add in some code on increment through the byte array.
2nd Edit. changed "test" to "andn". I think it will work this way.
James L
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
James L
Partner/Designer
Lil Brother SMT Assembly Services
Post Edited (James Long) : 4/21/2009 8:27:15 PM GMT
Hmmmm,
Well back to the drawing (programming) board.
I have changed the above listed code to andn for the testing of the variables
James L
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
James L
Partner/Designer
Lil Brother SMT Assembly Services
Post Edited (James Long) : 4/21/2009 8:25:44 PM GMT
start( 10, @somevar ) is used in whatever SPIN program. 10 is put on the stack, the adress of somevar is put on the adress and start is executed. Now start can access the 10 by using the parameter name note and the adress of somevar by parameter name cuelist_addr.
You then pass the adress of note to a PASM program. But the PASM program needs some time to load while the COG running your start returns and cleans up the stack. Usually an interpreter would not remove the values on the stack by overwriting with zeros, but it's very likely that you call another function which also has parameters. So, at the time you access the note in PASM it's real content is not necessarily the 10.
But I think you meant:
But please be aware, you pass the adress of note1 to the PASM. Incrementing this by 1 it'll point to cuelist_addr and not to the cuelist! By the way ... cuelist_addr at least should be word size, since HUB RAM adresses have 16 bit. Then we again have the problem of reorder.
So, you could pack both values in one 32 bit variable.
So the variables in the PASM must be:
"whatever" long 0
I get it.
James L
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
James L
Partner/Designer
Lil Brother SMT Assembly Services
Mag,
I'm going to need to read that a few times. I'm not sure that makes sense.
I'll post back, when I actually decide how to ask the question I have.
James L
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
James L
Partner/Designer
Lil Brother SMT Assembly Services
dat org mov x, val_tes ' this will move all 4 bytes into x add count, #1 ' will add ... hmmm ... i guess to list or val_test - depends on how the order is, big or little endian ' currently don't know it, would have to try it add count, # $0010 ' would add 1 to count leaving the rest untouched unless you did not reach $ff (if MSB comes first ' otherwise reordering would help -> val_test, count, outputval, list) ' but be aware, #$0020 would not work as only 9 bits are allowed as immediate shr x, #8 ' this way you can shift x to the LSBs of x and remove the rest (outputval and val_test) and x, #$ff x long 0 val_test byte 0 outputval byte 0 count byte 0 list byte 0Mag,
I definitely do not know what I'm doing.
I have this hang up with passing parameters in Spin, so passing them into PASM will definitely be a problem.
The top object collects all the data I'm using for a result. This is where I always have my pitfall.
I am trying to learn, but the hang ups still occur when I try to pass parameters.
For example, the last post you made would be a problem. I do not see how you would do action on the items, if the top object is constantly changing them. The timing is specific, so there would need to be a call (Pub method) to initiate the comparison.
With a Pub having parameters, does the initial command to start that Pub need to have the same? Ah, the basis for my hang up.
James L
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
James L
Partner/Designer
Lil Brother SMT Assembly Services
I now see your point about the pointer. Because it is a pointer (or address) I can not read what I need from it, only it's value, which I do not want. Passing the addresses from a previous Spin method is something I'll just need to work out.
James L
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
James L
Partner/Designer
Lil Brother SMT Assembly Services
I think now I understand the process.
If someone would, please critique the latest revision.
{{ Object created to compare two variables and pass back a number based on where the maching variable falls within a byte array.}} CON _clkmode = xtal1 + pll16x _xinfreq = 5_000_000 VAR long note_cuelist_addr PUB start cognew(@entry, @note_cuelist_addr) '** NOTE: we send the cog the address to the hub ram variables used ** PUB LEDdrivercall(note_addr,cuelist_addr) ' Used by spin programs to set parameters byte[noparse][[/noparse]note_cuelist_addr][noparse][[/noparse]0] := @note_addr ' Put note in HUB ram long[noparse][[/noparse]note_cuelist_addr] := @cuelist_addr ' Put the cutelist pointer in HUB ram DAT entry ' When the cog starts par is initialized with the address passed in the coginit command ' in this case it was passed @note_cuelist_addr org 0 mov ptr,par ' load parameter pointer into ptr (points to global variables) ' ptr is just a copy and keeps par unchanged for later. rdword note_val,ptr ' load first parameter into note_val (cog ram) add cue_ptr,ptr ' calculating cue_ptr location rdword list_ptr,cue_ptr ' Making list_ptr point to cuelist address rdbyte list,list_ptr ' get the first byte of the byte array (cuelist) :loop andn list,note_val wz ' Test (using and-not) a byte of cuelist with the value of note_val if_z jmp #:output_on ' if zero go to a jump add count,#%0_0000_0001 ' Increment count andn count,#%0_0111_1111 wz ' compare count with 127 if_z jmp #:output_on ' if count = 127 jump add list_ptr,#1 ' Move to the next byte (of the array cuelist) rdbyte list,list_ptr ' Read the next byte of cuelist jmp #:loop ' Jump back to the beginning of the loop :output_on wrlong par,count ' Output the count value entry_ret ' These variables are in cog ram! ' Uninitialized data ptr long 0 count long 0 cue_ptr long 0 list_ptr long 0 list long 0 note_val long 0 fitJust as a note: the other bracket is there in the code(for note_cuelist_addr), it just doesn't show on the forum.
James L
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
James L
Partner/Designer
Lil Brother SMT Assembly Services
{{ Object created to compare two variables and pass back a number based on where the maching variable falls within a byte array.}} CON _clkmode = xtal1 + pll16x _xinfreq = 5_000_000 VAR long note_cuelist_addr PUB start [color=red]' you did not initialize note_cuelist_addr, but the PASM immediately reads the content.[/color] [color=#ff0000] ' So in your case you need to call LEDdrivercall first and then you can call start. Possible, but unusual for a driver.[/color] [color=#ff0000] ' Usual is to give the start function all it needs to setup the driver. See FullDuplexSerial, TV ... whatever[/color] cognew(@entry, @note_cuelist_addr) '** NOTE: we send the cog the address to the hub ram variables used ** PUB LEDdrivercall(note_addr,cuelist_addr) ' Used by spin programs to set parameters [color=orange]byte[noparse][[/noparse]note_cuelist_addr][noparse][[/noparse]0] := @note_addr ' Put note in HUB ram[/color] [color=orange] ' 1. now you work with an adress here as well, so the type should be word [/color] [color=#ffa500] ' 2. you call the parameter note_addr, so LEDdrivercall( @a_note, @a_cuelist) would be the way you use it[/color] [color=#ffa500] ' @note_addr is wrong, because this will be a pointer to the stack adress of the parameter instead of the adress of the variable[/color] [color=orange] '-> word[noparse][[/noparse]note_cuelist_addr][noparse][[/noparse]0] := note_addr [/color][color=red]long[noparse][[/noparse]note_cuelist_addr][/color][color=red] := @cuelist_addr ' Put the cutelist pointer in HUB ram[/color] [color=red] ' this will overwrite the note part of note_cuelist_addr as well[/color] [color=red] ' -> word[noparse][[/noparse]note_cuelist_addr][noparse][[/noparse]1] := cuelist_addr [/color] DAT entry ' When the cog starts par is initialized with the address passed in the coginit command ' in this case it was passed @note_cuelist_addr org 0 mov ptr,par ' load parameter pointer into ptr (points to global variables) ' ptr is just a copy and keeps par unchanged for later. [color=orange]rdword note_val,ptr ' load first parameter into note_val (cog ram)[/color] [color=orange] ' remember, what you put into the first word of note_cuelist_addr is a pointer to the note and not the value of the note![/color] [color=orange] ' -> rdword note_ptr, ptr [/color] [color=orange] ' rdbyte note_val, note_ptr[/color] [color=orange] ' this is needed to get the value of the variable [/color] add cue_ptr,ptr ' calculating cue_ptr location rdword list_ptr,cue_ptr ' Making list_ptr point to cuelist address :loop rdbyte list,list_ptr ' get the first byte of the byte array (cuelist) [color=red][s]:loop[/s] andn list,note_val wz ' Test (using and-not) a byte of cuelist with the value of note_val[/color] [color=red] ' this is not equal to a compare instruction! It's result will be zero in many cases where the values are not equal, because[/color] [color=red] ' andn simply deletes each bit in list which is set in note_val. But if the bit already was zero you have the same result.[/color] [color=#ff0000] ' for example:[/color] [color=#ff0000] ' list note_val result[/color] [color=#ff0000] ' %000000, %000101 %000000[/color] [color=#ff0000] ' %000001, %000101 %000000[/color] [color=#ff0000] ' %000100, %000101 %000000[/color] [color=red] ' %000101, %000101 %000000[/color] [color=red] ' so, note_val %000101 will "match" with all these list values. First comes first serves. [/color] if_z jmp #:output_on ' if zero go to a jump add count,#%0_0000_0001 ' Increment count [color=orange] andn count,#%0_0111_1111 wz ' compare count with 127[/color] [color=orange] ' again, this is not a compare! you delete the bits in count which are 1 in your immediate. So, this will end the loop immediately[/color] [color=orange] ' for comparison we have the cmp instruction [/color] if_z jmp #:output_on ' if count = 127 jump add list_ptr,#1 ' Move to the next byte (of the array cuelist) [s]rdbyte list,list_ptr ' Read the next byte of cuelist[/s] jmp #:loop ' Jump back to the beginning of the loop [color=purple]:output_on wrlong par,count ' Output the count value[/color] [color=purple] ' wrong order! wrlong does work differently than all other instructions. You first give the source and then the adress![/color] [color=purple] ' -> wrlong count, par [/color]entry_ret [color=red]' and what do you do here? That's unpredictable, as it depends on the values in the following longs. It's very unlikely that[/color] [color=#ff0000] ' you find the opcode of the right cogstop instruction here. Please remember, the COG RAM is read completely even if your[/color] [color=#ff0000] ' PASM only needs 30 longs. So, what's behind the PASM code is also loaded. So, either you should have an outer loop here or[/color] [color=#ff0000] ' you should stop the COG. Funny things could happen if you don't do that. There might be the opcode jumping back in the[/color] [color=#ff0000] ' middle of your PASM .. Or there could be an opcode stopping COG 0.[/color] [color=#ff0000] ' To end an PASM program you can do a[/color] [color=#ff0000] ' COGID $0[/color] [color=#ff0000] ' COGSTOP $0[/color] [color=#ff0000] ' What you did up to now is not what you would call a driver. A driver is running in background, waiting for commands. So, you would[/color] [color=#ff0000] ' have the following code-structure[/color] [color=#ff0000] ' 1. take the parameters (note_addr and cueList_addr)[/color] [color=#ff0000] ' 2. read note_value[/color] [color=#ff0000] ' 3. if note_value = 0, go to 2.[/color] [color=#ff0000] ' 4. loop through the list until value has been found.[/color] [color=#ff0000] ' 5. store the index in HUB RAM ( don't use note_addr for that, because then the driver starts again immediately)[/color] [color=#ff0000] ' 6. set the note to 0 (SPIN then can see if the driver is done)[/color] [color=#ff0000] ' 7. jump to 2.[/color] ' These variables are in cog ram! [color=orange]' Uninitialized data[/color] [color=orange]' wrong comment, the data below is initialized with 0![/color] [color=orange]' res would be uninitialized data [/color] ptr long 0 count long 0 [color=red]cue_ptr long 0[/color] [color=red]' it's important to initialize this with 2, because of the "add cue_ptr, par". 0+par = par. The resulting pointer would then also point to[/color] [color=red]' note_addr and not to cuelist_addr. [/color]list_ptr long 0 list long 0 note_val long 0 fitHave fun digesting this ;o)
By the way ... what you do here looks like implementing the lookdownz in PASM. Do you expect it to be so much faster?
Post Edited (MagIO2) : 4/22/2009 7:17:10 AM GMT
You are right, it will take me some time to get all that through my head.
Your right of course. i used to being able to "call" a method when I want a result, and with a cog running all the time, the results can be rubbish.
You are right about the purpose. I was trying to make a lookdown event in pasm. I thought it was a good first project. Not sure if it would be much faster, but it is a good learning experiment.
You are definitely a patient person, because dealing with all of this is annoying, but I'll get it. You may have to beat it into my skull with the manual, but I will get it.
Ok, so the first words (notice words) of the variables addressed with be the address of the material (yet again I missed that). I must use that information to move the pointer to the respective address.
Could I do " andn list,note_val wz
if_nz jmp #wherever
I wanted the values to match perfectly, but may have used the wrong "z".
Ok, I read your list, and will try again to write this. I think this is a good exercise, even if you want to beat me after looking at it.
James L
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
James L
Partner/Designer
Lil Brother SMT Assembly Services
cmp list, note_val WZ
if_z jmp #value_match
Ok, lesson 1 learned ;o) :
A driver does not work like a function call in SPIN. The cognew does not wait until the PASM code is done with it's job. And it even does not wait until the PASM code has been loaded into COG RAM. That's why you should never (for newbies [noparse]:o[/noparse]) pass parameter adresses to the PASM because parameters are located on the stack and that might be used otherwise meanwhile. If you need the result in your 'calling' method, you have to synchronize. For drivers you reserve some memory in HUB RAM - for example a variable, some variables, an array .. - which is then used as communication buffer. Both, the PASM and the SPIN code need to know the structure of this buffer. For example: 1 long for passing a command, 1 long for returning a value, several longs for data.
Simple communication protocol is (as already scetched in the code comments of my previous post):
1. PASM waits until command <>0
2. So, as long as SPIN does not write a command into that part of the buffer, nothing happens
3. Depending on the value in command it can do different things ( in your case you might switch between lookdown and lookdownz )
4. When PASM is done, it copys the result to the return-part of the buffer and sets the command buffer to zero again.
This prevents PASM code running again immediately and it can be used to synchronize the SPIN code ( repeat while command )
Yet again, I haven't given up.
I have yet again totally changed the structure. I know you love that.
Try this and see if it is any better:
I edited for the return value pointer, it was wrong, maybe I fixed it this time.
VAR long note_cuelist_addr, output_num PUB start(note,cuelist_addr) word[noparse][[/noparse]note_cuelist_addr][noparse][[/noparse]0] := @note ' Pointer for note value word[noparse][[/noparse]note_cuelist_addr] := @output_num ' Pointer for value returned long[noparse][[/noparse]note_cuelist_addr] := @cuelist_addr ' Put the cutelist pointer in HUB ram cognew(@entry, @note_cuelist_addr) PUB LEDdrivercall ' Used to get the value back from the operation return output_num DAT org 0 ' When the cog starts par is initialized with the address passed in the coginit command ' in this case it was passed @note_cuelist_addr. entry mov ptr1,par ' load parameter pointer into ptr (points to global variables) ' ptr is just a copy and keeps par unchanged for later. mov ptr2,par ' We need a second copy of the pointer for cuelist :start rdword note_ptr,ptr1 ' Read the note pointer address from pointer1 add ptr1,note_ptr ' move pointer1 to the note data rdbyte note_val,ptr1 wz ' Read the note value if_z jmp #:start ' If the note value is zero start again add ptr2,#4 ' Move pointer2 to the address of cuelist rdlong list_ptr,ptr2 ' Read cuelist address add ptr2,list_ptr ' Move the pointer 2 to cuelist data :loop rdbyte list,ptr2 ' get the first byte of the byte array (cuelist) cmp list,note_val wz ' Compare a byte of cuelist with note_val if_z jmp #:output_on ' if zero go to a jump add count,#%0_0000_0001 ' Increment count cmp count,#%0_0111_1111 wz ' compare count with 127 if_z jmp #:output_on ' if count = 127 jump add ptr2,#1 ' Move pointer2 to the next byte (of the array cuelist) jmp #:loop ' Jump back to the beginning of the loop :output_on add ptr1,#2 ' Move ptr1 to the return value space rdword count_ptr,ptr1 ' Read the count pointer address add ptr1,count_ptr ' move the pointer to the counter data space wrlong count, ptr1 ' Output the count value mov note_val,#0 jmp #entry ' not sure about this jump, should it be to :start? ' These variables are in cog ram! ptr1 long 0 ptr2 long 0 count long 0 count_ptr word 0 cue_ptr long 0 list_ptr long 0 list long 0 note_val long 0 note_ptr word 0 test_num long 0 fit 496James
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
James L
Partner/Designer
Lil Brother SMT Assembly Services
Post Edited (James Long) : 4/22/2009 8:07:34 PM GMT