Shop OBEX P1 Docs P2 Docs Learn Events
problem understanding the results with the quickstart board — Parallax Forums

problem understanding the results with the quickstart board

CncjerryCncjerry Posts: 64
edited 2012-06-12 15:59 in Propeller 1
I was playing around with this code to illustrate a problem in another thread related to not being able to have the same variable name in two assembler routines in one file.

Just for the heck of it, I loaded it and this illustrates a consistency problem I've been having.

1) As below, I would expect the first asm routine to load with cognew, set the quickstart low order leds on, then loop. The expected output would be 4 bright lights.

2) Then the second routine is loaded with cognew and the output should be two of the higher order leds on at a lower brightness and pulsing that I read with a scope.

What happens though, is the first loads, the second loads, I get the low order lights on as in (1) and the alternate lights on in (2) then after about a second, the high order (alternating) lights turn off.

If I swap the cognew statements I get different results.

Can someone load this on a quickstart and see if you get the same results?


Thanks
VAR
  long X
  long Y
  long stack1
  long stack2
  
Pub Start
      cognew(@start1, @stack1)
      cognew(@start2, @stack2) 
      repeat
        x:=Y
      
DAT
        org 0
start1
        or    dira, allleds
        or   outa, leds
loop1        
        jmp   loop1
leds    long  $0F<<16
allleds long  $FF<<16

        org 0
start2
        or    dira, allleds2
loop2
       or   outa, leds2
        nop
        nop
        nop
        nop
        andn   outa,leds2
        nop
        nop
        nop
        nop        
        jmp   loop2
leds2   long  $50<<16
allleds2 long  $FF<<16       

