Not(Data.Bit) - Error

Discuss about beta versions of mikroBasic
compiler.
Post Reply
Author
Message
yo2lio
Posts: 1878
Joined: 19 Sep 2006 12:57
Location: Romania, Arad City
Contact:

Not(Data.Bit) - Error

#1 Post by yo2lio » 02 Nov 2007 12:12

Best regards, Florin Andrei Medrea.

http://www.microelemente.ro/
http://www.microelemente.ro/produse-si-servicii/
http://www.microelemente.ro/custom-software/

mail : florin@microelemente.ro

User avatar
zristic
mikroElektronika team
Posts: 6608
Joined: 03 Aug 2004 12:59
Contact:

Re: Not(Data.Bit) - Error

#2 Post by zristic » 02 Nov 2007 14:38

Note taken.

oliverb
Posts: 570
Joined: 24 May 2007 15:09

#3 Post by oliverb » 11 Jan 2008 10:23

You've got a tricky one to fix there.

We got hit by the same problem, and technically I'm not sure if its truely a bug, though it creates bugs alarmingly easily.

Fundamentally the problem is that a bit test returns a single bit value, 0 or 1. Interesingly a test operation such as =,>,< also returns 1 for true.

However the value of the "true" operator in a byte context is 255 rather than 1

This means that (1=1)<>true

Try evaluating

if (1=1) = true then ...

But the not operator is bitwise and therefore not 1 = 254 in a byte context.

This leads to a tricky problem, how to resolve this without breaking existing code, since it ought to work.

As a workaround portb.0 = portb.0 xor 1 should work

The safest solution I can see is to go the pascal route and implement booleans properly, but with an implied conversion from number to boolean when needed so as not to break existing code.

Under this system a bit would have type boolean. Evaluating a logic operator such as and, or, not in boolean context would result in boolean versions being used,

Examples: "A and B" is evaluated as "if A then return B else return 0", "A or B" would be "if A then return A else return B"

If you put a number into a bit it gets converted as it is now so no change there.

Starting from scratch I'd say make true=all bits set and make sure that all test operators and bit operatiors return only true or false eg 255 or 0.

It'd also be tempting to make all even numbers false and all odd numbers true, for good code optimization.
Last edited by oliverb on 11 Jan 2008 10:52, edited 1 time in total.

User avatar
zristic
mikroElektronika team
Posts: 6608
Joined: 03 Aug 2004 12:59
Contact:

#4 Post by zristic » 11 Jan 2008 10:50

The problem lies in the fact that there is no logical not operator, like in ANSI C. As it is now, mB uses not as bitwise.

Oliverb, how did you conclude that =,>,< also return 1 for true?

oliverb
Posts: 570
Joined: 24 May 2007 15:09

#5 Post by oliverb » 11 Jan 2008 11:35

Ran a sample program

aa=1
bb=1
cc=(aa=bb)

I admit I haven't tried every operator, or multiple values.

Incidentally you do appear to have a logical "not", its invoked if the argument is a test operator eg "not aa=bb" appears to evaluate correctly.

User avatar
zristic
mikroElektronika team
Posts: 6608
Joined: 03 Aug 2004 12:59
Contact:

#6 Post by zristic » 11 Jan 2008 12:04

oliverb wrote:Ran a sample program

aa=1
bb=1
cc=(aa=bb)
I tried this and I got 0xFF in cc.

oliverb
Posts: 570
Joined: 24 May 2007 15:09

#7 Post by oliverb » 11 Jan 2008 12:40

Here's where it gets wierd.

I looked at the assembly code and found I was getting:

Code: Select all

$0008	$	_main_main:
;bug03.pbas,3 :: 			aa=4
$0008	$0E04	    			MOVLW	4
$000A	$6E15	    			MOVWF	_aa, 0
;bug03.pbas,4 :: 			bb=4
$000C	$0E04	    			MOVLW	4
$000E	$6E16	    			MOVWF	_bb, 0
;bug03.pbas,5 :: 			cc=(aa=bb)
$0010	$0E01	    			MOVLW	1
$0012	$6E17	    			MOVWF	_cc, 0
Since nothing was getting tested I figure the compiler was evaluating (aa=bb) at compile time as a constant.

I tried making the variables volatile:

Code: Select all

