Looks like a compiler bug, see below the code generated.
Changing result.i to quad forces some other code generation to cope with data larger than 32 bits, so the compiler does not rely on the ebx register anymore and so the bug does not happen.
Code:
Define result.i, sNextChar.s
sNextChar = "3": result = 0
Debug "Val=" + Str(Val(sNextChar)) ;Correctly returns 3
Debug("Peek=" + Str( PeekA(?Lookup))) ;Correctly returns 0 (Lookup value index 0)
Debug("Peek=" + Str( PeekA(?Lookup + Val(sNextChar)) )) ;Correctly returns 3 (Lookup value index 3)
;THIS WORKS:
result = PeekA(?Lookup + Val(sNextChar))
Debug("result=" + Hex(result)) ;Correctly returns 3
;THIS FAILS, why!? the logic is essentially the same
result = 0
; result = result + PeekA(?Lookup + Val(sNextChar))
! MOV ebx,dword [v_result] ; ebx contains the value of result
! MOV ebp,l_lookup
! MOV edi,ebp
! PUSH dword [v_sNextChar]
! CALL _PB_Val_UNICODE@4
! MOV ecx,ebx
! SAR ecx,31
! PUSH ecx
! PUSH ebx
! MOV ecx,edi
! SAR ecx,31
! PUSH ecx
! PUSH edi
! PUSH edx
! POP edx
! ADD [esp],eax
! ADC [esp+4],edx
! MOV ebx,[esp] ; ebx is overwritten with the memory address ?Lookup + Val(sNextChar)
! ADD esp,8
! MOV eax,ebx
! PUSH eax
! CALL _PB_PeekA@4
; ! MOV ebx,dword [v_result] ; brutal reload of result into ebx, just to test this
! ADD ebx,eax ; without the line above, this sum the above memory address and 3
! MOV dword [v_result],ebx
Debug("result=" + Hex(result)) ;result is now 0x43353E !??!? (Expected: 3). And im only adding a single byte (PeekA) to result.i, which was 0 ... but somehow going from 0 to a strange address
DataSection
Lookup:
! db 0,1,2,3,4,5 ;eg if sNextChar = "3" we get ?Lookup+Val("3")= the fourth value which is 3
EndDataSection
Tested on Windows 7