Shop OBEX P1 Docs P2 Docs Learn Events
[PASM] Get the address — Parallax Forums

[PASM] Get the address

MazziniMazzini Posts: 58
edited 2011-09-06 15:13 in Propeller 1
Good Day,

How I get the memory's address without calculate it by hand ?
The code print some string on Lcd and convert the number 389 in ascii
CON 
  _clkmode = xtal1 + pll16x 
  _xinfreq = 5_000_000 
 

PUB Main 
  
cognew(@entry, @msg)
repeat ' the spin stops here
dat       ' separate dat section to show msg is independent
long
msg                     byte     "Hello ",0  'Test First message       
msg2                    byte     "World !",0,0 'Test second message
buffer                  res      1
 
dat org 0
                                                                       
entry                mov dira,port           'Config Port I/O

'INIT THE LCD
                     mov _tmpDelay,#500
                     Call #Delayms           'Wait for powerUp lcd  about 0.5s
                     Call #lcd_init          'Init Lcd
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
'READ STRING MSG AND MSG2(#7) FROM MEMORY AND PRINT IT
                     mov _ndx,par            'read the address of msg to ndx
                     Call #LcdChar

                     mov _ndx,par            'read the address of msg to ndx
                     add _ndx,#7             'I WOULD LIKE GET THE ADDRESS WITHOUT CALCULATE IT BY HAND ( @msg2 ? )     
                     Call #LcdChar
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
'CONVERT THE NUMBER  #389 TO ASCII ( THREE DIGIT ) AND PRINT IT,
'WRITE IT TO MEMORY, READ IT FROM MEMORY AND PRINT IT AGAIN
                     andn outa,rs            'Get ready for next string   
                     mov cmd,#$C0            'second line
                     call #LcdDat            'Send command
                     or outa,rs              '


                     mov _ndx,par            'read the address
                     add _ndx,#17            'My buffer start here ( 17th byte ) I WOULD LIKE GET THE ADDRESS WITHOUT CALCULATE IT BY HAND
                     Call #decToAscii        'Convert #389 to ascii. This is a test ( there is no reverse string)
      
                               
                     mov _ndx,par            'read buffer
                     add _ndx,#17            '
                     Call #LcdChar           'Print memory contents

:done                jmp #:done              'nothing left to do, just jmp #done forever


'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
LcdChar
                      
                     or outa,RS                     
                    
        :loop        rdbyte cmd,_ndx         'read the character from ndx
                     tjz cmd,#:done          'if the character is 0, exit the loop 

                     Call #LcdDat            'character is not 0, print it
                     mov _tmpDelay,#511
                     Call #Delayms            
                     add _ndx, #1            'get the next character address
                     jmp #:loop              'repeat the loop
        :done
LcdChar_ret          ret
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
                          
decToAscii  ' TEST
                     mov number,#389          'this is what I want view on Lcd
:loop                     
                     Call #Modulus            'digit = number % 10 

                     mov __x,number           'x = number
                     mov __y,#10              'y = 10
                     Call #Divide             'number = number / 10   
                     andn __x,clrW            'Clear remainder ( High word)
                     mov number,__x           'copy to var number the new value ( number /=10)

                     mov char,digit           'copy digit to char
                     add char,#48             'Add '0' to char. The ascii-characters for numbers start at 48 (for 0) up to 57(for 9)
                     mov cmd,char             'ready to send to Lcd
                     Call #LcdDat             'Send char to Lcd
                        
                     wrbyte char,_ndx
                     add _ndx,#1

                     tjnz number,#:loop       'if number = 0 Exit
                     mov char,#0
                     wrbyte char,_ndx         'I WOULD LIKE WRITE AN IMMEDIATE VALUE ( ZERO )
decToAscii_ret       ret
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''      



'Can I write #0 without var char ?
mov char,#0
wrbyte char,_ndx         

How I can return without jump to :done ?
tjz cmd,#:done   

:done
ret
Thanks in advance

