[fpc-devel] Math.DivMod results should be signed

k at i.fredriksen.net k at i.fredriksen.net
Wed Nov 8 17:04:23 CET 2006


I just read your posting on Delphi's DivMod.  It doesn't work very well, not on LongInt (Integer) values and negatives, not on Delphi 6, that I'm using, anyway.

I wrote an alternative that handles LongInt and negatives.  It takes only Integer parameters.  It's a function, rather than a procedure.  You pass Value (the number that you will divide), Divisor by value.  You pass Remainder (Mod-value) by ref, and it returns the Result (Div-Value).

It is almost as fast as DivMod, I have an alternative SmallInt-version that matches DivMod in speed, but handles negatives correctly.

function DivWithRemainder(Value, Divisor: Integer; var Remainder: Integer): Integer;
  {
   In:
     EAX = Value
     ECX = @Remainder
     EDX = Divisor

   Out:
     EAX = Result
     ECX = @Remainder
  }
asm
  PUSH EBX              { Save EBX - this register is not free to use }
  MOV  EBX  , EDX       { Copy Divisor to EBX, using it as a store }
  TEST EAX  , $80000000 { Test if Value is signed }
  JNZ  @Signed          { If Value is negative, prepare signed EDX }
  MOV  EDX  , 0         { If Value is positive, prepare unsigned EDX (Clear it) }
  @Continue:
  IDIV EBX              { Divides Value (actually EDX + EAX (64 bit)) by EBX. Result -> EAX, remainder -> EDX }
  MOV  [ECX], EDX       { Copies EDX to ECX^ (Remainder) }
  POP EBX               { Restore EBX }
  RET
  @Signed:
  MOV  EDX  , -1        { Fill EDX with $FFFFFFFF if Value was signed }
  JMP @Continue
end;

--
This message was sent on behalf of k at i.fredriksen.net at openSubscriber.com
http://www.opensubscriber.com/message/fpc-devel@lists.freepascal.org/3622483.html



More information about the fpc-devel mailing list