Forum - MCS Electronics

 

FAQFAQ SearchSearch RegisterRegister Log inLog in

Why does double come out wrong in HEX

 
Post new topic   Reply to topic    www.mcselec.com Forum Index -> BASCOM-AVR
View previous topic :: View next topic  
Author Message
Paulvk

Bascom Member



Joined: 28 Jul 2006
Posts: 1257
Location: SYDNEY

australia.gif
PostPosted: Mon Nov 23, 2015 12:44 pm    Post subject: Why does double come out wrong in HEX Reply with quote

Why is this double printing as BFF0000000000000


Regards Paul

Code:


$regfile = "m168pdef.dat"
$crystal = 8000000
$baud = 9600
$hwstack = 100                                              ' default use 32 for the hardware stack
$swstack = 100                                              'default use 10 for the SW stack
$framesize = 100                                            'default use 40 for the frame space


Dim Wx As Double


Wx = &HFFFFFFFFFFFFFFFF

Print "Wx= " ; Hex(wx)

End
 


(BASCOM-AVR version : 2.0.7.8 )
Back to top
View user's profile
Arera

Bascom Member



Joined: 23 Sep 2007
Posts: 386
Location: Wuppertal, Germany

germany.gif
PostPosted: Mon Nov 23, 2015 5:22 pm    Post subject: Reply with quote

From the HELP (Fundamentals):

Double: 8 Bytes; 5.0 x 10^–324 to 1.7 x 10^308; Doubles are stored as signed 64 bit binary numbers

in short words: assigning FFF... all over a double does not represent the content of the straight value of all the FFFFs. Some of the Fs control the exponent and who knowes what else.
That is different to e.g. a byte or a word.

To find out more I'd suggest to google a bit, for it's a complex thing..... (at least to me).
Back to top
View user's profile
MWS

Bascom Member



Joined: 22 Aug 2009
Posts: 2262

blank.gif
PostPosted: Mon Nov 23, 2015 5:37 pm    Post subject: Re: Why does double come out wrong in HEX Reply with quote

Paulvk wrote:
Why is this double printing as BFF0000000000000

If you would tell, what you'd expect, it will tell me about your understanding of internal representation of Singles and Doubles, i.e. mantissa, exponent and value range without rounding errors.
Hex is used for exact integer representation, how should it represent a float, means how would you tell the decimal place value?
It's not possible, so instead Hex() outputs the float's memory representation.

So why try this nonsense? Means I can tell PI is 3.141592653589 and if I scale it by 1E18, I can make 3141592653589793238 and thus &hB3FBCABC55F6E260 out of it.
But why in the world should I?

Your true reason behind this may be something different, so better describe, what you want to achieve.
Back to top
View user's profile
laborratte

Bascom Expert



Joined: 27 Jul 2005
Posts: 299
Location: Berlin

germany.gif
PostPosted: Mon Nov 23, 2015 7:38 pm    Post subject: Reply with quote

The compiler is interpreting your hex number in "Wx = &HFFFFFFFFFFFFFFFF " as int64, so it means "Wx = -1". And "BFF0000000000000" is, as MWS pointed out, the memory representation of -1 for floating point type DOUBLE.
&HFFFF and &HFFFFFFFF would also be interpreted as -1 (integer and long).
Back to top
View user's profile
Paulvk

Bascom Member



Joined: 28 Jul 2006
Posts: 1257
Location: SYDNEY

australia.gif
PostPosted: Tue Nov 24, 2015 8:50 am    Post subject: Reply with quote

Hello all

I can now see what the compiler is doing it sees it as a number not setting the bits.
I needed to have a variable with 8 bytes to store the 1wire address of devices.
I then need to test 8 bytes of eeprom to see if all bits are all set to "1" new unused.
I want to do it in one step all 8 bytes at once not in a loop.

I have been able to compare the addresses of device and that stored in eeprom in one step using the double.
I can now set the bits to "1" (see below) it works but maybe not best practice I do not know.


Regards Paul




Code:

$regfile = "m168pdef.dat"
$crystal = 8000000
$baud = 9600
$hwstack = 100                                              ' default use 32 for the hardware stack
$swstack = 100                                              'default use 10 for the SW stack
$framesize = 100                                            'default use 40 for the frame space

Dim X As Byte
Dim Wx As Double
Wx = 0
Dim Bx(2) As Long At Wx Overlay
  For X = 1 To 2
      Toggle Bx(x)

  Next


Print "Wx= " ; Hex(wx)

End
 
Back to top
View user's profile
MWS

Bascom Member



Joined: 22 Aug 2009
Posts: 2262

blank.gif
PostPosted: Tue Nov 24, 2015 9:57 am    Post subject: Reply with quote

