Page 1 of 1
String Comparison Confusion
Posted: Sat Jun 30, 2018 3:50 pm
by JenniferDigital
Hello!
I was minding my own business writing a little basic program when I stumbled on some odd behaviour. I figured it may be a bug but I can't seem to find it in the EhBASIC source.
Code: Select all
p$="*"
DIM q$(1)
q$(1)="*"
PRINT p$=q$(1)
0
PRINT q$(1)=p$
-1
So, if I have a string on the left hand side it evaluates with false being true and true being false but if I have a string
array on the left hand side, it evaluates correctly. The same appears true for <>
Am I going mad?
Re: String Comparison Confusion
Posted: Sat Jun 30, 2018 5:10 pm
by Klaus2m5
Actually ?p$=p$ fails already. a=p$=p$:?a results in 1.89739E-16. It fails only in direct mode. If you put your statements into numbered program lines the results are correct in run mode.
Re: String Comparison Confusion
Posted: Sat Jun 30, 2018 5:23 pm
by JenniferDigital
Interesting clue, though I am by no means clear on how EhBASIC evaluates the expression. I've been attempting to follow LAB_EVEX, but maybe I'm barking up the wrong tree.
Re: String Comparison Confusion
Posted: Sat Jun 30, 2018 5:54 pm
by GaBuZoMeu
Strange behavior indeed. I also test it and getting the same results. In programmed mode I got:
Code: Select all
100 P$="*"
110 DIM Q$(2)
120 Q$(1) = "*"
130 V$="+"
140 PRINTP$,Q$(1),V$
150 PRINT"P$=Q$(1) ",P$=Q$(1)
160 X=P$=Q$(1)
170 PRINTX,NOT(NOT(X))
180 PRINT"V$=Q$(1) ",V$=Q$(1)
190 X=V$=Q$(1)
200 PRINTX,NOT(NOT(X))
210 PRINT"Q$(1)=P$ ",Q$(1)=P$
220 X=Q$(1)=P$
230 PRINTX,NOT(NOT(X))
240 PRINT"Q$(1)=V$ ",Q$(1)=V$
250 X=Q$(1)=V$
260 PRINTX,NOT(NOT(X))
Ready
RUN
* * +
P$=Q$(1) -1
-1 -1
V$=Q$(1) 0
1.93215E-16 0
Q$(1)=P$ -1
-1 -1
Q$(1)=V$ 0
1.93215E-16 0
Ready
1,932E-16 isn't much but even EhBasic2.22 says:
Code: Select all
?X=0
0
Ready
?NOT(NOT(X))=0
-1
Ready

