Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Bit shift bug. (*solved*)
#1
Bit shift by 0, when 0 is from a variable=0, which is incorrect!


Code:
DIM num as uByte=1
DIM num2 as uByte=0

PRINT num
PRINT (num<<0)
PRINT (num<<num2)

All three lines should read "1"
Reply
#2
britlion Wrote:Bit shift by 0, when 0 is from a variable=0, which is incorrect!


Code:
DIM num as uByte=1
DIM num2 as uByte=0

PRINT num
PRINT (num<<0)
PRINT (num<<num2)

All three lines should read "1"

Code:
    ld hl, (_num2 - 1)
    ld a, (_num)
    ld b, h
__LABEL0:
    add a, a
    djnz __LABEL0

Putting a byte through HL is a bit inefficient (as opposed to ld a,(_num2) / ld b,a / ld a,(_num)- but I see the heart of the problem. DJNZ decreases first (to 255) then loops if not zero. So this does 256 bit shifts before releasing - making the result bit shift right off the top of the byte value. Not trivial to solve this and still be efficient, however. Looks like it might need a CP test Sad

I like how var<<0 is completely ignored to just print var though - very nice coding for that constant. Same code as the line above.
Reply
#3
britlion Wrote:
britlion Wrote:Bit shift by 0, when 0 is from a variable=0, which is incorrect!


Code:
DIM num as uByte=1
DIM num2 as uByte=0

PRINT num
PRINT (num<<0)
PRINT (num<<num2)

All three lines should read "1"

Code:
    ld hl, (_num2 - 1)
    ld a, (_num)
    ld b, h
__LABEL0:
    add a, a
    djnz __LABEL0

Putting a byte through HL is a bit inefficient (as opposed to ld a,(_num2) / ld b,a / ld a,(_num)- but I see the heart of the problem. DJNZ decreases first (to 255) then loops if not zero. So this does 256 bit shifts before releasing - making the result bit shift right off the top of the byte value. Not trivial to solve this and still be efficient, however. Looks like it might need a CP test Sad

I like how var<<0 is completely ignored to just print var though - very nice coding for that constant. Same code as the line above.
Yes, I supposed this was the problem. Anyway, the rule of thumb is that from the BASIC programmer point of view expr << 0 and expr << var must return the same result when 'var' = 0, as you pointed.

I could rearrange the instructions above, in the backend, to produce this:
Code:
; Loads a and h in reverse order so, a = number of shift iterations
; h = expression to shift
   ld a, (_num2 - 1)
    ld hl, (_num)
   or a ; a = 0?
   jr z, __LABEL1 ; a = 0 => No loop
    ld b, a ; Loads counter into b
   ld a, h ; Loads expression into a
__LABEL0:
    add a, a
    djnz __LABEL0
__LABEL1:
Will try to apply this patch this evening. Also, can you check if this bug happens with Uinteger and with Ulong, please?
Reply
#4
I think it's fixed for 8 bits (16 and 32 pending).
Please, download version 1.3.0s938, and tell me if it works.
This version also changes the way Floating point numbers are managed. They are some (a few) t-states slower, but uses much less memory (basically, using a subroutine), so new programs will save some precious bytes Tongue
Reply
#5
Britlion, Did you test it?
It worked for me.
Reply
#6
Test: Sadly, I still hadn't. I've been so crazy busy this month, I've done no coding at all...

I still have the same job, though. So you win on that...
Reply


Forum Jump:


Users browsing this thread: 1 Guest(s)