Paulvk wrote:
I can now set the bits to "1" (see below) it works but maybe not best practice I do not know.

The approach of using a double is dangerous, in case you forget one time, how floats are handled internally.
If you want to use it your way, I'd suggest to use a byte array as container and overlay it with longs.
Alternatively you may try out this:
Code:
$Regfile = "m328pdef.dat"
$Crystal = 4000000
$hwstack = 40
$swstack = 16
$framesize = 32

Const byte_to_comp = 8                                      ' bytes to compare
Dim val_A(8) As Byte                                        ' value 1
Dim val_B(8) As Byte                                        ' value 2

' val_A(2) = 1                                                ' test it

loadadr val_A , X
loadadr val_B , Z
!CLR      R6                                                ' use predefined Err in register R6 as result
!LDI      R19,      byte_to_comp                            ' R19 as counter
!cmp_start:
!LD       R20,      X+                                      ' X points to val_A
!LD       R21,      Z+                                      ' Z points to val_B
!CP       R20,      R21                                     ' compare!
!BREQ     cmp_equ                                           ' if equal all ok, next
!LDI      R19,      2^2                                     ' bitpos 2 in R6 is Err bit
!MOV      R6, R19                                           ' set Err
!LDI      R19,      1                                       ' exit at next loop
!cmp_equ:
!DEC      R19                                               ' decrease loop counter
!BRNE     cmp_start                                         ' if not zero do another loop

If Err > 0 Then
  Print "We have a miss"
Else
  Print "We got a match"
End If

End

As no compare-function exists in Bascom, I suggest to add one.


Last edited by MWS on Tue Nov 24, 2015 1:14 pm; edited 2 times in total
Back to top
View user's profile
Paulvk

Bascom Member



Joined: 28 Jul 2006
Posts: 1257
Location: SYDNEY

australia.gif
PostPosted: Tue Nov 24, 2015 10:21 am    Post subject: Reply with quote

Thank you MWS

Maybe an addition to bascom.

Can the byte_to_comp be a variable?

Bit confused here with the Y+ is that correct?
Code:

!LD       R20,      X+                                      ' X points to val_A
!LD       R21,      Y+                                      ' Z points to val_B
 


Regards Paul
Back to top
View user's profile
MWS

Bascom Member



Joined: 22 Aug 2009
Posts: 2262

blank.gif
PostPosted: Tue Nov 24, 2015 1:13 pm    Post subject: Reply with quote

Paulvk wrote:
Bit confused here with the Y+ is that correct?

No, was a typo, Y is in use by Bascom, by coincidence it did not hurt the simulation.
Quote:
Can the byte_to_comp be a variable?

Yes, but then you have to provide this variable, you can't alternatively use Const then.

Code:
'Const byte_to_comp = 8                                       ' bytes to compare
Dim byte_to_comp As Byte                                      ' bytes to compare
byte_to_comp = 8

'!LDI      R19,      byte_to_comp                             ' R19 as counter
!LDS      R19,      {byte_to_comp}                            ' R19 as counter
Back to top
View user's profile
Duval JP

Bascom Member



Joined: 22 Jun 2004
Posts: 1161
Location: France

france.gif
PostPosted: Tue Nov 24, 2015 5:47 pm    Post subject: Reply with quote

I played with the windows calculator, it give the same result: -1
Wink
jp
Back to top
View user's profile Visit poster's website
Paulvk

Bascom Member



Joined: 28 Jul 2006
Posts: 1257
Location: SYDNEY

australia.gif
PostPosted: Wed Nov 25, 2015 12:09 am    Post subject: Reply with quote

Hello MWS

Can the byte_to_comp be a variable a bascom variable eg
How to put variable B into R19
This will make it a re-usable function so bascom gets a compare function.

Code:

  Dim B as byte

 


Regards Paul
Back to top
View user's profile
MWS

Bascom Member



Joined: 22 Aug 2009
Posts: 2262

blank.gif
PostPosted: Wed Nov 25, 2015 3:55 am    Post subject: Reply with quote

Paulvk wrote:
Can the byte_to_comp be a variable a bascom variable eg
How to put variable B into R19

I've answered that already.
But the ASM can be wrapped with a regular call to a sub, this will make its use much cleaner, will see...
Back to top
View user's profile
MWS

Bascom Member



Joined: 22 Aug 2009
Posts: 2262

blank.gif
PostPosted: Wed Nov 25, 2015 12:17 pm    Post subject: Reply with quote

Here you are, ASM wrapped in a reusable function:
Code:
$Regfile = "m328pdef.dat"
$Crystal = 16000000
$hwstack = 40
$swstack = 32
$framesize = 32