Re: String Comparison Confusion
Posted: Sun Jul 01, 2018 4:48 pm
by Klaus2m5
The string compare is at LAB_1CAE. At LAB_1CE6 the strings are actually compared if they have the same length. FAC1_1 and FAC2_2 is used to hold the indirect pointer to the strings being compared. FAC2_2 was pointing to an invalid location in direct mode. Earlier in the code the string descriptor is pulled
Code: Select all
LDA FAC2_2 ; get descriptor pointer low byte
LDY FAC2_3 ; get descriptor pointer high byte
JSR LAB_22BA ; pop (YA) descriptor off stack or from top of string space
; returns with A = length, X=pointer low byte,
; Y=pointer high byte
STX FAC2_2 ; save string pointer low byte
STY FAC2_3 ; save string pointer high byte
In memory the pointer to the string descriptor is off by +$100. So I went back to LAB_EVEX to see where FAC2_2 is loaded. After some more single stepping I found it is pushed onto the stack from FAC1 and then restored to FAC2. When it is pushed to the stack via LAB_1B5B FAC1 is rounded which causes the high address to be incremented by 1 if FAC1_r is > $7f. FAC1_r is not cleared when FAC1 actually contains a memory pointer. Actually it is never cleared and so I am not so sure wether it could also go wrong in run mode.
Code: Select all
; push sign, round FAC1 and put on stack
LAB_1B5B
PLA ; get return addr low byte
STA ut1_pl ; save it
INC ut1_pl ; increment it (was ret-1 pushed? yes!)
; note! no check is made on the high byte! if the calling
; routine assembles to a page edge then this all goes
; horribly wrong !!!
PLA ; get return addr high byte
STA ut1_ph ; save it
LDA FAC1_s ; get FAC1 sign (b7)
PHA ; push sign
; round FAC1 and put on stack
LAB_1B66
JSR LAB_27BA ; round FAC1
LDA FAC1_3 ; get FAC1 mantissa3
PHA ; push on stack
LDA FAC1_2 ; get FAC1 mantissa2
PHA ; push on stack
LDA FAC1_1 ; get FAC1 mantissa1
PHA ; push on stack
LDA FAC1_e ; get FAC1 exponent
PHA ; push on stack
JMP (ut1_pl) ; return, sort of
Either FAC1_r must be cleared when FAC1 is used as a memory pointer or LAB_27BA should check wether the data type is string or number (without breaking something else of course).
Re: String Comparison Confusion
Posted: Sun Jul 01, 2018 8:52 pm
by GaBuZoMeu
Thank you Klaus.
Do you have any idea why the floating point accumulators are used during string compare??? Is it a space issue?
Re: String Comparison Confusion
Posted: Sun Jul 01, 2018 9:07 pm
by JenniferDigital
It really confuses me when a name isn't meaningful. I'd like to know why too please?
Re: String Comparison Confusion
Posted: Mon Jul 02, 2018 5:31 am
by Klaus2m5
While strings are saved from top of memory down in EhBASIC the pointers to the strings are saved like normal variables from the end of the program upwards. So when variables or strings are referenced the mechanism is at first identical and a variable or pointer will be loaded to the floating point accumulator. Up to this point there is no need for extra code and extra zero page locations.
Only when an operation is to be executed the extra steps are taken to reference the string location. For example a "+" operation will just use the loaded arguments and add them if they are variables. If they are strings they need to be concatenated which is a completely different operation. Only then the strings are actually copied to free space in the string area. An error will occur if the data type (string or variable) is not identical on both sides of the "+".
Of course this is not an exact description of what is happening but a simplified view of how it actually works.
Re: String Comparison Confusion
Posted: Mon Jul 02, 2018 6:25 am
by GaBuZoMeu
Ah, yes, I forget that Basic defaults to work with floats. And EhBasic does not use the % operator for integers - although it sometimes appears to distinguish between float and integer - at least it appears to me due to the speed it has compared to M$.
Re: String Comparison Confusion
Posted: Mon Jul 02, 2018 6:56 am
by barrym95838
... at least it appears to me due to the speed it has compared to M$.
I am by no stretch of the imagination an expert on either version, but the sources appear to me to do things in a superficially similar manner. Have you or anyone else had a chance to do any execution speed comparisons between them? OSI was the 32-bit float version, and therefore the most appropriate for the comparison.
Mike B.
Re: String Comparison Confusion
Posted: Mon Jul 02, 2018 7:34 am
by GaBuZoMeu
This entry was a response to the previous post. As it was quite a bit OT I moved it to
viewtopic.php?f=1&t=5198
Arne
Re: String Comparison Confusion
Posted: Mon Jul 02, 2018 8:07 am
by BigEd
> P.S.: Sorry - this is quite a bit OT.
But a great table of benchmark results!
Re: String Comparison Confusion
Posted: Mon Jul 02, 2018 7:09 pm
by Chromatix
Re: String Comparison Confusion
Posted: Sun Jul 08, 2018 7:25 am
by Klaus2m5
I have created 2 patches. They haven't been tested to the full extend and so I can't be sure that they don't break anything else for now!
Patch to fix the string compare of equal strings in direct mode returning FALSE:
Code: Select all
; variable name set-up
; get (var), return value in FAC_1 and $ flag
LAB_1C18
JSR LAB_GVAR ; get (var) address
STA FAC1_2 ; save address low byte in FAC1 mantissa2
STY FAC1_3 ; save address high byte in FAC1 mantissa3
LDX Dtypef ; get data type flag, $FF=string, $00=numeric
BMI LAB_1C25 ; if string then return (does RTS)
LAB_1C24
JMP LAB_UFAC ; unpack memory (AY) into FAC1
LAB_1C25
; *** begin patch string pointer high byte trashed when moved to stack
; *** add
LSR FAC1_r ; clear bit 7 (<$80) = do not round up
; *** end patch
RTS
Patch to fix FALSE value stored to a variable after string compare is not exactly zero:
Code: Select all
; perform LET
LAB_LET
JSR LAB_GVAR ; get var address
STA Lvarpl ; save var address low byte
STY Lvarph ; save var address high byte
LDA #TK_EQUAL ; get = token
JSR LAB_SCCA ; scan for CHR$(A), else do syntax error then warm start
LDA Dtypef ; get data type flag, $FF=string, $00=numeric
PHA ; push data type flag
JSR LAB_EVEX ; evaluate expression
PLA ; pop data type flag
ROL ; set carry if type = string
; *** begin patch result of a string compare stores string pointer to variable
; but should store FAC1 (true/false value)
; *** replace
; JSR LAB_CKTM ; type match check, set C for string
; BNE LAB_17D5 ; branch if string
; *** with
JSR LAB_CKTM ; type match check, keep C (expected type)
BCS LAB_17D5 ; branch if string
; *** end patch
JMP LAB_PFAC ; pack FAC1 into variable (Lvarpl) and return
; string LET
LAB_17D5
The patches above will eventually make it into my patched version of EhBASIC and my list of bugs supplied with the original version of EhBASIC. Now I am ready to have breakfast.

Re: String Comparison Confusion
Posted: Sun Jul 08, 2018 10:46 am
by GaBuZoMeu
I need to revive some old tools. This may take some time. But then I could apply these patches and verify them as well.
Brilliant work, Klaus
