[Back to NUMBERS SWAG index] [Back to Main SWAG index] [Original]

    program hexlong;

    const hexstr = '7fffffff';
    const hexstr1 = '80000000';

      function Hex2Long(S: string): Longint;
      var
        Temp: Longint;
        Err: Integer;
      begin
        Insert('$',S,1);
        Val(S, Temp, Err);
        Hex2Long := Temp;
      end;

    begin
      writeln (hexstr, ' = ', hex2long(hexstr));
      writeln ('MAXLONGINT = ', maxlongint);
      writeln (hexstr1, ' = ', hex2long(hexstr1));
      readln;
    end.

    ------------------------------------------------------------------------

    7fffffff = 2147483647
    MAXLONGINT = 2147483647
    80000000 = -2147483648

    ------------------------------------------------------------------------

    The values output are 100% correct.

    Mike Phillips
    INTERNET:  phil4086@utdallas.edu

    procedure UnsignedStr(L:longint; var S:string); assembler;
    var
     TS:array[0..9] of char; { Temp string, it's stored backwards }
    asm
     mov di,ds     { Save DS }
     mov si,ss     { Set DS:SI to TS }
     mov ds,si
     lea si,TS[10]
     mov bx,10     { Divide by 10 }
     mov cx,word ptr [L]    { Get L to ax:cx }
     mov ax,word ptr [L+2]
    @NotFin:
     xor dx,dx     { Divide ax:cx by 10 to cx:ax, remainder in dx }
     div bx
     xchg ax,cx
     div bx
     add dl,48     { Convert remainder to ASCII }
     dec si
     mov [si],dl   { Save in TS }
     xchg ax,cx    { Swap ax and cx to prepare for next divide }
     or ax,ax      { Already zero? }
     jnz @NotFin   { No -> continue }
     or cx,cx      { Also for high word... }
     jnz @NotFin
     lea cx,TS[10] { Get length of string }
     sub cx,si
     mov dx,di     { Move saved DS to dx }
     les di,S      { Get pointer of result string }
     cld
     mov al,cl     { Store length }
     stosb
     rep movsb     { Copy ASCII string }
     mov ds,dx     { Restore DS }
    end;

    var
     I:longint;
     J:integer;
     S:string;
    begin
     Val('$FFFFFFFF',I,J);
     UnsignedStr(I,S);
     WriteLn(S,',',J);
    end.

    Function Hex2Long(S:String):LongInt; Assembler;

    Asm
               les di,[S]
               xor bx,bx
               mov dx,bx
               mov cl,[es:di]
               inc di
    @@CnvLoop: mov al,[es:di]
               inc di
               mov ah,'0'
               cmp al,'9'
               jbe @@Cnv2Num
                      mov ah,'a'+10
                      cmp al,'a'
                      jae @@Cnv2Num
               mov ah,'A'+10
    @@Cnv2Num: sub al,ah
               shl dx,4
               mov ch,bh
               shr ch,4
               add dl,ch
               shl bx,4
               add bl,al
               dec cl
               jnz @@CnvLoop
               mov ax,bx
    End;

    This is untested, off-the-top-of-my-head code, but it should work.  If
    it doesn't just let me know and I will write a tested version for you.

    John Baldwin
    jbaldwin@freedomnet.com

    {----------------------------------------------------------------}

    PROGRAM Hexadecimal_To_Long_Converter;

    USES Crt;

    FUNCTION IsXDigit(CONST c: char): boolean;
    { -- TRUE iff C is a hexadecimal digit, i.e.
      -- C IN ['A' .. 'F', 'a' .. 'f', '0' .. '9']. }
    INLINE($5B/$80/$FB/$30/$72/$21/$80/$FB/$39/$77/$02/$EB/$16/$80/$FB/$41/$72/
           $07/$80/$FB/$46/$77/$02/$EB/$0A/$80/$FB/$61/$72/$09/$80/$FB/$66/$77/
           $04/$B0/$01/$EB/$02/$B0/$00);

    { -- Oh alright, I copied the above routine from one of my units ... }

    FUNCTION HexChar2Byte(CONST c: char): byte;
    { -- Convert a hex digit to its decimal value.
      -- Note: no argument checking. }
    BEGIN IF c IN ['0' .. '9']
          THEN HexChar2Byte:=byte(c) - 48
          ELSE HexChar2Byte:=byte(upcase(c)) - 55
    END;

    TYPE str8 = STRING[8];  { -- Hex strings in TP cannot exceed 8 characters. }

    FUNCTION Hex2Long(CONST St: str8; VAR longvalue: longint): boolean;
    { -- Will attempt to convert a hexadecimal string to its decimal value.
      -- If this is succesful, the function result is TRUE, and the computed
      -- value is in LONGVALUE.
      -- If the routine fails (i.e, ST contains bad characters), FALSE is
      -- returned and LONGVALUE is undefined. }
    VAR power_of_16: longint;
        j          : byte;
    BEGIN Hex2Long:=FALSE;  { -- Assume failure. }
          FOR j:=1 TO length(St) DO IF NOT IsXDigit(St[j]) THEN exit;

          {$Q-  -- Necessary but harmless. }
          longvalue:=0; power_of_16:=1;
          FOR j:=length(St) DOWNTO 1
          DO BEGIN inc(longvalue, HexChar2Byte(St[j]) * power_of_16);
                   power_of_16:=power_of_16 * 16
             END;
          {$Q+  -- "Pop all your pushes". }

          Hex2Long:=TRUE
    END;

    { -- Main: }

    VAR St: str8;
        L : longint;

    BEGIN clrscr;
          REPEAT gotoxy(1, 2); ClrEol;
                 write('Hex-string: '); readln(St);
                 gotoxy(20, 2);
                 IF Hex2Long(St, L)
                 THEN write(' --> ', L:1)
                 ELSE write(#7'Not a hex number ...');
                 readkey
          UNTIL St = ''
    END.

    The principle is this:

    decimal: 357 = 7*10^0 + 5*10^1 + 3*10^2
    hex    : a9f = f*16^0 + 9*16^1 + a*16^2

    in which "^" is the exponentiation operator.

    For the mathematically challenged among you:
    X^0 = 1 (any X), and X^1 = X (ditto).

    {-------------------------------------   LEE BARKER -------------------- }
    function hex2bin (s:string):longint;
      const h : array[0..15] of char = '0123456789ABCDEF';
            i,j : integer;
            x : longint;
      begin
        x := 0;
        for i := 1 to length(s) do
        begin
          j := pos(upcase(s[i]),h) -1;
            if j<0 then exit;             { error in str }
            if x and $F0000000 <> 0 then exit; { overflo }
          x := (x shl 4) + j;
        end;
        hex2bin := x;
      end;

[Back to NUMBERS SWAG index] [Back to Main SWAG index] [Original]