Declare Function Compare(Val1 As Byte , Val2 As Byte , ByVal BtComp As Word) As Word
' purpose: byte-wise compare
' arg Val1: first value to compare, type = don't care
' arg Val2: second value to compare, type = don't care
' arg BtComp: count of bytes to compare, can be a constant or a variable
' range is 1 to 65535 bytes
' result: zero if all bytes within range of BtComp are matching
'         1 up to BtComp if there's a miss,
' zero is used for signaling a comlete match, so Config Base has no effect
' 1 is always the first byte of the variable, whatever type of variable it is

'### TEST BEGIN ###################################################################
Const testver = 0                                           ' edit for different tests

Dim mmpos As Word                                           ' dimension word var to hold the result, i.e. mismatch position
Dim btt As Word                                             ' bytes to test

#IF testver = 0
Dim val_A(8) As Byte                                        ' byte array vs. byte array
Dim val_B(8) As Byte                                        ' arrays are initialyzed 0
  btt = 8
  val_A(4) = 1                                              ' test it
#ENDIF

#IF testver = 1
Dim val_A As Double                                         ' Double vs. byte array
Dim val_B(8) As Byte
  btt = 8
  val_B(2) = 1                                              ' test it
#ENDIF

#IF testver = 2                                             ' compare strings
Dim val_A As String * 16
Dim val_B As String * 16
  btt = 12
  val_A = "Hello Bascom"
  val_B = "Hello Bascon"                                    ' find the mismatch
#ENDIF

mmpos = Compare(val_A , val_B , btt)

If mmpos > 0 Then
  Print "We have a miss at pos: " ; mmpos
Else
  Print "Match!"
End If

'### TEST END ###################################################################

End

Function Compare(Val1 As Byte , Val2 As Byte , ByVal BtComp As Word) As Word
  !LD       XL,       Y+0                                   ' get pointer to BtComp
  !LD       XH,       Y+1
  !LD       R24,      X+                                    ' R24/25 as counter
  !LD       R25,      X
  !MOVW     R16,      R24                                   ' save BtComp for later calculation of mismatch position
  !LD       XL,       Y+4                                   ' get pointer to Val1 into X
  !LD       XH,       Y+5
  !LD       ZL,       Y+2                                   ' get pointer to Val2 into Z
  !LD       ZH,       Y+3
!cmp_start:
  !LD       R20,      X+                                    ' X points to Val1
  !LD       R21,      Z+                                    ' Z points to Val2
  !CP       R20,      R21                                   ' compare!
  !BRNE     cmp_nomatch                                     ' if equal: ok, next one
  !SBIW     R24,      1                                     ' decrease loop counter
  !BRNE     cmp_start                                       ' if not zero do another turn
  !RJMP     cmp_end
!cmp_nomatch:
  !SBIW     R24,      1                                     ' else: calculate the position of compare mismatch
  !SUB      R16,      R24
  !SBC      R17,      R25
  !MOVW     R24,      R16
!cmp_end:
  !LD       XL,       Y+6
  !LD       XH,       Y+7
  !ST       X+,       R24                                   ' store success or position of mismatch
  !ST       X,        R25
End Function


Edit: Reordered the inner loop, saves 1 cycle per turn, that's 8% for one turn, which would sum up to 1000 cycles for an array of 1000 Bytes.
Back to top
View user's profile
Paulvk

Bascom Member



Joined: 28 Jul 2006
Posts: 1257
Location: SYDNEY

australia.gif
PostPosted: Thu Nov 26, 2015 10:24 am    Post subject: Reply with quote

Thank you MWS

This makes a nice addition to bascom

If I could write ASM I would write many libs like the LCD Guru.

But I am still learning to use bascom.

Maybe Mark will put it into the examples and list it in the help

Regards Paul
Back to top
View user's profile
albertsm

Administrator



Joined: 09 Apr 2004
Posts: 5921
Location: Holland

blank.gif
PostPosted: Thu Nov 26, 2015 3:51 pm    Post subject: Reply with quote

hi MWS,

well done. i can see the value of this function so i will include it in a future version.

_________________
Mark
Back to top
View user's profile Visit poster's website
MWS

Bascom Member



Joined: 22 Aug 2009
Posts: 2262

blank.gif
PostPosted: Thu Nov 26, 2015 5:01 pm    Post subject: Reply with quote

albertsm wrote:
i can see the value of this function so i will include it in a future version.

Nice to hear Wink
Back to top
View user's profile
Display posts from previous:   
Post new topic   Reply to topic    www.mcselec.com Forum Index -> BASCOM-AVR All times are GMT + 1 Hour
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum
You cannot attach files in this forum
You cannot download files in this forum