Shop OBEX P1 Docs P2 Docs Learn Events
indirect addressing in assembly? — Parallax Forums

indirect addressing in assembly?

HarleyHarley Posts: 997
edited 2009-09-16 19:16 in Propeller 1
I'm trying to do something new (to me) in assembly. I have a table of bytes I wish to get the address of to begin to pick up values for a D/A.

Looking at what's happening in PASD, at ':dloop' I get an address of 68BE4AFD, yet that location is 01B!

I'm obviously something is not proper here. Anyone got a clue?

DAT           org       0      ' 
entry  ' --- Debugger Kernel add this at 'entry'  --- MUST BE LAST COG IF USE 'PASD'
  long $34FC1202,$6CE81201,$83C120B,$8BC0E0A,$E87C0E03,$8BC0E0A
  long $EC7C0E05,$A0BC1207,$5C7C0003,$5C7C0003,$7FFC,$7FF8
'  --------------------------------------------------------------
D2A           or        DIRA,DAmsk              ' make A16.A19 outputs
              or        OUTA,DAmsk              '  and at HI level
              mov       indx,#15                ' set for 16 samples
:dloop        mov       tmp,@D_A
              add       tmp,#15
              sub       tmp,indx
              mov       tmp,@tmp
              mov       wait,D2Ams
              add       wait,cnt
              waitcnt   wait,D2Ams              ' wait for next sample time
              xor       tmp,OUTA                ' alter just D2A pins
              xor       OUTA,tmp
              djnz      indx,#:dloop

              jmp       #D2A                    ' run forever             
' Initialized data 
D_A           BYTE      $02,$06,$0E,$0F,$0A,$03,$00,$03,$02,$02,$02,$02,$02,$02,$02,$02
D2Ams         LONG      5_000_000               ' for 16 samples at 60 bpm
DAmsk         LONG      $000F_0000              ' uses pins A16..A19 for D/A
' Uninitialized data
indx          RES       1
wait          RES       1
tmp           RES       1


▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Harley Shanko

