Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Library: Algorithmen (https://www.delphipraxis.net/28-library-algorithmen/)
-   -   Delphi Integer Werte in Binärstring umwandeln (https://www.delphipraxis.net/67477-integer-werte-binaerstring-umwandeln.html)

Amateurprofi 15. Apr 2006 04:54


Integer Werte in Binärstring umwandeln
 
Da dieses Thema immer mal wieder angesprochen wird, und weil ich gerade eine solche Funktion brauchte, habe ich
zwei Assembler Funktionen geschrieben, die integer bzw int64 Werte in Binärstrings umwandeln.
Das ganze läßt sich natürlich auch in Pascal leicht realisieren, jedoch sind diese Funktionen deutlich schneller.
Über Verbessererungsvorschläge und/oder Kritik freute ich mich.

Delphi-Quellcode:
{------------------------------------------------------------------------------}
{ IntToBin (integer)                                                         }
{ Wandelt value in einen String mit der Länge len um, der die unteren len Bits }
{ von value in binärer Darstellung zeigt.                                     }
{ Wenn len<=0 oder len>32 ist, entscheidet die Position des höchsten 1-Bits   }
{ in value über die Länge des Strings, wobei aber, wenn value leer ist,       }
{ mindestens ein Zeichen ausgegeben wird                                      }
{------------------------------------------------------------------------------}
FUNCTION IntToBin(value,len:integer):string;
const bits:array[0..63] of char=
         '0000000100100011010001010110011110001001101010111100110111101111';
asm
               // EAX Wert
               // EDX Länge
               // ECX Zeiger Result
               push    edi
               mov     edi,ecx          // Zeiger auf Result
               or      edx,edx
               je      @DefineLen       // len = 0, benötigte Länge holen
               cmp     edx,32
               jbe     @Start           // 0 < len <= 32
@DefineLen:   bsr     edx,eax          // Index höchstes Bit in Value
               jnz     @AdjustLen
               xor     edx,edx
@AdjustLen:   add     edx,1
@Start:       push    eax              // value
               mov     eax,edi          // Zeiger Result
               call    System.@LStrSetLength
               mov     edi,[edi]        // Zeiger String
               mov     ecx,[edi-4]      // Länge
               pop     eax              // value
               sub     ecx,4
               jc      @EndDW           // weniger als 4 bits
               // Jeweils 4 Bits umwandeln
@LoopDW:      mov     edx,eax
               and     edx,$F
               mov     edx,DWORD [bits+edx*4]
               mov     [edi+ecx],edx
               shr     eax,4
               je      @FillZero
               sub     ecx,4
               jnc     @LoopDW          // nochmal 4 Bits
@EndDW:       // Restline 1..3 Bytes
               and     eax,$F
               mov     eax,DWORD [bits+eax*4]
               cmp     cl,$FE
               ja      @3Bytes
               je      @2Bytes
               jnp     @End
               rol     eax,8
               mov     [edi],al
               jmp     @End
@2Bytes:      shr     eax,16
               mov     [edi],ax
               jmp     @End
@3Bytes:      mov     [edi],ah
               shr     eax,16
               mov     [edi+1],ax
               jmp     @End
               // Mit 0en auffüllen
               // ECX = Anzahl
@FillZero:    mov     eax,'0000'
               mov     edx,ecx
               shr     ecx,2
               rep     stosd
               mov     ecx,edx
               and     ecx,3
               rep     stosb
@End:         pop     edi
end;

{------------------------------------------------------------------------------}
{ IntToBin (int64)                                                           }
{ Wandelt value in einen String mit der Länge len um, der die unteren len Bits }
{ von value in binärer Darstellung zeigt.                                     }
{ Wenn len<=0 oder len>64 ist, entscheidet die Position des höchsten 1-Bits   }
{ in value über die Länge des Strings, wobei aber, wenn value leer ist,       }
{ mindestens ein Zeichen ausgegeben wird                                      }
{------------------------------------------------------------------------------}
FUNCTION IntToBin(value:int64; len:integer):string;
const bits:array[0..63] of char=
         '0000000100100011010001010110011110001001101010111100110111101111';
asm
               // EAX Länge
               // EDX Zeiger Result
               // [EBP+8] = LoValue
               // [EBP+12] = HiValue
               push    ebx
               push    edi
               mov     edi,edx       // Zeiger Result
               mov     ebx,[ebp+8]   // LoValue
               mov     ecx,[ebp+12]  // HiValue
               // len prüfen
               mov     edx,eax
               or      edx,edx
               je      @DefineLen    // len = 0, benötigte Länge holen
               cmp     edx,64
               jbe     @Start
@DefineLen:   mov     eax,33
               bsr     edx,ecx       // EAX=Höchstes Bit in HiValue
               jnz     @AdjustLen    // HiValue nicht leer
               mov     eax,1
               bsr     edx,ebx       // EAX=Höchstes Bit in LoValue
               jnz     @AdjustLen    // LoValue nicht leer
               xor     edx,edx
@AdjustLen:   add     edx,eax       // Länge=BitPos+1
@Start:       mov     eax,edi       // Zeiger Result
               call    System.@LStrSetLength
               mov     edi,[edi]        // Zeiger String
               mov     ecx,[edi-4]      // Länge
               mov     edx,[ebp+12]     // HiValue
               // Jeweils 4 Bits umwandeln
@LoopDW:      sub     ecx,4
               jc      @EndDW           // weniger als 4 bits
               mov     eax,ebx          // LoValue
               and     eax,$F
               mov     eax,DWORD [bits+eax*4]
               mov     [edi+ecx],eax
               shrd    ebx,edx,4         // Value 4 Bits nach unten
               shr     edx,4
               jne     @LoopDW          // HiValue nicht leer
               or      ebx,ebx
               jne     @LoopDW          // LoValue nicht leer
               // Mit 0en auffüllen
@FillZero:    mov     eax,'0000'
               mov     edx,ecx
               shr     ecx,2
               rep     stosd
               mov     ecx,edx
               and     ecx,3
               rep     stosb
               jmp     @End
@EndDW:       // Restline 1..3 Bytes
               and     ebx,$F
               mov     eax,DWORD [bits+ebx*4]
               cmp     cl,$FE
               ja      @3Bytes
               je      @2Bytes
               jnp     @End
               rol     eax,8
               mov     [edi],al
               jmp     @End
@2Bytes:      shr     eax,16
               mov     [edi],ax
               jmp     @End
@3Bytes:      mov     [edi],ah
               shr     eax,16
               mov     [edi+1],ax
@End:         pop     edi
               pop     ebx
end;
Hagen hat folgende Alternativen gepostet:
Delphi-Quellcode:
function IntToBIN(Value: Cardinal): String;
var
  I: Integer;
begin
  Result := StringOfChar('0', 32);
  I := 32;
  while Value <> 0 do
  begin
    if Odd(Value) then Result[I] := '1';
    Dec(I);
    Value := Value shr 1;
  end;  
end;

function IntToBIN(Value: Cardinal): String;
var
  I: Integer;
begin
  Result := StringOfChar('0', 32);
  I := 32;
  while Value <> 0 do
  begin
    Result[I] := Char(Ord('0') + Ord(Odd(Value)));
    Dec(I);
    Value := Value shr 1;
  end;  
end;

function IntToBIN(Value: Cardinal): String;
const
  cChar: array[Boolean] of Char = ('0', '1');
var
  I: Integer;
  M: Cardinal;
begin
  SetLength(Result, 32);
  M := 1;
  for I := 32 downto 1 do
  begin
    Result[I] := cChar[Value and M <> 0];
    Inc(M, M);
  end;
end;

function IntToBIN(Value: Cardinal): String;
const
  cChar: array[Boolean] of Char = ('0', '1');
var
  I: Integer;
begin
  SetLength(Result, 32);
  for I := 1 to 32 do
  begin
    Result[I] := cChar[Value and $80000000 <> 0];
    Inc(Value, Value);
  end;
end;

function IntToBIN(Value: Cardinal): String;
var
  I: Integer;
begin
  SetLength(Result, 32);
  for I := 1 to 32 do
  begin
    Result[I] := Char(Ord('0') + (Value shr 31));
    Inc(Value, Value);
  end;
end;

function IntToBIN(Value: Cardinal): String;
var
  I: Integer;
begin
  Result := StringOfChar('0', 32);
  I := 1;
  while Value <> 0 do
  begin
    if Value and $80000000 <> 0 then Result[I] := '1';
    Inc(I);
    Inc(Value, Value);
  end;
end;
[edit=Chakotay1308]Code aktualisiert und Hagen's Alternativen hinzugefügt. Mfg, Chakotay1308[/edit]


Alle Zeitangaben in WEZ +1. Es ist jetzt 07:06 Uhr.

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz