Starting with this source:
Code: Select all
dim as integer x,y
for i as byte = 3 to 1 step -1
x += 1
next
for i as ubyte = 3 to 1 step -1
y += 1
next
print x, y
sleep
In the generated assembly it looks like the loop code for the unsigned iterator has been intentionally bypassed:
.intel_syntax noprefix
.section .text
.balign 16
.globl _main
_main:
push ebp
mov ebp, esp
and esp, 0xFFFFFFF0
sub esp, 16
push ebx
mov dword ptr [ebp-4], 0
call ___main
push 0
push dword ptr [ebp+12]
push dword ptr [ebp+8]
call _fb_Init@12
.Lt_0001:
mov dword ptr [ebp-8], 0
mov dword ptr [ebp-12], 0
mov byte ptr [ebp-16], 3
.Lt_0006:
inc dword ptr [ebp-8]
.Lt_0004:
movsx eax, byte ptr [ebp-16]
dec eax
mov bl, al
mov byte ptr [ebp-16], bl
.Lt_0003:
movsx ebx, byte ptr [ebp-16]
cmp ebx, 1
jge .Lt_0006
.Lt_0005:
mov byte ptr [ebp-16], 3
jmp .Lt_0009 /* bypass */
.Lt_000A:
inc dword ptr [ebp-12]
.Lt_0008:
movzx ebx, byte ptr [ebp-16]
add ebx, 255
mov al, bl
mov byte ptr [ebp-16], al
.Lt_0007:
movzx eax, byte ptr [ebp-16]
cmp eax, 1
jbe .Lt_000A
.Lt_0009:
push 2
push dword ptr [ebp-8]
push 0
call _fb_PrintInt@12
push 1
push dword ptr [ebp-12]
push 0
call _fb_PrintInt@12
push -1
call _fb_Sleep@4
.Lt_0002:
push 0
call _fb_End@4
mov eax, dword ptr [ebp-4]
pop ebx
mov esp, ebp
pop ebp
ret
Commenting out the jmp .Lt_0009 statement, and building the EXE directly from the assembly code, the loop runs two times instead of three. A total of three modifications were required to force the loop to run three times:
.intel_syntax noprefix
.section .text
.balign 16
.globl _main
_main:
push ebp
mov ebp, esp
and esp, 0xFFFFFFF0
sub esp, 16
push ebx
mov dword ptr [ebp-4], 0
call ___main
push 0
push dword ptr [ebp+12]
push dword ptr [ebp+8]
call _fb_Init@12
.Lt_0001:
mov dword ptr [ebp-8], 0
mov dword ptr [ebp-12], 0
mov byte ptr [ebp-16], 3
.Lt_0006:
inc dword ptr [ebp-8]
.Lt_0004:
movsx eax, byte ptr [ebp-16]
dec eax
mov bl, al
mov byte ptr [ebp-16], bl
.Lt_0003:
movsx ebx, byte ptr [ebp-16]
cmp ebx, 1
jge .Lt_0006
.Lt_0005:
mov byte ptr [ebp-16], 3
/*jmp .Lt_0009*/
.Lt_000A:
inc dword ptr [ebp-12]
.Lt_0008:
movzx ebx, byte ptr [ebp-16]
/*add ebx, 255*/
dec ebx
mov al, bl
mov byte ptr [ebp-16], al
.Lt_0007:
movzx eax, byte ptr [ebp-16]
cmp eax, 1
/*jbe .Lt_000A*/
jge .Lt_000A
.Lt_0009:
push 2
push dword ptr [ebp-8]
push 0
call _fb_PrintInt@12
push 1
push dword ptr [ebp-12]
push 0
call _fb_PrintInt@12
push -1
call _fb_Sleep@4
.Lt_0002:
push 0
call _fb_End@4
mov eax, dword ptr [ebp-4]
pop ebx
mov esp, ebp
pop ebp
ret
IMO, given that a QB FOR…NEXT can accept negative values for
startvalue and
endvalue, the use of an unsigned iterator is a logical error that FBC should report as an error. If it were my decision, I would disallow unsigned iterators as well as iterators smaller than 32 bits.