Bit Shifting in BASIC?

for bbc micro/electron hardware, peripherals & programming issues (NOT emulators!)
Post Reply
User avatar
JohnH
Posts: 37
Joined: Thu Aug 11, 2016 9:59 pm
Contact:

Bit Shifting in BASIC?

Post by JohnH » Wed Aug 24, 2016 9:41 pm

Hiya,

is there an easy way to rotate the lower nibble of a byte left and right?

I don't want to shift bit 4 to bit 5, I want it to wrap round to bit 1 and vice versa for shifting right.

A simple divide by 2 works for a right shift but you lose bit 1 I think. Maybe if you read bit 1 first (with byte AND 1?) and then right shift and somehow set bit 4 if bit 1 was set before the shift?

Same for left shift, a *2 seems to work but how to move bit 5 to bit 1 position after the shift? Some kind of AND to check if it's set before the shift and then another operation to set bit 1 after the shift if needed.

Am I on the right lines? I was thinking I might end up doing it in assembler but if I can just do it in BASIC it would simplify it a lot.

User avatar
MartinB
Posts: 5273
Joined: Mon Mar 31, 2008 9:04 pm
Location: Obscurity
Contact:

Re: Bit Shifting in BASIC?

Post by MartinB » Wed Aug 24, 2016 10:17 pm

I win! :D

Byte to play with is N% in line 10

Code: Select all

   10 N%=&B9
   20 NB%=N% AND &F
   30 B3%=(NB% AND 1)*8 
   40 B0%=NB%/8 
   50 RL%=((NB% AND 7)*2)OR B0%
   60 RR%=(NB%/2)OR B3% 
   70 NRR%=(N% AND &F0)OR RR%
   80 NRL%=(N% AND &F0)OR RL%
   90 PRINT"RIGHT ";~NRR%
  100 PRINT"LEFT  ";~NRL%

User avatar
jms2
Posts: 2402
Joined: Mon Jan 08, 2007 6:38 am
Location: Derby, UK
Contact:

Re: Bit Shifting in BASIC?

Post by jms2 » Wed Aug 24, 2016 10:21 pm

MartinB beat me to it, but as I've typed this anyway, I'll post it. :lol: My way is different actually, how about this for a right shift:

Code: Select all

DEF FNright(byte%)
=(byte% DIV 2) + (byte% MOD 2)*8
I have not tested this, just dreamed it up so it may be wrong! However I hope it will give you some ideas.

Left shifting is more difficult. ..

Code: Select all

DEF FNleft(byte%)
=(byte%*2) AND &0F + ((byte% AND &08) DIV 8)
Please try them out and let me know if they work! :D

User avatar
lurkio
Posts: 2414
Joined: Tue Apr 09, 2013 11:30 pm
Location: Doomawangara
Contact:

Re: Bit Shifting in BASIC?

Post by lurkio » Wed Aug 24, 2016 10:56 pm

Just to add to the melee...

Code: Select all

DEF FNror(b%)
LOCAL n%
n%=b% AND &F
=(b% AND &F0)+(n% DIV 2)+8*(n% MOD 2)

DEF FNrol(b%)
LOCAL n%
n%=b% AND &F
=(b% AND &F0)+2*(n% AND 7)+((n% AND 8) DIV 8)
EDIT: If you want to throw away the higher four bits of the byte b%, then delete the string "(b% AND &F0)+" from both functions.

:?:
Last edited by lurkio on Thu Aug 25, 2016 10:19 am, edited 1 time in total.

User avatar
MartinB
Posts: 5273
Joined: Mon Mar 31, 2008 9:04 pm
Location: Obscurity
Contact:

Re: Bit Shifting in BASIC?

Post by MartinB » Wed Aug 24, 2016 11:01 pm

Fact of life guys - nobody ever remembers who came second... \:D/ :lol:

(...even if yours do make mine look like it was written by a five year old :wink: )

User avatar
jgharston
Posts: 3830
Joined: Thu Sep 24, 2009 11:22 am
Location: Whitby/Sheffield
Contact:

Re: Bit Shifting in BASIC?

Post by jgharston » Wed Aug 24, 2016 11:58 pm

JohnH wrote:is there an easy way to rotate the lower nibble of a byte left and right?
I don't want to shift bit 4 to bit 5, I want it to wrap round to bit 1 and vice versa for shifting right.
Presuming you mean bit 0, etc... what I use is, assuming A% is already 0-255:
LSR A% - A%=A% DIV 2
ASL A% - (A%=A%*2) AND 255
ROR A% - A%=(A% DIV 2) OR 128*(A% AND 1)
ROL A% - A%=((A%*2) OR (A% DIV 128)) AND 255

So, reducing these to manipulate A% as a 4-bit number, assuming A% is already a 4-bit number:
LSR A% - A%=A% DIV 2
ASL A% - (A%=A%*2) AND 15
ROR A% - A%=(A% DIV 2) OR 8*(A% AND 1)
ROL A% - A%=((A%*2) OR (A% DIV 8 )) AND 15

You can expand these up to any data size, but it gets fiddly with 32-bit numbers as the arithmetic treats bit 31 as a sign bit:
LSR A% - A%=(((A%+(A%<0))DIV2)AND&7FFFFFFF) :REM The same as A%=A% >>> 1 in BASIC V.
ASL A% - A%=(A% AND &3FFFFFFF)*2 OR (&80000000 AND (A% AND &40000000)<>0) :REM A%=A% << 1 in BASIC V
ROR A% - A%=(((A%+(A%<0))DIV2)AND&7FFFFFFF) OR (&80000000 AND (A% AND 1)<>0)
ROL A% - A%=(A% AND &3FFFFFFF)*2 OR (&80000000 AND (A% AND &40000000)<>0) OR ((A%<0)AND1)

(I'm not at home atm, so I've retyped these from memory from first principles)

Code: Select all

$ bbcbasic
PDP11 BBC BASIC IV Version 0.25
(C) Copyright J.G.Harston 1989,2005-2015
>_

User avatar
JohnH
Posts: 37
Joined: Thu Aug 11, 2016 9:59 pm
Contact:

Re: Bit Shifting in BASIC?

Post by JohnH » Thu Aug 25, 2016 6:32 am

Woah! a plethora of replies, that's awesome guys.

I'll give some of those a tryout and play around with tonight after work.

Good to know from looking at them quickly that I was heading in the right direction. :D

Post Reply