Search code examples
delphimathinline-assemblybasm

Delphi read overflow flag


If I do this

var
  a,b,c:cardinal;
begin
  a:=$80000000;
  b:=$80000000;
  c:=a+b;
end;

c will equal 0, since the addition overflowed. What's the best way to catch this overflowed boolean? (a+b<a) or (a+b<b)? a really nice way would be with inline assembler, but I'm not that prolific in assembler (though my guess would be it would envolve something like JO)


Solution

  • In assembly the term Overflow usually refers to signed arithmetic and means that the sign of the sum is different from the signs of both operands; for unsigned arithmetic the term Carry is preferable.

    You can implement addition with Overflow (Carry) check in pure pascal:

    // signed add - returns True if no overflow produced
    function SAdd(A, B: integer; out C: integer): Boolean;
    begin
      C:= A + B;
      Result:= (A xor B < 0)   // operands have different signs
            or (C xor A >= 0); // sum has the same sign as operands
    end;
    
    // unsigned add - returns True if no carry produced
    function UAdd(A, B: Cardinal; out C: Cardinal): Boolean;
    begin
      C:= A + B;
      Result:= (C >= A);
    end;
    

    The same functions in assembly - optimized variant of Andreas' solution:

    // Signed Add
    function SAdd(A, B: Integer; out C: Integer): Boolean;
    asm
            ADD   EAX,EDX
            MOV   [ECX],EAX
            SETNO AL
    end;
    
    // Unsigned Add
    function UAdd(A, B: Cardinal; out C: Cardinal): Boolean;
    asm
            ADD   EAX,EDX
            MOV   [ECX],EAX
            SETNC AL
    end;