Adding data to an "array" in ASM


Closed Thread
Results 1 to 12 of 12
  1. #1
    Join Date
    Jun 2007
    Location
    Mansfield, UK
    Posts
    697

    Default Adding data to an "array" in ASM

    Hi, Im trying to write some of my PBP code in ASM. The bit im stuck on is setting values in an array. I know arrays dont really exist in ASM but i know its still possible to do what i want. After reading Mike's example in another thread i can see that i can access the elements of an array by using +1, +2 etc. Thats fine when its being added to a constant value. In Mike's example "Led" appears to be the address of the first element in the array.

    The array im working on at the moment uses a variable to decide which element to put data in. Heres the PBP version of the code
    Code:
    bOutData[bOutDataPos]=cControlCharOut	'Control character (a constant)
    bOutDataPos=bOutDataPos+1
    bOutData[bOutDataPos]=0			'Data length (always zero here)
    bOutDataPos=bOutDataPos+1
    bOutData[bOutDataPos]=aAddress		'Chip address (from variable aAddress)
    bOutDataPos=bOutDataPos+1
    bOutData[bOutDataPos]=cAction		'Action (another constant)
    bOutDataPos=bOutDataPos+1
    bOutData is an output buffer array. bOutDataPos gets incremented every time a byte is added to the array. The send routine elsewhere in the code then sends a byte, shifts all bytes up 1 place in the array then decrements bOutDataPos.

    So, can anyone point me in the right direction here? I just need to know how to access the array elements based on the value in bOutDataPos

  2. #2
    Join Date
    Nov 2005
    Location
    Bombay, India
    Posts
    947


    Did you find this post helpful? Yes | No

    Default

    This does the same thing in assembly
    Code:
    asm
        movlw   _bOutDataPos    ; read the index to W
        addwf   _bOutData,w     ; add base of the array and keep in W
        movwf   FSR             ; move W to INDirect File register
        movlw   _cControlCharOut
        movwf   INDF
        incf    FSR             ; move to the next location of array
        clrw
        movwf   INDF
        incf    FSR             ; move to the next location of array
        movlw   _aAddress
        movwf   INDF
        incf    FSR             ; move to the next location of array
        movlw   _cAction
        movwf   INDF
        incf    FSR             ; move to the next location of array
    endasm

  3. #3
    Join Date
    Jun 2007
    Location
    Mansfield, UK
    Posts
    697


    Did you find this post helpful? Yes | No

    Default

    Thanks. That looks like exactly what i want. I wasnt sure if it was even possible with PICs.

    Ive looked FSR and INDF up in the datasheet and i found something else interesting too.
    POSTINC: accesses the FSR value, then automatically increments it by 1 afterwards

  4. #4
    Join Date
    Jul 2003
    Posts
    2,405


    Did you find this post helpful? Yes | No

    Default

    The first part of this probably isn't working like you might expect.
    Code:
      movlw   _bOutDataPos    ; gets the "address" of bOutDataPos into W
      addwf   _bOutData,w     ; adds the address + the "value" in bOutData
      movwf   FSR             ; loads FSR with the wrong address
    You want to add the base address of the array, which will never change, to the
    offset value in bOutDataPos to get the address for each array element;
    Code:
      movf   _bOutDataPos,W   ; get the value of your index pointer in bOutDataPos
      addlw  _bOutData        ; add the index to the base address of your array
      movwf  FSR              ; load FSR with base address + offset
    This will probably make it easier to follow;
    Code:
    Array       VAR BYTE[8]
    Index       VAR BYTE
    Address     VAR BYTE
    
    Action      CON 10
    ControlChar CON 20
    
    CLEAR
    
    Address = 15  ' address
    Index = 0     ' starting Array Index position
    
    Main:
     Array[Index]=ControlChar
     Index=Index+1
     Array[Index]=0
     Index=Index+1
     Array[Index]=Address
     Index=Index+1
     Array[Index]=Action
     Index=Index+1
     GOTO Main
    The code after Main would be something like this, which maintains your Index pointer.
    Code:
    asm
      movf   _Index, W     ;get "offset" value from Index pointer
      addlw  _Array        ;add it to Array[0] base address (result in W)           
      movwf  FSR           ;load pointer with base + offset  
      movlw  _ControlChar  ;load W with constant value in ControlChar
      movwf  INDF          ;move it to Array[Index]
      incf   _Index, F     ;inc Index pointer  
      movf   _Index, W     ;load new Index pointer value  
      addlw  _Array        ;add it to Array[0] base address            
      movwf  FSR           ;load pointer with base + offset  
      clrf   INDF          ;Clear Array[Index]  
      incf   _Index, F     ;inc Index pointer  
      movf   _Index, W     ;load new Index pointer value
      addlw  _Array        ;add it to Array[0] base address           
      movwf  FSR           ;load pointer with base + offset  
      movf   _Address, W   ;get Address byte value  
      movwf  INDF          ;move it to Array[Index]  
      incf   _Index, F     ;inc Index pointer  
      movf   _Index, W     ;load new Index pointer value  
      addlw  _Array        ;add it to Array[0] base address          
      movwf  FSR           ;load pointer with base + offset  
      movlw  _Action       ;load W with Constant value in Action
      movwf  INDF          ;move it to Array[Index]  
      incf   _Index, F     ;inc Index pointer
    endasm
    It could be made a bit smaller, and you could use incf FSR to increment the
    pointer each time, but you could lose track of which array element you last
    wrote to pretty quick.
    Regards,

    -Bruce
    tech at rentron.com
    http://www.rentron.com

  5. #5
    Join Date
    Jun 2007
    Location
    Mansfield, UK
    Posts
    697


    Did you find this post helpful? Yes | No

    Default

    Ahh, I didnt notice that it was the wrong way round. It is right in my code though because i wrote it out myself instead of copy/paste (i remember better that way).

    Heres how my code looks now. I think its all right
    Code:
    	; Get the start address for the array
    	MOVLW	_bOutData				; Set WREG to the start of the bOutData array
    	ADDWF	_bOutDataPos,0			; Add bOutDataPos to the address and store back in WREG
    	MOVWF	FSR0					; Copy WREG to the indirect file register
    	
    	; Control character
    	MOVLW	_cControlCharOut		; Copy the output control character to WREG
    	MOVWF	POSTINC0				; Copy WREG to bOutData[bOutDataPos] (specified by indirect file register) and increment FSR0
    	INCF	_bOutDataPos			; Increment the array position
    	
    	; Data length
    	MOVLW	0						; Set WREG to 0
    	MOVWF	POSTINC0				; Copy WREG to bOutData[bOutDataPos]
    	INCF	_bOutDataPos			; Increment the array position
    	
    	; Chip address
    	MOVFF	_aAddress,POSTINC0		; Copy aAddress to bOutData[bOutDataPos]
    	INCF	_bOutDataPos			; Increment the array position
    	
    	; Action
    	MOVLW	_cActionPing			; Copy the ping action character to WREG
    	MOVWF	POSTINC0				; Copy WREG to bOutData[bOutDataPos]
    	INCF	_bOutDataPos			; Increment the array position

  6. #6
    Join Date
    Jul 2003
    Posts
    2,405


    Did you find this post helpful? Yes | No

    Default

    Looks like you have it under control..;o}

    I don't recommend using this particular syntax though ADDWF _bOutDataPos,0. I much
    prefer being explicit with ADDWF _bOutDataPos,W. I can never remember if 0 or 1 is
    specifying W or F, so it's a lot easier for me, at a later time, to review code with explicit
    arguments.
    Regards,

    -Bruce
    tech at rentron.com
    http://www.rentron.com

  7. #7
    Join Date
    Jun 2007
    Location
    Mansfield, UK
    Posts
    697


    Did you find this post helpful? Yes | No

    Default

    Thats a very good point. Originally i saw it written how you said but the datasheet said it had to be 1 or 0. If typing W works too then i will do it that way. Thanks

  8. #8
    Join Date
    Jan 2009
    Location
    Miami, Florida USA
    Posts
    644


    Did you find this post helpful? Yes | No

    Default

    Hi all,

    Let me ask you a very stupid question here, but like they say if you don't ask you don't learn. This piece of code is very simple to do using PBP, so what is the purpose of complicating your life using ASM for this program? Using ASM saves programming space, but other than that why would you use it for this simple program?

    Thank you for your answers,

    Robert

  9. #9
    Join Date
    Jun 2007
    Location
    Mansfield, UK
    Posts
    697


    Did you find this post helpful? Yes | No

    Default

    Theres 2 reasons.

    1) For a while now ive been wanting to learn ASM. By learning ASM a lot of things in other languages like PBP and even C are starting to make sense. I think its a very usefull thing to learn. It helps to understand how things are actually working inside the chip

    2) Probably the most important one. This section of code is only part of a much bigger program. Its actually the same one from my other thread which is titled "PBP Using too many instructions". ASM uses a lot less instructions so i can finally add in the extra features that i wanted to do in PBP but couldnt because the code was running too slow.

  10. #10
    Join Date
    Jun 2007
    Location
    Mansfield, UK
    Posts
    697


    Did you find this post helpful? Yes | No

    Default

    Im having a bit of trouble getting this code working.

    Heres some test code i wrote
    Code:
    	MOVLW	38
    	MOVWF	FSR0
    	
    	MOVLW	57
    	MOVWF	38
    	MOVFF	INDF0,TXREG
    This code should set W to 38 then move that value to FSR0.

    It then sets W to 57 (my test value) and moves W to memory location 38. Then it sends INDF0 over serial to the PC. I would expect INDF0 to reference memory location 38 and send 57 but it doesnt. I keep getting random values (a different one each time i reset the PIC asif its an uninitialized memory location). Its not a serial problem. MOVWF TXREG sends the correct value.

    I know im writing data to memory location 38 and if i read FSR0 back it also says 38. Did i miss something obvious? It seems like both are accessing memory location 38 but in 2 different blocks of memory (im not sure if thats possible)

  11. #11
    Join Date
    Jul 2003
    Location
    Colorado Springs
    Posts
    4,959


    Did you find this post helpful? Yes | No

    Default

    FSR0 is a constant that equates to 0.
    It's for use with the LFSR opcode, LFSR FSR0, 38

    The address for the FSR0 is 2 bytes, FSR0L and FSR0H.
    So with your example, it could be one of these ...
    Code:
    	LFSR  FSR0, 38
    	
    	MOVLW	57
    	MOVWF	38
    	MOVFF	INDF0,TXREG
    ... OR ...
    Code:
    	MOVLW	38
    	MOVWF	FSR0L
    	CLRF	FSR0H
    	
    	MOVLW	57
    	MOVWF	38
    	MOVFF	INDF0,TXREG
    hth,
    DT

  12. #12
    Join Date
    Jun 2007
    Location
    Mansfield, UK
    Posts
    697


    Did you find this post helpful? Yes | No

    Default

    Thanks. Thats working perfectly now

Similar Threads

  1. Using Nokia LCD
    By BobP in forum mel PIC BASIC Pro
    Replies: 300
    Last Post: - 3rd May 2018, 04:47
  2. Read/Write Problem
    By Tobias in forum mel PIC BASIC Pro
    Replies: 1
    Last Post: - 10th February 2010, 01:51
  3. Big characters on HD44780 4x20
    By erpalma in forum mel PIC BASIC Pro
    Replies: 23
    Last Post: - 7th January 2007, 02:21
  4. LCD + bar graph
    By DynamoBen in forum mel PIC BASIC Pro
    Replies: 13
    Last Post: - 5th October 2005, 14:50
  5. Sinus calculating !
    By Don Mario in forum mel PIC BASIC Pro
    Replies: 29
    Last Post: - 28th November 2004, 23:56

Members who have read this thread : 1

You do not have permission to view the list of names.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts