Einzelnen Beitrag anzeigen

Amateurprofi

Registriert seit: 17. Nov 2005
Ort: Hamburg
1.041 Beiträge
 
Delphi XE2 Professional
 
#1

Integer Werte in Binärstring umwandeln

  Alt 15. Apr 2006, 04:54
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]
Gruß, Klaus
Die Titanic wurde von Profis gebaut,
die Arche Noah von einem Amateur.
... Und dieser Beitrag vom Amateurprofi....
  Mit Zitat antworten Zitat