Byte madness

Blitz3D Forums/Blitz3D Beginners Area/Byte madness

Jimmy(Posted 2015) [#1]
Okay I´m gonna post this in the beginners portion just bc of the nature of this despite I´m by no means a beginner but this just makes me scream out of embarrassment while debugging.

Can you please spot the buggie? D prints 256 not 255 as expected?
PRINT dd and you get 255, or move the print D inside the loop, and you get 255. )

Why does it show d show up as 256? what have I´ve been missing?


; fun packing unpacking bytes

; example that tests all 4 bytes 
For a = 0 To 255
For b = 0 To 255
For c = 0 To 255
For d = 0 To 255

aa=a : bb=b : cc=c : dd=d ; we keep the original values

value = a Shl 24 + b Shl 16 + c Shl 8 + d ; PACK IT into an integer

a = value Shr 24 And 255 : b = value Shr 16 And 255 : c = value Shr 8 And 255 : d = value And 255 ; now UNPACKing

; quit if anything did go wrong with the bytes 
If aa<>a Then End
If bb<>b Then End
If cc<>c Then End
If dd<>d Then End 

; print d ;  this would show 0-255, never 256

;Print "--------"
Next : Next : Next : Delay 1 :  Print d: Next ; this d DOES show only 256?

Print "All went well" : WaitKey