Comments

  • Phil Pilgrim (PhiPi)Phil Pilgrim (PhiPi) Posts: 23,514
    edited 2011-09-04 10:53
    Try this:
    [s]        mov   _ndx,#msg2
            sub   _ndx,#msg
            add   _ndx,par[/s]
    

    -Phil
  • MazziniMazzini Posts: 58
    edited 2011-09-04 11:33
    pasm wants msg2 as long type
  • Phil Pilgrim (PhiPi)Phil Pilgrim (PhiPi) Posts: 23,514
    edited 2011-09-04 11:46
    Oops! What was I thinking? 'Sorry for the misdirection. Try this instead:
                            mov     _ndx,par
                            add     _ndx,offset
                            ...
    offset                  long    @msg2 - @msg
    

    -Phil
  • jazzedjazzed Posts: 11,803
    edited 2011-09-04 12:33
    Wouldn't it be better to just use a table (array of message pointers) in a mailbox?
    That way all you have to do is reference the message by number.
  • MazziniMazzini Posts: 58
    edited 2011-09-04 14:06
    Oops! What was I thinking? 'Sorry for the misdirection. Try this instead:
                            mov     _ndx,par
                            add     _ndx,offset
                            ...
    offset                  long    @msg2 - @msg
    

    -Phil

    It works , Thanks :)

    @Jazzed : yes it would be better, but I dont know what mailbox means, where I can read about it ?
    is there an example ?sry I'm learning step by step :)
    Thanks
  • jazzedjazzed Posts: 11,803
    edited 2011-09-04 15:10
    Mazzini wrote: »
    @Jazzed : yes it would be better, but I dont know what mailbox means, where I can read about it ?
    There are examples in many PASM programs. I don't think anyone has come up with a good description though.

    Basically you can pass a PAR value to PASM like cognew(@pasm, @value).

    The @value is the address of the variable value.
    You can use value as an "anchor" for a set of variables - for example:
    dat
      value  long 0
      value2 long 0
      value3 long 0
    
    That is a set of variables which can be used as a mailbox.

    Now, consider this:
    dat
      value  long @msg
      value2 long @msg2
      value3 long @msg3
    
      msg  byte "Hello",0
      msg2 byte "Hello !",0
      msg3 byte "Goodbye.",0
    

    You can read the contents of value and friends in PASM almost the same way you read "msg" before. The problem is in getting the initial address of each message. Here's an example to study.
    CON
      _clkmode = xtal1 + pll16x
      _xinfreq = 5_000_000
    
      OBJOFFSET = $10
    
    PUB start
      cognew(@entry, @value)
      repeat ' the spin stops here
    
    dat
      value  long   @msg+OBJOFFSET  ' use address of message + object offset
      value2 long   @msg2+OBJOFFSET
      value3 long   @msg3+OBJOFFSET
    
      msg   byte    "Hello",0
      msg2  byte    "Hello !",0
      msg3  byte    "Goodbye.",0
    
    dat org 0
    entry
    
    again
                    mov     msgndx, par             ' read the address of value to msgbase
                    mov     msgcnt, #3
    :loop
                    call    #printMsg
                    add     msgndx, #4              ' get the next message pointer
                    djnz    msgcnt, #:loop
                    jmp     #again                  ' just jmp #again forever
    
    printMsg
                    rdlong  ndx,msgndx              ' read the address of msg to ndx
    :loop
                    rdbyte  text,ndx                ' read the character from ndx
                    tjz     text, #printMsg_ret     ' if the character is 0, exit the loop (# optional)
    
                    'Call    #LcdDat                 ' character is not 0, print it
                    'Call    #wait
                    add     ndx, #1                 ' get the next character address
                    jmp     #:loop                  ' repeat the loop
    printMsg_ret    ret
    
    msgndx long 0   ' ndx address messages
    msgcnt long 0   ' message counter
    ndx    long 0   ' use ndx as an index into the msg array
    text   long 0   ' text to send
    
  • kuronekokuroneko Posts: 3,623
    edited 2011-09-04 16:26
    Mazzini wrote: »
    'Can I write #0 without var char ?
    ShadowB]par[/B is usually unused (therefore 0). So this will work.
    wr[byte|word|long] par,_ndx
    
    Mazzini wrote: »
    How I can return without jump to :done ?
    Provided that tjz is inside the subroutine just remove the #.
    tjz cmd, :done   
    
    :done   ret
    
    Once the subroutine is called the lower 9 bit of :done contain the return address (as part of a jump instruction). By using a register as the jump target for tjz it will effectively duplicate the ret behaviour (without actually going through the ret).

    If you are - what looks like - concerned about speed/wasted cycles then you should use something like this:
    :loop           rdbyte  cmd, _ndx [COLOR="orange"]wz[/COLOR]        'read the character from ndx
            [COLOR="orange"]if_z[/COLOR]    jmp     :done               'if the character is 0, exit the loop 
    
    So in case the jump is taken you spend 4 cycles, in case it's not you only have to worry about a nop (rather than the full jump-not-taken penalty).
  • ChrisGaddChrisGadd Posts: 310
    edited 2011-09-05 08:41
    Neat, I've just been following the object address plus symbol @@ example in the prop manual:
    CON
    _clkmode = xtal1 + pll16x
    _xinfreq = 5_000_000
    
    PUB Main
      cognew(@String_Lookup, @@0)                ' Launch with address stored in par
    
    DAT     org
    
    Message_1         byte    "Message 1",00
    Message_2         byte    "Message 2",00
    Message_3         byte    "Message 3",00
    Message_4         byte    "Message 4",00
    
    DAT                   org
    
    String_Lookup
              or      dira,Tx_Mask
              or      outa,Tx_Mask
    Message_Init
              mov     Temp,#@Message_1           ' #@Message_1 is the address of Message_1
              call    #Send_Message              '  relative to the address of String_Lookup
              mov     UART_Byte,#$0D
              call    #UART_Transmit
              mov     Temp,#@Message_2
              call    #Send_Message
              mov     UART_Byte,#$0D
              call    #UART_Transmit
              jmp     #Message_Init
    '-----------------------------------------------------------------------                           
                                                                                                                                                      
    Send_Message
              add     Temp,par                   ' Add the relative address of the message to the address 
    :Get_Byte                                    '  of String_Lookup to find the absolute address
              rdbyte  UART_Byte,Temp wz
      if_z   jmp      Send_Message_ret
              call    #UART_Transmit
              add     Temp,#1
              jmp     #:Get_Byte
    Send_Message_ret  ret
    
    '-----------------------------------------------------------------------                           
                                                                                                                                                      
    UART_Transmit
              or      UART_Byte,#$100            ' Add a stop bit
              shl     UART_Byte,#1               ' Add a start bit
              mov     Bit_Counter,#10
              mov     cnt,Baud
              add     cnt,#16
              add     cnt,cnt
    :Loop
              shr     UART_Byte,#1          wc   ' Shift lsb out of Data into C
              muxc    outa,Tx_Mask               ' Set / clear the Tx_pin depending on C
              waitcnt cnt,Baud
              djnz    Bit_Counter,#:Loop         ' Loop until ten bits sent
    UART_Transmit_ret ret
    
    '---------------------------------------------------------------------                           
                                                                                                                                                      
    Tx_Mask           long    1<<30
    Baud              long    694                   ' 694 * 0.0125µs = 115,274 bps
    Temp              res     1
    Bit_Counter       res     1
    UART_Byte         res     1
    
  • MazziniMazzini Posts: 58
    edited 2011-09-06 15:13
    Hello again and thank for your time

    sry for later answer

    @Jazzed :
    again
                    mov     msgndx, par             ' read the address of value to msgbase
                    mov     msgcnt, #3
    :loop
                    call    #printMsg
                    add     msgndx, #4             <<<<<< ' get the next message pointer
                    djnz    msgcnt, #:loop
                    jmp     #again                  ' just jmp #again forever
    
    
    
    I am constrained to know the message 's address but it works thanks

    @kuroneko: thanks for your tips
    :loop           rdbyte  cmd, _ndx wz        'read the character from ndx
            if_z    jmp     :done               'if the character is 0, exit the loop
    

    @ChrisGadd : because that @@ is part of Chap 2 Spin Section I haven't read it ( my error )
    I will try it thanks


    :smile:


    Edit :
    It works thanks !
Sign In or Register to comment.