Shop OBEX P1 Docs P2 Docs Learn Events
ASM - Move a BYTE into a LONG? — Parallax Forums

ASM - Move a BYTE into a LONG?

Ron CzapalaRon Czapala Posts: 2,418
edited 2010-09-02 03:13 in Propeller 1
I am trying to determine the best way to set the high order bits (above $1FF) using a the 8 bits in a BYTE into a LONG variable.

In the spin example below, how to accomplish this statement in PASM

LongVar.Byte[2] := bitmask


For example, the LEDs on the demo board are on pins 16 to 23.
If I have a BYTE variable that I want to set into OUTA to set those pins.

In spin it wouild like:
CON
VAR
  long LongVar
  byte ByteVar
 
PUB Main
  dira[16..23]~~                ' set to outputs
  ByteVar := %01010101     ' some changing bit pattern 
  LongVar.Byte[2] := ByteVar
  outa := LongVar  
  repeat

Comments

  • kuronekokuroneko Posts: 3,623
    edited 2010-09-01 17:58
    In SPIN you could also use outa[16..23] := ByteVar. In PASM I usually use this kind of fragment:
    mov     dira, mask              ' dira[16..23]~~
            mov     outa, #%01010101        ' |
            rev     outa, #8                ' | outa[16..23] := %01010101
    
    mask    long    $00FF0000
    
            fit
    

    You can also reach certain places (easily) with movi/movd but a shift/rotate will always do the job.
  • Ron CzapalaRon Czapala Posts: 2,418
    edited 2010-09-01 18:07
    kuroneko,
    When you execute this instruction, you are setting all 32 bits for OUTA.
    This could affect other devices on those pins, correct?


    mov outa, #%01010101
  • kuronekokuroneko Posts: 3,623
    edited 2010-09-01 18:16
    When you execute this instruction, you are setting all 32 bits for OUTA.
    This could affect other devices on those pins, correct?

    mov outa, #%01010101

    IF those bits are marked as outputs in dira then that's not an acceptable procedure. Otherwise it doesn't matter. If you want to insert stuff into a live outa then you need to prepare the data in a temporary register, e.g.
    mov     temp, #%01010101        ' %00000000_00000000_00000000_01010101
            rev     temp, #8                ' %00000000_10101010_00000000_00000000
            andn    outa, mask              ' %xxxxxxxx_00000000_xxxxxxxx_xxxxxxxx
            or      outa, temp              ' %xxxxxxxx_10101010_xxxxxxxx_xxxxxxxx
    
    mask    long    $00FF0000
    
  • Ron CzapalaRon Czapala Posts: 2,418
    edited 2010-09-01 18:54
    The temporary register seems like the right approach to be safe.
    I need to investigate the REV instruction, but I used SHL instead.

    I wasn't sure if a MOV longvar, bytevar would move the 8 bits into the lower 8 bits of the long but it does.

    I was playing with this code which accepts keys entered the Serial Terminal and displays the binary value of the key on the Demo Board's LEDs on pins 16 thru 23.
     
    {{accept a key value entered from the keyboard and display it in binary on leds pins 16..23}}
    CON
    VAR
      byte charval 
     
    OBJ
      Debug           : "Extended_FDSerial.spin"
     
    PUB Main
    '  dira[16..23]~~                     ' demo board LED pins - make output
      COGNEW(@test01, @charval)       
      Debug.start(31, 30, 0, 57600)      ' ignore tx echo on rx
      waitcnt(clkfreq * 3 + cnt)         ' Pause for FullDuplexSerial.spin to initialize
      Debug.tx(16)
      Debug.str(@testmsg)
     
      repeat
        charval := Debug.rx
        Debug.tx(13)
        Debug.tx(charval)
        Debug.tx(" ")
        Debug.Bin(charval, 8) 
        charval := charval >< 8           ' bitwise reverse byte to display on pins 16..23 
    DAT
            ORG 0
    test01
            MOV DIRA, LEDpins ' 16..23 for output
    :loop
            RDBYTE r1, PAR
            MOV temp, r1 
            SHL temp, #16
            MOV OUTA, temp
            JMP #:loop
    LEDpins LONG $FF<<16
    r1      BYTE 0
    temp    LONG 0  
    testmsg BYTE 13,"Entered characters will display in binary on pins 16-23 ", 0
    
  • kuronekokuroneko Posts: 3,623
    edited 2010-09-01 19:03
    Code looks OK, you could skip r1 and do the rdbyte directly into temp (in a cog all data is 32bit anyway). I'm a bit puzzled, you go through the trouble of using a temporary register but then move it to outa thereby clearing/affecting the 24bit you're not interested in (0..15, 24..31)?!

    Minor point, depending on timing the PASM part may pick up charval before it's reversed (SPIN is quite slow). You could probably initialise charval with the reverse of the rx method result directly.
  • Ron CzapalaRon Czapala Posts: 2,418
    edited 2010-09-01 19:33
    kuroneko,
    I modified the code to use ANDN and OR to effect only bits 16-23 and eliminated the r1 variable. Good point about the PASM code picking up the value before it is reversed, but doesn't seem to be noticeable.

    I am learning...

    Thanks,
    - Ron

    Revised code:
    {{accept a key value entered from the keyboard and display it in binary on leds pins 16..23}}
    CON
    VAR
      byte charval 
     
    OBJ
      Debug           : "Extended_FDSerial.spin"
     
    PUB Main
    '  dira[16..23]~~                     ' demo board LED pins - make output
      COGNEW(@test01, @charval)       
      Debug.start(31, 30, 0, 57600)      ' ignore tx echo on rx
      waitcnt(clkfreq * 3 + cnt)         ' Pause for FullDuplexSerial.spin to initialize
      Debug.tx(16)
      Debug.str(@testmsg)
     
      repeat
        charval := Debug.rx
        Debug.tx(13)
        Debug.tx(charval)
        Debug.tx(" ")
        Debug.Bin(charval, 8) 
        charval := charval >< 8           ' bitwise reverse byte to display on pins 16..23 
    DAT
            ORG 0
    test01
            MOV DIRA, LEDpins ' 16..23 for output
    :loop
            RDBYTE temp, PAR
            SHL    temp, #16
            ANDN   outa, LEDpins   ' clear bits 16-23 in outa
            OR     outa, temp      ' set bits 16-23 based on temp
            JMP #:loop
    LEDpins LONG $FF<<16
    temp    LONG 0  
    testmsg BYTE 13,"Entered characters will display in binary on pins 16-23 ", 0
    
  • kuronekokuroneko Posts: 3,623
    edited 2010-09-01 19:47
    I modified the code to use ANDN and OR to effect only bits 16-23 and eliminated the r1 variable. Good point about the PASM code picking up the value before it is reversed, but doesn't seem to be noticeable.

    Nice work! Yes, given how long the non-reversed state exist compared to the time it takes to send a new character it's hardly noticable. But it may lead to trouble when the wrong value is acted on. Not an issue for a simple display though.

    Regarding rev, ATM you reverse the byte in SPIN (><) then shift it up by 16 in PASM. Now imagine you promote charval to a long and use >< 24 in SPIN instead of >< 8. What happens is that the lower 24 bits get mirrored and byte[0] ends up (reversed) in byte[2], right? Then let PASM pick up a long instead of a byte. This way you save the extra shl temp, #16 (in PASM).

    Or you continue passing the raw byte value down to PASM and combine reversal and shift by using rev reg, #8 (in PASM the meaning is 32 - n where SPIN uses n).

    HTH
  • Beau SchwabeBeau Schwabe Posts: 6,568
    edited 2010-09-01 20:42
    Hope that this doesn't confuse the issue, but I thought I would bring up examples showing the differences between mov, movd, movi, and movs
    PUB Pasm
        cognew(@Entry,0)
    
    DAT
    Entry
    
    
    Example1
    
                  mov       LEDout, value
    '                       %11111111000110001100001101011010  <--- contents of value
    '                       %11111111000110001100001101011010  <--- contents of LEDout after mov
    '                                                               a mov instruction looks at all
    '                                                               32 bits.                                   
                  mov       dira,   LEDmask
                  mov       outa,   LEDout
    '                       %00000000111111110000000000000000  <--- since the LEDs on the Propeller
    '                                                               demo board only mask bits 16 to
    '                                                               the output fro this example would
    '                                                               result in ...                          
    '                       %xxxxxxxx00011000xxxxxxxxxxxxxxxx  <--- THIS
    
    '###############################################################################################
    
    Example2
    
                  movd      LEDout, value
    '                       %11111111000110001100001101011010  <--- contents of value
    '                       %xxxxxxxxxxxxxxxxxxxxxxx101011010  <--- movd only cares about the first
    '                                                               9 bits ... and will only move
    '                                                               those 9 bits into the 'd'
    '                                                               field of LEDout.  So LEDout
    '                                                               will end up looking like ...
    '                       %xxxxxxxxxxxxxx101011010xxxxxxxxx  <--- THIS
    '                       %iiiiiiiiiXXXXXdddddddddsssssssss  <--- notice the alignment to the 'd'
    '                                    ->|                        field
                  shl       LEDout, #7
    '                                |<-           
    '                       %00000000111111110000000000000000  <--- shift LEDout left by 7 to align
    '                                                               to the demo boards LEDs resulting
    '                                                               in this on the LED 
    '                       %xxxxxxxx01011010xxxxxxxxxxxxxxxx  <--- THIS ; notice you loose bit 9
    '                                                               because of the mask.  A shift of 6
    '                                                               would have kept bit 9 but then you
    '                                                               would loose bit 0
                  mov       dira,   LEDmask
                  mov       outa,   LEDout
    
    '###############################################################################################
    
    Example3
    
                  movi      LEDout, value
    '                       %11111111000110001100001101011010  <--- contents of value
    '                       %xxxxxxxxxxxxxxxxxxxxxxx101011010  <--- movi only cares about the first
    '                                                               9 bits ... and will only move
    '                                                               those 9 bits into the 'i'
    '                                                               field of LEDout.  So LEDout
    '                                                               will end up looking like ...
    '                       %101011010xxxxxxxxxxxxxxxxxxxxxxx  <--- THIS
    '                       %iiiiiiiiiXXXXXdddddddddsssssssss  <--- notice the alignment to the 'i'
    '                        |<-                                    field
                  shr       LEDout, #7
    '                              ->|    
    '                       %00000000111111110000000000000000  <--- shift LEDout right by 7 to align
    '                                                               to the demo boards LEDs resulting
    '                                                               in this on the LED 
    '                       %xxxxxxxx01011010xxxxxxxxxxxxxxxx  <--- THIS ; notice you loose bit 9
    '                                                               because of the mask.  A shift of 8
    '                                                               would have kept bit 9 but then you
    '                                                               would loose bit 0
                  mov       dira,   LEDmask
                  mov       outa,   LEDout
                   
    '###############################################################################################
    
    Example4
    
                  movs      LEDout, value
    '                       %11111111000110001100001101011010  <--- contents of value
    '                       %xxxxxxxxxxxxxxxxxxxxxxx101011010  <--- movs only cares about the first
    '                                                               9 bits ... and will only move
    '                                                               those 9 bits into the 's'
    '                                                               field of LEDout.  So LEDout
    '                                                               will end up looking like ...
    '                       %xxxxxxxxxxxxxxxxxxxxxxx101011010  <--- THIS
    '                       %iiiiiiiiiXXXXXdddddddddsssssssss  <--- notice the alignment to the 's'
    '                                             ->|               field
                  shl       LEDout, #16
    '                                |<-
    '                       %00000000111111110000000000000000  <--- shift LEDout left by 16 to align
    '                                                               to the demo boards LEDs resulting
    '                                                               in this on the LED 
    '                       %xxxxxxxx01011010xxxxxxxxxxxxxxxx  <--- THIS ; notice you loose bit 9
    '                                                               because of the mask.  A shift of 15
    '                                                               would have kept bit 9 but then you
    '                                                               would loose bit 0
                  mov       dira,   LEDmask
                  mov       outa,   LEDout
    '                                                               Note: the 'movs' instruction is
    '                                                                     most like the 'mov'
    '                                                                     instruction with the
    '                                                                     difference being that only
    '                                                                     bits 0 through 9 are affected.
    '                                                                     bits 10 to 31 are ignored.
    '
    '                                                                   - in this example you could
    '                                                                     substitute 'movs' for 'mov'
    '                                                                     and observe the same result                                                                                
    
    
    
    value         long      %11111111000110001100001101011010
    '                       %iiiiiiiiiXXXXXdddddddddsssssssss                          
    LEDmask       long      %00000000111111110000000000000000
    LEDout        long      0
    
  • Ron CzapalaRon Czapala Posts: 2,418
    edited 2010-09-01 20:49
    kuroneko,
    The REV temp, #8 instruction really threw me for a while - I didn't see how the value ended up in bits 16-23.

    After studying your helpful bit pattern comments, I could see that the lower 24 bits get reversed and the upper 8 cleared.


    Thanks again,
    - Ron
    mov     temp, #%01010101        ' %00000000_00000000_00000000_01010101
            rev     temp, #8                ' %00000000_10101010_00000000_00000000
    
  • Beau SchwabeBeau Schwabe Posts: 6,568
    edited 2010-09-01 21:32
    If the exercise is to do this in Pasm, then how about this?

    Spin Example 1 - Called as a Pasm function from Spin
    VAR
      long LongVar,ByteVarAddress,Flag
      byte ByteVar
     
    PUB Main
      dira[16..23]~~                ' set to outputs
      ByteVar := %01010101     ' some changing bit pattern
       
    '  LongVar.Byte[2] := ByteVar
      Pasm
    
      outa := LongVar
      repeat
      
    PUB Pasm
        ByteVarAddress := @ByteVar
        Flag := 1
        cognew(@Entry,@LongVar)
        repeat until Flag == 0
    
    DAT
    ''      LongVar.Byte[2] := ByteVar
    Entry
            mov             temp,      par            'address of LongVar           ;PAR+0
            add             temp,      #2       ' <--  This points to the 3rd BYTE in LongVar 
            mov             _LongVar,  temp 
    
            add             temp,      #2             'address of ByteVarAddress    ;PAR+4
            rdlong          _ByteVarAddress, temp     'read address of ByteVar
            rdbyte          _ByteVar, _ByteVarAddress 'read contents of ByteVar
    
            wrbyte          _ByteVar, _LongVar        'write contents of ByteVar to 3rd Byte of LongVar
    
            add             temp,      #4             'address of Flag              ;PAR+8
            wrlong          _Flag,     temp           'Clear Flag
    
            cogid           temp                    'get COG id
            cogstop         temp                    'terminate COG
    
    temp                    long    0
    _Flag                   long    0
    _LongVar                long    0
    _ByteVarAddress         long    0
    _ByteVar                byte    0
    

    Pasm Example
    PUB Pasm
        cognew(@Entry,@temp)
    
    DAT
    Entry
    
                  mov       temp,                   par              'PAR+0 = temp               
                  add       temp,                   #2               'PAR+2 = temp.BYTE[2]
                  
                  wrbyte    value,                  temp             'write byte to temp.BYTE[2]  
                  rdlong    temp,                   par              'read temp
    
                  mov       dira,                   LEDmask          'use LEDmask to make LED's output
                  mov       outa,                   temp             'display binary pattern on LED's
    
    temp          long      0
    value         long      %01011010
    LEDmask       long      %00000000111111110000000000000000
    



    If you just want a clever way to do it in Spin you could do this...

    Spin Example 2 - Variable aliasing
    PUB Main
      dira[16..23]~~                ' set to outputs
      ByteVar := %01010101          ' some changing bit pattern
    
      outa := LongVar
      repeat
    
    DAT
    LongVar   long
              byte 0
              byte 0
    ByteVar   byte 0
              byte 0
    
  • Ron CzapalaRon Czapala Posts: 2,418
    edited 2010-09-02 03:13
    Beau,
    Thanks for the code examples. I just started learning PASM several days ago, so I was just experimenting with ways to manipulate data and using the Serial Monitor to get data to pass to PASM routines.

    I also wanted a framework to test out [puzzle] PASM beginners only code.

    Your variable aliasing example gave me pause until I remembered that data is stored in little-endian format.

    Thanks again.
Sign In or Register to comment.