AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Sprachen und Entwicklungsumgebungen Object-Pascal / Delphi-Language Delphi asm MulDiv64 C übersetzung stürzt ab ...
Thema durchsuchen
Ansicht
Themen-Optionen

asm MulDiv64 C übersetzung stürzt ab ...

Ein Thema von stoxx · begonnen am 19. Feb 2008 · letzter Beitrag vom 5. Mär 2008
 
Benutzerbild von stoxx
stoxx

Registriert seit: 13. Aug 2003
1.111 Beiträge
 
#1

asm MulDiv64 C übersetzung stürzt ab ...

  Alt 19. Feb 2008, 06:21
beim Übersetzen eines C Quelltextes tritt noch ein GleitkommadivisionsFehler auf...
Wissen die Assembler Profis mehr?
Vielen Dank schonmal !!


Delphi-Quellcode:


type Var128 = packed record
 DW : array[0..3] of DWORD;
end;

function xMulDiv64(operant, multiplier, divider : int64) : int64; stdcall;
var
  quotient : Var128;

//   // Declare 128bit storage
//   struct{
//      unsigned long DW[4];
//   }var128, quotient;
//   // Change semantics for intermediate results for Full Div
//   // by renaming the vars
//   #define REMAINDER quotient
//   #define QUOTIENT edi
begin


asm

      mov      eax, dword ptr[operant+4]
      xor      eax, dword ptr[multiplier+4]
      xor      eax, dword ptr[divider+4]
      pushfd
end;



   // Take absolute values because algorithm is for unsigned only
   operant      := ABS(operant);
   multiplier   := ABS(multiplier);
   divider      := ABS(divider);

asm

      // First check divider for 0
      mov      eax, dword ptr[divider+4]
      or      eax, dword ptr[divider]
      jnz      @@dividerOK
      div      eax
@@dividerOK:
      lea      edi,[var128]               // edi = &var128
      // Check multiplier for 1 or 0
      xor      eax, eax
      cmp      eax, dword ptr[multiplier+4]
      jnz      @@startMUL
      cmp      eax, dword ptr[multiplier]
      jnz      @@multiNotNUL
      xor      edx, edx
      popfd                           // cleanup stack
      jmp      @@done
@@multiNotNUL:
      // Set result HI part to 0
      xor      eax,eax
      mov      dword ptr[edi+12], eax
      mov      dword ptr[edi+8], eax
      mov      eax, 1
      cmp      eax, dword ptr[multiplier]
      jnz      @@smallMUL
      // Multiplier is 1 so just copy operant to result
      mov      eax, dword ptr[operant+4]
      mov      dword ptr[edi+4], eax
      mov      eax, dword ptr[operant]
      mov      dword ptr[edi], eax
      jmp      @@startDIV
@@smallMUL:
      // Test for 32/32 bit multiplication
        xor      eax, eax
        mov      ecx, dword ptr[operant+4]
        or ecx, eax //;test for both hiwords zero.
      jnz      @@startMUL
      // Do 32/32 bit multiplication
        mov      ecx, dword ptr[multiplier]
      mov      eax, dword ptr[operant]
      mul      ecx
      mov      dword ptr[edi+4], edx
      mov      dword ptr[edi], eax
      jmp      @@startDIV
@@startMUL:
      // Check signs
      // Multiply: var128 = operant * multiplier
      mov      eax, dword ptr[multiplier]      // eax = LO(multiplier)
      mul      dword ptr[operant]            // edx:eax = eax * LO(operant)
      mov      dword ptr[edi], eax            // var128.DW0 = eax
      mov      ecx, edx                  // ecx = edx

      mov      eax, dword ptr[multiplier]      // eax = LO(multiplier)
      mul      dword ptr[operant+4]         // edx:eax = eax * HI(operant)
      add      eax, ecx                  // eax = eax + ecx
      adc      edx, 0                     // edx = edx + 0 + carry
      mov      ebx, eax
      mov      ecx, edx

      mov      eax, dword ptr[multiplier+4]
      mul      dword ptr[operant]
      add      eax, ebx
      mov      dword ptr[edi+4], eax
      adc      ecx, edx
      pushfd

      mov      eax, dword ptr[multiplier+4]
      mul      dword ptr[operant+4]
      popfd
      adc      eax, ecx
      adc      edx, 0
      mov      dword ptr[edi+8], eax
      mov      dword ptr[edi+12], edx