;bug03.pbas,5 :: 			cc=(aa=bb)
$0010	$5015	    			MOVF	_aa, 0, 0
$0012	$1816	    			XORWF	_bb, 0, 0
$0014	$0EFF	    			MOVLW	255
$0016	$A4D8	    			BTFSS	STATUS, Z, 0
$0018	$0E00	    			MOVLW	0
$001A	$6E17	    			MOVWF	_cc, 0
So if the test is performed at runtime it returns 255 as expected.

User avatar
zristic
mikroElektronika team
Posts: 6608
Joined: 03 Aug 2004 12:59
Contact:

#8 Post by zristic » 11 Jan 2008 13:54

OK, I got it, it is the optimizer that induced the 1 instead of 255.

We will fix it.

janni
Posts: 5373
Joined: 18 Feb 2006 13:17
Contact:

#9 Post by janni » 11 Jan 2008 14:20

Same effect may be observed in mP even though there is type boolean defined. Declaring cc as boolean does not change anything because type boolean is only formally introduced, i.e. there is no implicit or explicit typecasting or type checking.

BTW, for properly implemented type boolean there is no need for logical operators, as bitwise ones give proper results assuming 0 and FF arguments.

Bit logic would require different approach, using the properties of assembly language rather than trying to translate bits into bytes and then using logical operators.

oliverb
Posts: 570
Joined: 24 May 2007 15:09

#10 Post by oliverb » 11 Jan 2008 16:57

Back to the original point of this though a bit test returns 0 or 1. As a result the (perfectly reasonable looking) expression "not portb.0" returned unexpected values.

Now in my opinion it ought to have returned true or false right from the beginning but to arbitrarily change that behavior now would break any code that relied on it returning 1.

Out of curiosity I wonder what values mP uses. In a strict pascal "true" is not a number but ord(true) returns 1. I think usually "ord" is just a type conversion and doesn't generate code but there's no reason why true couldn't be represented as 255 internally and the "ord" operator could generate code to convert it to 1.

janni
Posts: 5373
Joined: 18 Feb 2006 13:17
Contact:

#11 Post by janni » 11 Jan 2008 19:08

Back to the original point of this though a bit test returns 0 or 1. As a result the (perfectly reasonable looking) expression "not portb.0" returned unexpected values.
That certainly should not take place. Compiler may easily differentiate between byte and bit variable, so, assuming aa=1, following operations

Code: Select all

bb=not aa.0
cc=not aa
should produce different results (0 and 254, respectively).

It looks like mB and mP got leftovers from implementing bit logic in mC, where there is a separate logical negation. Note that other logical operations on bits, like

Code: Select all

cc=aa.1 and bb.2
produce correct results (in 0/1 representation, though).
Out of curiosity I wonder what values mP uses.
mP uses 0 and 255 to represent FALSE and TRUE (Pascal should use 0 and 1). As I've written before, boolean type is implemented only formally, and does not differ from byte. One may assign any (0..255) value to a boolean variable, and logical expressions (like in if..then) are not checked for validity of operands or results. This wouldn't be a problem if not for the bit logic.

ADDED
----------
Neither Basic nor Pascal were created with microcontrollers in mind, so they have no provision for bit logic. It's time to stop pretending that mB and mP are the same as respective implementations for big processors and appropriately adjust to the situation.

Best solution would be to operate only on bit 0 in logical expressions (any even number would then lead to FALSE, and any odd one to TRUE, just as you proposed, oliverb). In this way bit logic could be unified with the byte one (where FALSE would be represented by 0 and TRUE by 1).

Well written program should not assume any numerical values of TRUE and FALSE anyway (just use the constants whatever compiler sets them to internally), so there should not be any problems with code compatibility.

