Problem mit 80bit Zahlen

Anfängerfragen zum Programmieren mit PureBasic.
- chris -
Beiträge: 195
Registriert: 24.08.2005 19:52
Wohnort: Stadtallendorf

Re: Problem mit 80bit Zahlen

Beitrag von - chris - »

Hier das ganze für 32Bit und 64bit (80bit Umwandeln nach Double).
@Helle, Ist das so korrekt?
Wie sieht dann der umgedrehte Fall aus (Double Umwandeln nach 80bit)?

Code: Alles auswählen


EnableExplicit

Procedure.d ExtendedFloat2Double(buffer.i)

  Protected value.d

  If buffer

    CompilerSelect #PB_Compiler_Processor

      CompilerCase #PB_Processor_x86

         !lea eax,[p.v_value]
         !mov edx,[p.v_buffer]
         !fld tword[edx]
         !fstp qword[eax]

      CompilerCase #PB_Processor_x64

         !lea rax,[p.v_value]
         !mov rdx,[p.v_buffer]
         !fld tword[rdx]
         !fstp qword[rax]

    CompilerEndSelect

  EndIf

  ProcedureReturn value
EndProcedure

Define *buffer, value.d, buffer$, n.i, b$

*buffer = AllocateMemory(10)
If *buffer = 0
  End
EndIf  

buffer$ = "00:00:00:00:00:00:00:A8:04:40"
Debug buffer$

For n = 0 To 9
  b$ = "$" + StringField(buffer$, n + 1, ":")
  PokeA(*buffer + n, Val(b$))
Next n

value = ExtendedFloat2Double(*buffer)

Debug value

PB v5.72 x86/x64
Windows 10 Pro 64bit
Benutzeravatar
Helle
Beiträge: 566
Registriert: 11.11.2004 16:13
Wohnort: Magdeburg

Re: Problem mit 80bit Zahlen

Beitrag von Helle »

Ist oK. Umwandeln in ExtDouble ist natürlich auch möglich; je nach Ausgangswert tritt aber (natürlich) ein Genauigkeitsverlust auf:

Code: Alles auswählen

;Beispiele für 64-Bit-Windows, für 32-Bit: rax zu eax und rdx zu edx ändern
Buffer.i = AllocateMemory(10)
ValueF.f = 42.0
ValueD.d = 42.0

!jmp @f  ;sonst wird ValueT als Code interpretiert
ValueT:
!ValueT dt 42.0
!@@:

Debug "Byte-weise Hex von Float 42.0 (4 Bytes) :"
For n = 0 To 2
  ValueF$ + RSet(Hex(PeekA(@ValueF + n)), 2, "0") + ":"
Next n
ValueF$ + Hex(PeekA(@ValueF + n))
Debug ValueF$
Debug "============================================================"

Debug "Byte-weise Hex von Double 42.0 (8 Bytes) :"
For n = 0 To 6
  ValueD$ + RSet(Hex(PeekA(@ValueD + n)), 2, "0") + ":"
Next n
ValueD$ + Hex(PeekA(@ValueD + n))
Debug ValueD$
Debug "============================================================"

Debug "Byte-weise Hex von ExtDouble 42.0 (10 Bytes) :"
For n = 0 To 8
  ValueT$ + RSet(Hex(PeekA(?ValueT + n)), 2, "0") + ":"
Next n
ValueT$ + Hex(PeekA(?ValueT + n))
Debug ValueT$
Debug "============================================================"

;Konvertierung von Float in ExtDouble
!lea rax,[v_ValueF]
!mov rdx,[v_Buffer]
!fld dword[rax]
!fstp tword[rdx]
Debug "Byte-weise Hex von ExtDouble 42.0 (10 Bytes), konvertiert von Float :"
For n = 0 To 8
  ValueTKF$ + RSet(Hex(PeekA(Buffer + n)), 2, "0") + ":"
Next n 
ValueTKF$ + Hex(PeekA(Buffer + n))
Debug ValueTKF$
Debug "============================================================"

;Konvertierung von Double in ExtDouble
!lea rax,[v_ValueD]
!mov rdx,[v_Buffer]
!fld qword[rax]
!fstp tword[rdx]
Debug "Byte-weise Hex von ExtDouble 42.0 (10 Bytes), konvertiert von Double :"
For n = 0 To 8
  ValueTKD$ + RSet(Hex(PeekA(Buffer + n)), 2, "0") + ":"
Next n 
ValueTKD$ + Hex(PeekA(Buffer + n))
Debug ValueTKD$

Debug "================================================================"
Debug "Bis hierher gab es noch keinen Genauigkeitsverlust, aber jetzt :"
Debug "================================================================"