@@startDIV:
      // Divide: var128 = var128 / divider
      //
      // Test divider = 32bit value
      mov      eax, dword ptr[divider+4]
      cmp      eax, 0
      jnz      @@fullDIV
      mov      ecx, dword ptr[divider]
      cmp      ecx, 1
      jz      @@applySign

      // Start 128/32 bit division
      mov      eax, dword ptr[edi+12]
      xor      edx, edx
      div      ecx
      mov      dword ptr[quotient+12], eax

      mov      eax, dword ptr[edi+8]
      div      ecx
      mov      dword ptr[quotient+8], eax

      mov      eax, dword ptr[edi+4]
      div      ecx
      mov      dword ptr[quotient+4], eax

      mov      eax, dword ptr[edi]
      div      ecx
      mov      dword ptr[quotient], eax
      
      // Copy the quotient to the result storage (var128)
      mov      eax, dword ptr[quotient+12]
      mov      dword ptr[edi+12], eax
      mov      eax, dword ptr[quotient+8]
      mov      dword ptr[edi+8], eax
      mov      eax, dword ptr[quotient+4]
      mov      dword ptr[edi+4], eax
      mov      eax, dword ptr[quotient]
      mov      dword ptr[edi], eax
      // To sign correction and return
      jmp      @@applySign

@@fullDIV:
      // Full 128/64 bit division
      xor      eax, eax
      mov      dword ptr[quotient+12], eax
      mov      dword ptr[quotient+8], eax
      mov      dword ptr[quotient+4], eax
      mov      dword ptr[quotient], eax

      mov      ecx, 128
@@loop1:
      // Compute REMAINDER:QUOTIENT = REMAINDER:QUOTIENT shl 1
      shl      dword ptr[edi], 1
      rcl      dword ptr[edi+4], 1
      rcl      dword ptr[edi+8], 1
      rcl      dword ptr[edi+12], 1
      rcl      dword ptr[quotient], 1
      rcl      dword ptr[quotient+4], 1
      rcl      dword ptr[quotient+8], 1
      rcl      dword ptr[quotient+12], 1

      // Test (REMAINDER >= Divider)
      xor      eax, eax
      cmp      dword ptr[quotient+12], eax
      ja      @@iftrue
      jb      @@iffalse

      cmp      dword ptr[quotient+8], eax
      ja      @@iftrue
      jb      @@iffalse

      mov      eax, dword ptr[quotient+4]
      cmp      eax, dword ptr[divider+4]
      ja      @@iftrue
      jb      @@iffalse

      mov      eax, dword ptr[quotient]
      cmp      eax, dword ptr[divider]
      jb      @@iffalse
@@iftrue:
      // Remainder = remainder - divider
      mov      eax, dword ptr[divider]
      sub      dword ptr[quotient], eax
      mov      eax, dword ptr[divider+4]
      sbb      dword ptr[quotient+4], eax
      xor      eax, eax
      sbb      dword ptr[quotient+8], eax
      sbb      dword ptr[quotient+12], eax
      // Quotient = quotient +1
      add      dword ptr[edi], 1
      adc      dword ptr[edi+4], 0
      adc      dword ptr[edi+8], 0
      adc      dword ptr[edi+12], 0
@@iffalse:
      // Loop size = 101 bytes, is less than 127 so loop is possible
      loop   @@loop1

@@applySign:
      // Correct the sign of the result based on the stored combined sign
      popfd
      jns      @@storeRes
      not      dword ptr[edi+12]
      not      dword ptr[edi+ 8]
      not      dword ptr[edi+ 4]
      not      dword ptr[edi]
      add      dword ptr[edi], 1
      adc      dword ptr[edi+ 4], 0
      adc      dword ptr[edi+ 8], 0
      adc      dword ptr[edi+12], 0

@@storeRES:
      // Get low order qword from var128
      mov      edx, dword ptr[edi+4]
      mov      eax, dword ptr[edi]
@@done:
   
   // result is returned in edx:eax