The only problem is that then the mC compiler logic would differ from mB and mP :( . ME may not like it. On the other hand, the present situation discriminates users of mB and mP.
Last edited by janni on 12 Jan 2008 18:01, edited 1 time in total.

oliverb
Posts: 570
Joined: 24 May 2007 15:09

#12 Post by oliverb » 11 Jan 2008 20:59

Thought I'd poke pascal to see what I got back.

Interestingly again "aa:=4=4;" sets aa to 1.

Also apparently the "ord" operator doesn't work on variables only constants. Seems odd as I recall that "ord" is the correct way to convert a char into a byte.

ord(true) returns 255. Now that is just plain wrong. There are only two states a boolean can have and the states are numbered from zero.

oliverb
Posts: 570
Joined: 24 May 2007 15:09

#13 Post by oliverb » 12 Jan 2008 14:44

janni wrote:ADDED
----------
Neither Basic nor Pascal were created with microcontrollers in mind, so they have no provision for bit logic. It's time to stop pretending that mB and mP are the same as respective implementations for big processors and appropriately adjust to the situation.

While I agree that Pascal wasn't created for microcontrollers I'd also disagree and say it did have provision for bit logic. Part of the beauty of having a boolean type is that it can be represented by only one bit, making it perfectly feasible for the compiler to pack booleans in eight to the byte.

Regular Pascal tends not to pack booleans unless you tell it to and many PC compilers ignore the "packed" directive but for a PIC there's no reason not to pack by default, enabling the use of bit operators.

janni
Posts: 5373
Joined: 18 Feb 2006 13:17
Contact:

#14 Post by janni » 12 Jan 2008 15:14

oliverb wrote:ord(true) returns 255. Now that is just plain wrong. There are only two states a boolean can have and the states are numbered from zero.
Yes, indeed. What we have now is two values for TRUE (1 for some bit operations and 255 for the rest) and a problem with bit negation which does not fit into any of the above.

Lets try to find a systematic approach. It really does not matter whether we assume 1 or 255 for TRUE (naturally, 0 would be FALSE) as long as we test only bit 0. It's not hard to see that all bitwise operations on byte variables produce valid logical results in such case - so there is no need for separate logical operators (and no differentiation between byte and boolean variables is necessary).

Bit logic case is more complicated, but can be systematically solved. Test operations (like in if..then or while...) should obviously test the indicated bit, rather than byte (bit 0), as in

Code: Select all

if aa.3 then ...
which also could lead to big savings in code length if bit testing assembly instructions were used.

All bitwise/logical operators should function normally (i.e as they do now, whether they produce 1 or 255 as true), but the negation - only indicated bit should be negated, for example

Code: Select all

aa=3
bb:=not aa.1 
should give bb=1. This allows for bit toggling without influencing bit testing or logical operations, like

Code: Select all

cc=bb.1 and aa.0


Special case (in mP) would be if result of bit negation was declared boolean - then obviously it should be assigned logical TRUE or FALSE. Also assignment to boolean variable, like bool:=aa.1, should work in this way.

Concluding, bit state, rather than byte value, should determine logical value. If either bit 0, or specifically indicated bit, if set, would correspond to TRUE, and if cleared, to FALSE, then both bit and byte logic could work coherently.

_________________
ADDED
Regular Pascal tends not to pack booleans unless you tell it to and many PC compilers ignore the "packed" directive but for a PIC there's no reason not to pack by default, enabling the use of bit operators.
Yes, the packed boolean array was a nice idea but mostly uniplemented (because of the underlying hardware), or implemented through macros thus producing unaceptable code overhead.
Anyway, with the approach presented above, where specified bits are being tested in conditional instructions and with not operating on bits, any variable represents practically a packed boolean array.

oliverb
Posts: 570
Joined: 24 May 2007 15:09

#15 Post by oliverb » 14 Jan 2008 21:02

janni wrote:
oliverb wrote:ord(true) returns 255. Now that is just plain wrong. There are only two states a boolean can have and the states are numbered from zero.
Yes, indeed. What we have now is two values for TRUE (1 for some bit operations and 255 for the rest) and a problem with bit negation which does not fit into any of the above.

Lets try to find a systematic approach. It really does not matter whether we assume 1 or 255 for TRUE (naturally, 0 would be FALSE) as long as we test only bit 0. It's not hard to see that all bitwise operations on byte variables produce valid logical results in such case - so there is no need for separate logical operators (and no differentiation between byte and boolean variables is necessary).
Actually the "ord" operator is about the only time when it does matter what value is returned, though it doesn't matter what value is used internally. I'm pretty sure that its in the specification for the Pascal language that ord(false)=0 and ord(true)=1, always. It doesn't matter what values are used internally for true, but when converted to integer those values are correct.

If we went with the bit 0 boolean as you proposed earlier then the ord function should be made usable on variables and if used on a boolean it should "and" it with 1 to return a legal result.

Post Reply

Return to “mikroBasic Beta testing”