Comments

  • Heater.Heater. Posts: 21,230
    edited 2012-06-11 14:28
    At least you should remember to put a # in front of the target label in your jump instructions.
  • CncjerryCncjerry Posts: 64
    edited 2012-06-11 14:50
    some reason my post didn't take.

    my previous response was "duh".

    I don't understand why you need to prefix short jumps, setting aside the fact that this is a flat memory model. This will fix all kinds of problems I have been having. I've been having a hell of a time figuring out the assembler on this chip. I think it is because I have been programming assembler since 1976 on a collection of 360, 370,System/3, AS/400, System/34, PC, 808x and most versions, PIC, Arduino, Analog Devices DSP, Motorol DSP, dos masm and I am sure a bunch more. I'm sure there a people around here that can add to this list.

    Thanks again.
  • pedwardpedward Posts: 1,642
    edited 2012-06-11 14:52
    The # operator is a dereferencing operator. It says, load the COG address of #foo, not load the contents of foo.
  • Heater.Heater. Posts: 21,230
    edited 2012-06-11 15:02
    There are no short or long jumps. All instuctions have 9 bit src and dst fields. Enough to get you anywhere in cog. So a jmp can either jump to the address held in it 9 bit dst field or it can jump to the address contained in the long that the 9 bit address field ponts to. For the former case use a #.
  • msrobotsmsrobots Posts: 3,709
    edited 2012-06-11 15:25
    Cncjerry,

    pasm and spin are quite unusual in some aspects. indirect jmp is one of those things. but not having any stack pasm is different from most assembler-languages. Usually you want a # in front of the jmp target else you will jmp to the content of that adress.

    CHIPS way of doing things different is confusing sometimes (lookup min and max for example). On the other hand this is what makes the propeller so great - it is different from other microcontrollers because he is thinking outside of usual used ways.

    NEVER assume you understand assembler.there area lot of gotchas hidden there behind well known memnonics. If in doubt ALLWAYS read the manual again. TWICE. Then try to grook it. In most cases you will understand the reasoning behind the decision and will like it.

    On the third hand - I still can not wrap my head around MIN and MAX as well as ">=","<=" versus "=<","=>" in Spin they get me EVERY time, again and again.

    But think about the beauty of "if_z" and friends. conditional excecuting without speed-penalty. CHIP is brilliant.

    Enjoy!

    Mike
  • CncjerryCncjerry Posts: 64
    edited 2012-06-11 22:19
    Understand this all better now combined with the other thread which seems to clear-up a basic misunderstanding I had.

    I do wonder why they used the # instead of the more common convention that might have been used with @. So I would jump to a label named "function" (without a # or @) or load the address of that label by using @function into for instance the program counter. The assembler uses the @ correctly on cognew, cognit where you are doing cognew(@function, @stack) or address of function and address of stack.

    I am trying to think of a case where you would jump to function without specifying #?
  • msrobotsmsrobots Posts: 3,709
    edited 2012-06-11 23:42
    Cncjerry,

    well it is a indirect jmp. For example look at some of the serial objects. They usually use 2 cog-mem-locations as 'state' pointer for rx-thread and tx-thread. each thread is a state-machine saving its 'next-to-execute' adress in its own pointer and jmp to the other ones. This enables some form of multithreading in one cog.

    Another example is the jmpret instruction (see Manual) wich allows you to 'call' some subroutine and return to the next instruction, WITHOUT having a stack.

    Enjoy!

    Mike
  • pedwardpedward Posts: 1,642
    edited 2012-06-12 00:31
    Jerry, think of the assembler different from the SPIN compiler. In SPIN the @ and @@ operators are used. @ is effectively the same thing as # in PASM, which is similar to & in C.
    PASM only has a 512 location memory space, that's why the SRC and DST fields are 9 bits. You can only read and write hub memory, not execute.
  • CncjerryCncjerry Posts: 64
    edited 2012-06-12 09:44
    I am using the call instruction in some test code and noticed you need the function_ret label so I assume the assembler is just poking in the return address on a jump instruction, that is why the stack isn't needed. So I get it now, no debate here and I appreciate all the pointers. This forum is much, much more productive than others. By now I would have had about 20 people pointing me at the book.

    btw: can you return from more than one place in a program? I assume not considering the need for the function_ret label.

    Here's some trivia. Thinking of jump and return, I don't know how many were arround in the 370 days, but there was a competition to write the simplest program.

    It worked out to this:
            org     0
            br     14
    

    In 370 assembler, register 14 had the return address of the caller so you were just branching on register 14 to return. The caller in this state was the OS (termed supervisor back then when it was executing) It worked but time went by and someone pointed out the program had a bug. This was an example of a program that had the same number of bugs as lines of compiled instructions since the org was an assembler directive. The return code was supposed to be in register 15 and if not zero, it was conventionally an error. So it was changed to:
            org     0
            subl r15,r15    ' might have been sub (subtract) instead of subl, subtract logical, to clear r15
            br     14
    
  • kuronekokuroneko Posts: 3,623
    edited 2012-06-12 15:49
    Cncjerry wrote: »
    btw: can you return from more than one place in a program? I assume not considering the need for the function_ret label.
    Sure you can. The obvious way would be to jump to the end of the function:
    subr            ...
                    cmp     a, b wz
            if_e    jmp     #subr_ret
                    ...
                    mov     c, a
    subr_ret        ret
    
    Which works (first jump to end of subroutine followed by jump back to caller). A bit more efficient (time-wise) would be this version
    subr            ...
                    cmp     a, b wz
            if_e    jmp     subr_ret
                    ...
                    mov     c, a
    subr_ret        ret
    
    The ret instruction is just a jmp #call_location_plus_one which has its target adjusted the moment you call the subroutine. So we might as well use this value by doing an indirect jump. OTOH you can jump to anywhere you want (error handler etc).

    Disclaimer: This is a before-morning-coffee answer. If you meant something else please elaborate.
  • AribaAriba Posts: 2,693
    edited 2012-06-12 15:59
    Cncjerry wrote: »
    ...btw: can you return from more than one place in a program? I assume not considering the need for the function_ret label....

    Yes, just do a jump to function_ret. You can dor it with JMP #function_ret, then you have two jumps executed, or more tricky without the # then the CPU does only one jump but picks the address from the ret instruction.

    Andy

    Edit: As usual, kuroneko was faster ...
Sign In or Register to comment.