ValueF1.f = 42.123456789012345678
ValueD1.d = 42.123456789012345678

!jmp @f  ;sonst wird ValueT1 als Code interpretiert
ValueT1:
!ValueT1 dt 42.123456789012345678
!@@:

Debug "Byte-weise Hex von Float 42.123456789012345678 (4 Bytes) :"
For n = 0 To 2
  ValueF1$ + RSet(Hex(PeekA(@ValueF1 + n)), 2, "0") + ":"
Next n
ValueF1$ + Hex(PeekA(@ValueF1 + n))
Debug ValueF1$
Debug "============================================================"

Debug "Byte-weise Hex von Double 42.123456789012345678 (8 Bytes) :"
For n = 0 To 6
  ValueD1$ + RSet(Hex(PeekA(@ValueD1 + n)), 2, "0") + ":"
Next n
ValueD1$ + Hex(PeekA(@ValueD1 + n))
Debug ValueD1$
Debug "============================================================"

Debug "Byte-weise Hex von ExtDouble 42.123456789012345678 (10 Bytes) :"
For n = 0 To 8
  ValueT1$ + RSet(Hex(PeekA(?ValueT1 + n)), 2, "0") + ":"
Next n
ValueT1$ + Hex(PeekA(?ValueT1 + n))
Debug ValueT1$
Debug "============================================================================"

;Konvertierung von Float in ExtDouble
!lea rax,[v_ValueF1]
!mov rdx,[v_Buffer]
!fld dword[rax]
!fstp tword[rdx]
Debug "Byte-weise Hex von ExtDouble 42.123456789012345678 (10 Bytes), konvertiert von Float :"
For n = 0 To 8
  ValueTKF1$ + RSet(Hex(PeekA(Buffer + n)), 2, "0") + ":"
Next n 
ValueTKF1$ + Hex(PeekA(Buffer + n))
Debug ValueTKF1$
Debug "============================================================================"

;Konvertierung von Double in ExtDouble
!lea rax,[v_ValueD1]
!mov rdx,[v_Buffer]
!fld qword[rax]
!fstp tword[rdx]
Debug "Byte-weise Hex von ExtDouble 42.123456789012345678 (10 Bytes), konvertiert von Double :"
For n = 0 To 8
  ValueTKD1$ + RSet(Hex(PeekA(Buffer + n)), 2, "0") + ":"
Next n 
ValueTKD1$ + Hex(PeekA(Buffer + n))
Debug ValueTKD1$

Gruß
Helle
- chris -
Beiträge: 195
Registriert: 24.08.2005 19:52
Wohnort: Stadtallendorf

Re: Problem mit 80bit Zahlen

Beitrag von - chris - »

Hier wieder das ganze für 32Bit und 64bit (80bit nach Double und Double nach 80bit)

Code: Alles auswählen


EnableExplicit

;Konvertierung von ExtDouble in Double (80bit -> 64bit)
Procedure.d ExtDouble2Double(buffer.i)

  Protected value.d

  If buffer

    CompilerSelect #PB_Compiler_Processor

      CompilerCase #PB_Processor_x86

         !lea eax,[p.v_value]
         !mov edx,[p.v_buffer]
         !fld tword[edx]
         !fstp qword[eax]

      CompilerCase #PB_Processor_x64

         !lea rax,[p.v_value]
         !mov rdx,[p.v_buffer]
         !fld tword[rdx]
         !fstp qword[rax]

    CompilerEndSelect

  EndIf

  ProcedureReturn value
EndProcedure

;Konvertierung von Double in ExtDouble (64bit -> 80bit)
Procedure Double2ExtDouble(buffer.i, value.d)

  If buffer

    CompilerSelect #PB_Compiler_Processor

      CompilerCase #PB_Processor_x86

         !lea eax, [p.v_value]
         !mov edx, [p.v_buffer]
         !fld qword[eax]
         !fstp tword[edx]

      CompilerCase #PB_Processor_x64

         !lea rax,[p.v_value]
         !mov rdx,[p.v_buffer]
         !fld qword[rax]
         !fstp tword[rdx]

    CompilerEndSelect

  EndIf

EndProcedure

Define *buffer, value.d, buffer$, n.i, b$

*buffer = AllocateMemory(10)
If *buffer = 0
  End
EndIf

value = 42.0

Double2ExtDouble(*buffer, value)

buffer$ = ""
For n = 0 To 9
  b$ = RSet(Hex(PeekA(*buffer + n)), 2, "0")
  buffer$ = buffer$ + b$
  If n < 9
    buffer$ = buffer$ + ":"
  EndIf
Next n
Debug buffer$

value = ExtDouble2Double(*buffer)

Debug value

PB v5.72 x86/x64
Windows 10 Pro 64bit
Antworten