steve_ancell(Posted 2015) [#2]
I'm not 100 percent sure what you're trying to achieve, but I just found that swapping 255 in all of the For loops to 254 gives 255 as a result.


Yasha(Posted 2015) [#3]
This is the nature of loops. `Next` increments its associated variable, then checks if it's still in range. On the 256th run through `Next`, d is incremented to 256, fails the test, and the loop ends.

Ideally you should never rely on the value of a loop index variable after its associated loop ends, or assume it will hold any particular value, since this is an undocumented implementation detail (and in theory, could change; there are other ways to implement a loop). The loop's over, the variable isn't being used for that any more. Set it to a new value or just don't use it.

(Are you forgetting that the `d` loop ends with the first `Next`, not the last?)


Jimmy(Posted 2015) [#4]
I´m trying to figure out why one see the counter go beyond the FOR NEXT loop.

Why 256 even pops up there. It should not.

By all means you can put eg 254 there, but then why does it show 255 then, it is the same problem.


Jimmy(Posted 2015) [#5]
Yasha I see. I´m just about trying to grasp this concept I´ve actually never seen or HAD to think about this before.

Is this common on all platforms and dialects? It feels like a bug, really, to me but I´m very confused about this discovery right now. It never occured to me before.


Yasha(Posted 2015) [#6]
Well the variable has to have some value... it's only within the loop itself that you said it specifically has to be one of the following ones. After the loop, you haven't actually told it what you want the variable to hold, so anything is valid (and therefore the value is meaningless).

In other languages (e.g. BlitzMax and C) you'd usually scope the variable declaration to the `For` and you wouldn't even be able to access it from outside, thus eliminating the question. You can't do that in B3D, sadly.


steve_ancell(Posted 2015) [#7]
0 to 255 is a range of 256, don't forget zero is included in the loop.


Jimmy(Posted 2015) [#8]
So this would mean that all code inbetween a NEXT and its respective FOR
actually contains +1 or +STEP?

I guess this makes sense for all other values before the last one.

Still need to wrap my head around this.

C++ also has this then without me evert noticing it? haha I´m glad to find out finally. This could otherwise have created some truly nasty bugs.

EDIT: Ahh scoping coming into sensible use, nice.


Jimmy(Posted 2015) [#9]
Steve true, the 0 vs 1 in loops I´ve known and used that all my life most coders learns that pretty quickly (or HAVE to rather) still, this "detail" flew right above my head.


Jimmy(Posted 2015) [#10]
Thanks guys for clearing this up. Really appreciated. I was going nuts.


Who was John Galt?(Posted 2015) [#11]
Rewriting as a while loop with the same functionality may make it clearer

x=0
while (x<256) 'i.e. 0->255, same as for loop version
     print x ' will print 0->255
     x=x+1
wend
print x ' will print 256 due to final increment which failed 'x<256' test



virtlands(Posted 2015) [#12]
;; Hi Jimmy,

;; That's the nature of FOR loops in almost any language (C, C++, BASIC,...), ...;
;; (It's my opinion that the last value of "a=256", shall remain stable, and you can depend on it for coding logic.)

For a = 0 To 255
;; When "a" increments past segment [0..255]
;; then this loop shall exit past "next"
Next

;; --- You might like REPEAT...UNTIL loops :)

z=0 ;;;;;

Repeat
z = z +1
Until z=255

;; In the case of a REPEAT...UNTIL block, "z" shall remain
;; at value 255, and shall not proceed to 256 .

Delay(10) ;;

;; .. On the other hand, here is a way for a FOR loop to stay in segment [0..255] : (Depend on "aa" instead.)

For a=0 to 255
aa = a
next

;; ---> "aa" shall stop at value 255, even though "a" runs away to 256.

End


Matty(Posted 2015) [#13]
One of the only things I learned in a programming subject I did at university 20 years ago was this:

Never ever count on the value of a for loop counter being what you expect after exiting the loop.


RGR(Posted 2015) [#14]
; fun packing unpacking bytes

; example that tests all 4 bytes 
For a = 0 To 255
	For b = 0 To 255
		For c = 0 To 255
			For d = 0 To 255
			
				aa=a : bb=b : cc=c : dd=d ; we keep the original values
				
				value = a Shl 24 + b Shl 16 + c Shl 8 + d ; PACK IT into an integer
				
				a = value Shr 24 And 255 : b = value Shr 16 And 255 : c = value Shr 8 And 255 : d = value And 255 ; now UNPACKing
				
				; quit if anything did go wrong with the bytes 
				If aa<>a Then End
				If bb<>b Then End
				If cc<>c Then End
				If dd<>d Then End 
			
				; print d ;  this would show 0-255, never 256
			
				;Print "--------"
			Next ; This is Next of the d Loop. What happens here internaly? d=d+Step (Step=1 in your case) ... if d <= 255 the Loop continues ... otherwise ends ... So it must be bigger than 255 !
		Next ; This is Next of the c Loop.
	Next ; This is Next of the b Loop.
	Delay 1
	Print d
Next ; This is Next of the a Loop.     this d DOES show only 256? Yes It should ... otherwise the d loop above would never end

Print "All went well" : WaitKey


See the comment after Next in your code ...
Use Indentation
... and remember ... Your Logic may not always be the Logic of the System ;-)
If you do not know how Next works internaly you cannot expect to be right with a statement ... *d should be 255* !?

Btw: In Blitz you can rely on the content of a Variable after exiting a Loop. Its exact the result of the last internal calculation ... and it does not get changed as long as you don't write code which changes the variable.


Below is the Code translated to assembler
Note the section
_18                           ; Next starts here
	add	[ebp-16],1    ; Adds 1
_13
	cmp	[ebp-16],255  ; Compares with 255 ( For d = 0 to 255 )
	jle	_14           ; Jump to Label _14 when lower or equal


BlitzCC V11.8
(C)opyright 2000-2003 Blitz Research Ltd
Compiling "D:\Downloads\20150101\!B3D\Jimmy.bb"
Parsing...
Generating...
Translating...

	.align	16
__MAIN
	push	ebx
	push	esi
	push	edi
	push	ebp
	mov	ebp,esp
	sub	esp,36
	sub	esp,4
	mov	eax,__DATA
	mov	[esp],eax
	call	__bbRestore
	sub	esp,4
	mov	eax,__LIBS
	mov	[esp],eax
	call	__bbLoadLibs
	call	_2_begin
	jmp	_2_leave
_2_begin
	mov	ebx,0
	mov	[ebp-4],ebx
	mov	[ebp-8],ebx
	mov	[ebp-12],ebx
	mov	[ebp-16],ebx
	mov	[ebp-20],ebx
	mov	[ebp-24],ebx
	mov	[ebp-28],ebx
	mov	[ebp-32],ebx
	mov	[ebp-36],ebx
	mov	[ebp-4],0
	jmp	_7
_8
	mov	[ebp-8],0
	jmp	_9
_10
	mov	[ebp-12],0
	jmp	_11
_12
	mov	[ebp-16],0
	jmp	_13
_14
	mov	ebx,[ebp-4]
	mov	[ebp-20],ebx
	mov	ebx,[ebp-8]
	mov	[ebp-24],ebx
	mov	ebx,[ebp-12]
	mov	[ebp-28],ebx
	mov	ebx,[ebp-16]
	mov	[ebp-32],ebx
	mov	ebx,[ebp-4]
	shl	ebx,byte 24
	mov	esi,[ebp-8]
	shl	esi,byte 16
	add	ebx,esi
	mov	esi,[ebp-12]
	shl	esi,byte 8
	add	ebx,esi
	add	ebx,[ebp-16]
	mov	[ebp-36],ebx
	mov	ebx,[ebp-36]
	shr	ebx,byte 24
	mov	esi,255
	and	ebx,esi
	mov	[ebp-4],ebx
	mov	ebx,[ebp-36]
	shr	ebx,byte 16
	mov	esi,255
	and	ebx,esi
	mov	[ebp-8],ebx
	mov	ebx,[ebp-36]
	shr	ebx,byte 8
	mov	esi,255
	and	ebx,esi
	mov	[ebp-12],ebx
	mov	ebx,[ebp-36]
	mov	esi,255
	and	ebx,esi
	mov	[ebp-16],ebx
	mov	ebx,[ebp-4]
	cmp	[ebp-20],ebx
	jz	_15
	call	_fend
_15
	mov	ebx,[ebp-8]
	cmp	[ebp-24],ebx
	jz	_16
	call	_fend
_16
	mov	ebx,[ebp-12]
	cmp	[ebp-28],ebx
	jz	_17
	call	_fend
_17
	mov	ebx,[ebp-16]
	cmp	[ebp-32],ebx
	jz	_18
	call	_fend
_18
	add	[ebp-16],1
_13
	cmp	[ebp-16],255
	jle	_14
_6
	add	[ebp-12],1
_11
	cmp	[ebp-12],255
	jle	_12
_5
	add	[ebp-8],1
_9
	cmp	[ebp-8],255
	jle	_10
_4
	sub	esp,4
	mov	[esp],1
	call	_fdelay
	sub	esp,8
	mov	eax,[ebp-16]
	mov	[esp],eax
	call	__bbStrFromInt
	mov	[esp],eax
	call	_fprint
	add	[ebp-4],1
_7
	cmp	[ebp-4],255
	jle	_8
_3
	sub	esp,8
	mov	eax,_19
	mov	[esp],eax
	call	__bbStrConst
	mov	[esp],eax
	call	_fprint
	call	_fwaitkey
	ret
_2_leave
	mov	esp,ebp
	pop	ebp
	pop	edi
	pop	esi
	pop	ebx
	ret	word 0
_19	.db	"All went well",0
	.align	4
__LIBS
	.db	"",0
	.align	4
__DATA
	.dd	0

Assembling...



virtlands(Posted 2015) [#15]
@RGR
That's neat how you got the assemebly language there. How did you do it?


RGR(Posted 2015) [#16]
Create a batch file BlitzCC.bat inside the bin Folder (easiest way) like that:

blitzcc -a -c D:\SourcePath\SourceFile.bb >D:\DestinationPath\DestinationFile.asm

Doubleclick the batchfile.
SourcePath and DestinationPath, SourceFile and DestinationFile can be the same if they have different file extensions as shown above.
Use Paths/Filenames with no blanks ... otherwise you have to use quotation marks.
.asm is a textfile you can view with any texteditor (I use Crimson Editor)


Jimmy(Posted 2015) [#17]
Thanks for great feedback !

Hi John Galt and Virtland Acatually I really like those loop analogies you both gave there, nice stuff Thanks. Matty that´s a good rule.

RGR Interesting stuff !