A little byte problem

BlitzMax Forums/BlitzMax Beginners Area/A little byte problem

Algo(Posted 2004) [#1]
Whats going on here?

This code runs forever.

Global b:byte
For b=0 To 255
	Print b
Next

It seems to be reseting back to 0 too soon.


skn3(Posted 2004) [#2]
Very stange.


marksibly(Posted 2004) [#3]
Works fine on the Mac!

Must be a bug in the x86 code...


ashmantle(Posted 2004) [#4]
yep, runs forever on x86 version here too


FlameDuck(Posted 2004) [#5]
Well here it does count up to 255, but then it just starts over, much like what would happen in the following code:
Global b:Byte = 0
While b < 256
	Print b
	b:+1
End While
Interestingly, this doesn't work either:
Global s:Short
For s = 0 To 65535
	Print s
Next



Panno(Posted 2004) [#6]
yes it will only run up to 254
without the print get follow asm code


look here
_3:
add byte [edx],1
_9:
movzx eax,byte [edx]
cmp eax,255 !
jle _5 !
_4:
mov eax,0
jmp _6
_6:
pop ebp
ret


Hotcakes(Posted 2004) [#7]
Hehehehee bmx on x86 adds one to the variable and then checks to see if it is over the loop's count limit. By that time, the variable has reset to 0 ;]


Floyd(Posted 2004) [#8]
It's the same for regular integers.

Apparently this bug was always in Blitz, but nobody noticed.
I guess there's not much call for loops that go up to 2147483647.


EOF(Posted 2004) [#9]
*EDIT* Working now .. see post below.

This only prints 2,3,4,5 (missing the 1) ...
framework brl.basic

Local b:Byte

For b=1 To 5
 Print b
next



Damien Sturdy(Posted 2004) [#10]
ive not come across this, and ive written a simple emulator that did 0-255....

oh wait.. there were no "bytes" in blitz.. so it would work with those values.. hmm...
I must say, this is interesting. Mark, whats the plan? ^.^


Damien Sturdy(Posted 2004) [#11]
ive not come across this, and ive written a simple emulator that did 0-255....

oh wait.. there were no "bytes" in blitz.. so it would work with those values.. hmm...
I must say, this is interesting. Mark, whats the plan? ^.^

its okay for this to wrap forever as its understandable, (well, as a programmer used to 6502, 8 bit assembler)
Global b:Byte = 0
While b < 256
	Print b
	b:+1
End While


however the following realy should work. maybe a simple clause will fix it in the compiler? i dont know. i know as much about Bmax's infrastructure as i do x86 assembly... hehehe. (nothing by the way)

Global b:byte
For b=0 To 255
	Print b
Next



Floyd(Posted 2004) [#12]
@JimB

The 1 to 5 loop works here. Are you sure the 1 was missing?

I've gotten seriously confused by apparently missing console output. Sometimes the window will scroll down even when the output is nowhere near the bottom.


Panno(Posted 2004) [#13]
@jimb
will work here

framework brl.basic
Local b:Byte

For b=1 To 5
Print b
next
1
2
3
4
5


FlameDuck(Posted 2004) [#14]
yes it will only run up to 254
Huh? Runs up to 255 here...

JimBs example also prints the one here.

What kind of CPU's has everyone got?


EOF(Posted 2004) [#15]
@Floyd,
Mmmm, bizzare. it works now.
Restarting the IDE (Win32 Beta) must have cured the output fault.

@FD,
CPU=Pentium 4 Mobile 3.06Ghz


BODYPRINT(Posted 2004) [#16]
if you make it a local it works here, but global keeps looping??

CPU=3.2Ghz P4


FlameDuck(Posted 2004) [#17]
if you make it a local it works here, but global keeps looping??
Yeah same here. Wierd that.

CPU = 3.6 GHz Prescott.


Michael Reitzenstein(Posted 2004) [#18]
It kind of makes sense, because I bet globals are being written to memory and read in again, whereas the local version will be stored in a register pernamently.


Hotcakes(Posted 2004) [#19]
That's exactly what's happenning.


ImaginaryHuman(Posted 2004) [#20]
My interpretation is this:

Because you are asking for your loop variable to be a byte, and the biggest value you can store in a byte is 255, I think the For..Next loop perhaps adds 1 to the loop value PRIOR to testing to see if it is *greater than* the highest amount of the loop counter ie 255. So it would go something like this:

Counter is at 253
Do the loop with counter at 253
Add 1 to the loop counter
Is the counter>255? no, its 254, loop round
Counter is at 254
Do the loop with counter at 254
Add 1 to the loop counter
Is the counter >255 .... counter is now 255 but not >255, loop around
Counter is at 255
Do the loop with counter at 255
Add 1 to the loop counter - should be 256 but 256 in binary is %100000000 and since the variable is only a byte, the `1` bit is ignored - it thinks counter=%00000000
Is the counter>255? ... should be yes but it only reads Counter as a byte which has gone beyond its numerical range, so Counter=0, keep looping
and looping
and loping forever because this keeps happening.

That's my take on it. The loop counter is checking for a number greater than the loop limit, and adds the step to the counter at the END of each loop, BEFORE deciding whether to do another iteration. So if your loop limit is equal to the maximum number that can be stored in a variable of a given type (ie byte word long etc), there is an `overflow` that accidentally produces a value of 0 again, keeping the loop going.

If this is true, you could *probably* test it by also doing a short/word sized loop, going from 0 to 65535, and when it reaches 65535 the counter should internally become %10000000000000000 (65536), even though only the lower 16-bits are recognized (=0).

Maybe someone can test if this is the reason behind it. If so, maybe the Blitz developers need to come up with a fix to this design flaw.

I am also expecting that when you define the Counter as a Local, it works, because Locals are kept in registers which are usually 32-bit, and I expect there is no difference in speed between comparing a byte value and comparing a long value, so it probably knows that the number reaches 256 instead of seeing it as 0?

If this isn't exactly the reasoning behind it my second guess is perhaps the loop-counter value is held in an `immediate` value in assembly language, ie something like cmp #255,register, and really it needs to be a 16-bit compare in order to avoid the overflow problem?

Feedback please.


FlameDuck(Posted 2004) [#21]
I am also expecting that when you define the Counter as a Local, it works, because Locals are kept in registers which are usually 32-bit, and I expect there is no difference in speed between comparing a byte value and comparing a long value, so it probably knows that the number reaches 256 instead of seeing it as 0?
I'm thinking this sounds probable.