Comments

  • Ken PetersonKen Peterson Posts: 806
    edited 2009-09-15 18:55
    Harley,

    In order to do indexed addressing in PASM you have to use self-modifying code. PASM has statements especially for this that make it easy.

    For a good tutorial on PASM, check out deSilva's excellent Machine Language Tutorial

    http://forums.parallax.com/showthread.php?p=668559

    Ken

    P.S. Chapter 5 in the tutorial is where you'll find info you need.

    Post Edited (Ken Peterson) : 9/15/2009 7:01:47 PM GMT
  • KyeKye Posts: 2,200
    edited 2009-09-15 19:19
    Basically you need to use the movd and movs commands to change the source and destination address of one instruction to something else. Be careful to put at least one instruction in between the modifying code and the code that was modified also.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Nyamekye,
  • AlsowolfmanAlsowolfman Posts: 65
    edited 2009-09-15 20:59
    What everyone has said above is correct, but the effect that you are describing is that the @D_A in [noparse]:D[/noparse]loop is giving you the the hub address of D_A, not the copy in the cog memory. to access the cog memory you have to use #D_A, that should get you 01B. This will not fix everything, but it explains what your address issues.
  • HarleyHarley Posts: 997
    edited 2009-09-16 00:28
    Thanks all, I got a bit of it going pretty well, except the 'modify instruction' portion. The 'movs' seems to get the proper value into 'tmp2 now', but deSilva's description was too lightly brushed over for me to catch what one actually HAS TO DO. Like does one affect the i, d, s field for every instruction? If so how does one know what the 'i-field should be? The ' mov tmp,#tmp2' line is mostly wrong as some strange value turned up in 'tmp' for the 'shl' line.

    Is there a a short, concise description of what one has to do to accomplish what's needed for self modifying code. To me deSilva's document is great, but think he didn't complete what he started on pg 21. Certainly didn't describe sufficiently for someone who'd never worked with such code.



    D2A           or        DIRA,DAmsk              ' make A16.A19 outputs
                  or        OUTA,DAmsk              '  and at HI level
                  mov       indx,#15                ' set for 16 samples
    :dloop        mov       tmp,#D_A                ' get address of D_A array
                  add       tmp,#15                 '  add offset to array end
                  sub       tmp,indx                '  subtract  indx value
                  movs      tmp2,tmp                ' get value at pointer tmp
                  nop
                  mov       tmp,#tmp2
                  nop
                  shl       tmp,#16                  ' position to D/A pins
                  mov       wait,D2Ams              ' add delay count (2 ms)
                  add       wait,cnt
                  waitcnt   wait,D2Ams              ' wait for next sample time
                  xor       tmp,OUTA                ' alter just D2A pins
                  xor       OUTA,tmp                ' plus add system counter value
                  djnz      indx,#:dloop
    
                  jmp       #D2A                    ' run forever             
    ' Initialized data 
    D_A           BYTE      $02,$06,$0E,$0F,$0A,$03,$00,$03,$02,$02,$02,$02,$02,$02,$02,$02
    D2Ams         LONG      5_000_000               ' for 16 samples at 60 bpm
    DAmsk         LONG      $000F_0000              ' uses pins A16..A19 for D/A
    ' Uninitialized data
    indx          RES       1
    wait          RES       1
    tmp           RES       1
    tmp2         RES       1
    
    

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Harley Shanko
  • Mike GreenMike Green Posts: 23,101
    edited 2009-09-16 00:48
    You actually modify part of an instruction in your code. In your case, you want to access a byte array which is a little bit complicated since the cog memory is all longs. The easy way to do this is to change D_A to an array of longs, then do:
    :dloop  mov   tmp,#D_A
            add   tmp,#15
            sub   tmp,indx
            movs  :moveIt,tmp
            nop
    :moveIt mov   tmp,0-0
            shl   tmp,#16
    


    The "0-0" is just a placeholder. By convention, that implies that the instruction field will be modified somewhere else in the code.
  • Beau SchwabeBeau Schwabe Posts: 6,568
    edited 2009-09-16 01:09
    Harley,

    Perhaps this might make some since... another problem outside of needing to create self modifying code, your 'D_A' table is setup in BYTES

    The line that reads...
    :dloop        mov       tmp, D_A
    
    


    ...is justified in LONGS, and thus reads an entire long.



    CON
      _CLKMODE = XTAL1 + PLL16X
      _XINFREQ = 5_000_000
    
    PUB start
        cognew(@D2A, 0)
    
    DAT
                  org       0      ' 
    
    D2A           or        DIRA,LEDs
    
    ''------------------------------------------------------------------------------------------------------------------------------------------
                  ''The next 4-lines of code self modify ':dloop's Source register
    ''------------------------------------------------------------------------------------------------------------------------------------------
                  movs      tmp, :dloop    '<-Indirectly read the address of D_A through ':dloop's Source redister
                  add       tmp, #1        '<-Increment to appropriate position ; LONG justified ; for this demo, try a 1 or 0 here
                  movs      :dloop, tmp    '<-Self modify ':dloop's Source register to point ot new location
                  nop                               
    ''------------------------------------------------------------------------------------------------------------------------------------------
    
    :dloop        mov       tmp, D_A    '<- Even though D_A is defined as BYTE, this will read the entire long
                                        'into tmp as little Endian
    
    
    ''------------------------------------------------------------------------------------------------------------------------------------------
                  ''Unremark one of the next 4-lines at a time to 'see' what's happening with the Demo Boards LEDs
    ''------------------------------------------------------------------------------------------------------------------------------------------
                  'ror       tmp,    #8              '<- Moves 'D-Byte' of D_A, 8 places to the RIGHT to align with DEMO Board-LED 'C-Byte'
                  'ror       tmp,    #0              '<- No alignment necessary here 'C-Byte' of D_A already aligned with DEMO Board-LED 'C-Byte'  
                  'rol       tmp,    #8              '<- Moves 'B-Byte' of D_A, 8 places to the LEFT to align with DEMO Board-LED 'C-Byte'              
                  rol       tmp,    #16             '<- Moves 'A-Byte' of D_A, 16 places to the LEFT to align with DEMO Board-LED 'C-Byte'
    ''------------------------------------------------------------------------------------------------------------------------------------------
    
                  mov       OUTA,   tmp
    NoEnd         jmp       #NoEnd
    
    ' Initialized data
    
    '                       LSB-long <--------Long 1--------> MSB-long       LSB-long <--------Long 2--------> MSB-long
    '                         A-Byte     B-Byte     C-Byte     D-Byte          A-Byte     B-Byte     C-Byte     D-Byte                    
    D_A           BYTE      %11001100, %10101010, %00111100, %11110000,      %01100110, %01010101 , %11000011, %00001111
    
    '                       MSB-long                    LSB-LONG
    '                         D-Byte   C-Byte   B-Byte   A-Byte
    LEDs          LONG      %00000000_11111111_00000000_00000000
    '                        |        |        |        |      | 
    '                        P31      P23      P15      P7     P0
    
    tmp           res       1
    
    

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Beau Schwabe

    IC Layout Engineer
    Parallax, Inc.

    Post Edited (Beau Schwabe (Parallax)) : 9/16/2009 2:29:30 AM GMT
  • Agent420Agent420 Posts: 439
    edited 2009-09-16 11:18
    This is an area that I also struggled with a bit...· The self-modifying technique works well for sequential access, where you can simply keep adding to the source/dest addresses, but if you require 'random' access it's a bit more of a pita I think.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
  • DroneDrone Posts: 433
    edited 2009-09-16 18:02
    Hi Harley,

    Have a look at Mike Green's post Posted around 8/23/2006 or 8/22/2006 (look about two thirds the way down the page) at:

    http://forums.parallax.com/showthread.php?p=601870

    This shows how to do do table look-up in PASM cog RAM; bytes as well as longs [noparse][[/noparse]note the comments and lines commented at the end with (*)]. Mike's post may provide some insight. Also 0-0 is apparently legacy nomenclature from assembler in early IBM machines. It means the "here" PASM address, which is actually the $ character in the latest prop manual. so you may use something like $-$ instead. But 0-0 is prolific in propeller example code, so my recommendation is to stick with 0-0. There was a short thread about this 0-0 thing I started not too long ago not knowing what 0-0 was with excellent feedback; but I can't find the URL right now.

    Regards, David
  • HarleyHarley Posts: 997
    edited 2009-09-16 19:16
    Thanks everyone for your suggestions. They helped get the code working properly.

    When there's time I'll need to look into the references to self-modifying code. Sounds like magic, slight of hand as a newcomer to such coding. yeah.gif

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Harley Shanko
Sign In or Register to comment.