ASM - Move a BYTE into a LONG?
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:
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
mov dira, mask ' dira[16..23]~~ mov outa, #%01010101 ' | rev outa, #8 ' | outa[16..23] := %01010101 mask long $00FF0000 fitYou can also reach certain places (easily) with movi/movd but a shift/rotate will always do the job.
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 $00FF0000I 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 ", 0Minor 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.
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 ", 0Nice 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
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 0The 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_00000000Spin 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 0Pasm 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 %00000000111111110000000000000000If 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 0Thanks 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.