END;
end;


Delphi-Quellcode:
/*
 *   Source file:      MulDiv64.cpp
 *   Author:            Richard van der Wal
 *   Contact:         [email]R.vdWal@xs4all.nl[/email]
 *
 *   Description:
 *      Implementation for MulDiv64 and MulShr64
 *
 *   $Log: $
 */


/*
 * MulDiv64
 * Multiplies an operant by a multiplier and divides the result by a divider
 * Used for scaling 64 bit integer values
 * Xscaled = Xstart * Multiplier / Divider
 * Uses 128 bit intermediate result
 */
#define ABS64(num) (num >=0 ? num : -num)
//
__int64 _stdcall MulDiv64(__int64 operant, __int64 multiplier, __int64 divider)
{
   // Declare 128bit storage
   struct{
      unsigned long DW[4];
   }
var128, quotient;
   // Change semantics for intermediate results for Full Div
   // by renaming the vars
   #define REMAINDER quotient
   #define QUOTIENT edi

   // Save combined sign on stack
   _asm{
      mov      eax, dword ptr[operant+4]
      xor      eax, dword ptr[multiplier+4]
      xor      eax, dword ptr[divider+4]
      pushfd
   }


   // Take absolute values because algorithm is for unsigned only
   operant      = ABS64(operant);
   multiplier   = ABS64(multiplier);
   divider      = ABS64(divider);

   _asm{
      // First check divider for 0
      mov      eax, dword ptr[divider+4]
      or      eax, dword ptr[divider]
      jnz      dividerOK
      div      eax
dividerOK:
      lea      edi,[var128]               // edi = &var128
      // Check multiplier for 1 or 0
      xor      eax, eax
      cmp      eax, dword ptr[multiplier+4]
      jnz      startMUL
      cmp      eax, dword ptr[multiplier]
      jnz      multiNotNUL
      xor      edx, edx
      popfd                           // cleanup stack
      jmp      done
multiNotNUL:
      // Set result HI part to 0
      xor      eax,eax
      mov      dword ptr[edi+12], eax
      mov      dword ptr[edi+8], eax
      mov      eax, 1
      cmp      eax, dword ptr[multiplier]
      jnz      smallMUL
      // Multiplier is 1 so just copy operant to result
      mov      eax, dword ptr[operant+4]
      mov      dword ptr[edi+4], eax
      mov      eax, dword ptr[operant]
      mov      dword ptr[edi], eax
      jmp      startDIV
smallMUL:
      // Test for 32/32 bit multiplication
        xor      eax, eax
        mov      ecx, dword ptr[operant+4]
        or      ecx, eax        ;test for both hiwords zero.
      jnz      startMUL
      // Do 32/32 bit multiplication
        mov      ecx, dword ptr[multiplier]
      mov      eax, dword ptr[operant]
      mul      ecx
      mov      dword ptr[edi+4], edx
      mov      dword ptr[edi], eax
      jmp      startDIV
startMUL:
      // Check signs
      // Multiply: var128 = operant * multiplier
      mov      eax, dword ptr[multiplier]      // eax = LO(multiplier)
      mul      dword ptr[operant]            // edx:eax = eax * LO(operant)
      mov      dword ptr[edi], eax            // var128.DW0 = eax
      mov      ecx, edx                  // ecx = edx

      mov      eax, dword ptr[multiplier]      // eax = LO(multiplier)
      mul      dword ptr[operant+4]         // edx:eax = eax * HI(operant)
      add      eax, ecx                  // eax = eax + ecx
      adc      edx, 0                     // edx = edx + 0 + carry
      mov      ebx, eax
      mov      ecx, edx

      mov      eax, dword ptr[multiplier+4]
      mul      dword ptr[operant]
      add      eax, ebx
      mov      dword ptr[edi+4], eax
      adc      ecx, edx
      pushfd

      mov      eax, dword ptr[multiplier+4]
      mul      dword ptr[operant+4]
      popfd
      adc      eax, ecx
      adc      edx, 0
      mov      dword ptr[edi+8], eax
      mov      dword ptr[edi+12], edx
startDIV:
      // Divide: var128 = var128 / divider
      //
      // Test divider = 32bit value
      mov      eax, dword ptr[divider+4]
      cmp      eax, 0
      jnz      fullDIV
      mov      ecx, dword ptr[divider]
      cmp      ecx, 1
      jz      applySign

      // Start 128/32 bit division
      mov      eax, dword ptr[edi+12]
      xor      edx, edx
      div      ecx
      mov      dword ptr[quotient+12], eax

      mov      eax, dword ptr[edi+8]
      div      ecx
      mov      dword ptr[quotient+8], eax

      mov      eax, dword ptr[edi+4]
      div      ecx
      mov      dword ptr[quotient+4], eax

      mov      eax, dword ptr[edi]
      div      ecx
      mov      dword ptr[quotient], eax
      
      // Copy the quotient to the result storage (var128)
      mov      eax, dword ptr[quotient+12]
      mov      dword ptr[edi+12], eax
      mov      eax, dword ptr[quotient+8]
      mov      dword ptr[edi+8], eax
      mov      eax, dword ptr[quotient+4]
      mov      dword ptr[edi+4], eax
      mov      eax, dword ptr[quotient]
      mov      dword ptr[edi], eax
      // To sign correction and return
      jmp      applySign

fullDIV:
      // Full 128/64 bit division
      xor      eax, eax
      mov      dword ptr[REMAINDER+12], eax
      mov      dword ptr[REMAINDER+8], eax
      mov      dword ptr[REMAINDER+4], eax
      mov      dword ptr[REMAINDER], eax

      mov      ecx, 128
loop1:
      // Compute REMAINDER:QUOTIENT = REMAINDER:QUOTIENT shl 1
      shl      dword ptr[QUOTIENT], 1
      rcl      dword ptr[QUOTIENT+4], 1
      rcl      dword ptr[QUOTIENT+8], 1
      rcl      dword ptr[QUOTIENT+12], 1
      rcl      dword ptr[REMAINDER], 1
      rcl      dword ptr[REMAINDER+4], 1
      rcl      dword ptr[REMAINDER+8], 1
      rcl      dword ptr[REMAINDER+12], 1

      // Test (REMAINDER >= Divider)
      xor      eax, eax
      cmp      dword ptr[REMAINDER+12], eax
      ja      iftrue
      jb      iffalse

      cmp      dword ptr[REMAINDER+8], eax
      ja      iftrue
      jb      iffalse

      mov      eax, dword ptr[REMAINDER+4]
      cmp      eax, dword ptr[divider+4]
      ja      iftrue
      jb      iffalse

      mov      eax, dword ptr[REMAINDER]
      cmp      eax, dword ptr[divider]
      jb      iffalse
iftrue:
      // Remainder = remainder - divider
      mov      eax, dword ptr[divider]
      sub      dword ptr[REMAINDER], eax
      mov      eax, dword ptr[divider+4]
      sbb      dword ptr[REMAINDER+4], eax
      xor      eax, eax
      sbb      dword ptr[REMAINDER+8], eax
      sbb      dword ptr[REMAINDER+12], eax
      // Quotient = quotient +1
      add      dword ptr[QUOTIENT], 1
      adc      dword ptr[QUOTIENT+4], 0
      adc      dword ptr[QUOTIENT+8], 0
      adc      dword ptr[QUOTIENT+12], 0
iffalse:
      // Loop size = 101 bytes, is less than 127 so loop is possible
      loop   loop1

applySign:
      // Correct the sign of the result based on the stored combined sign
      popfd
      jns      storeRes
      not      dword ptr[edi+12]
      not      dword ptr[edi+ 8]
      not      dword ptr[edi+ 4]
      not      dword ptr[edi]
      add      dword ptr[edi], 1
      adc      dword ptr[edi+ 4], 0
      adc      dword ptr[edi+ 8], 0
      adc      dword ptr[edi+12], 0

storeRES:
      // Get low order qword from var128
      mov      edx, dword ptr[edi+4]
      mov      eax, dword ptr[edi]
done:
   }

   // result is returned in edx:eax
}
Phantasie ist etwas, was sich manche Leute gar nicht vorstellen können.
  Mit Zitat antworten Zitat
 


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 07:28 Uhr.
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz