Registriert seit: 17. Nov 2005
Ort: Hamburg
1.087 Beiträge
Delphi XE2 Professional
|
Integer Werte in Binärstring umwandeln
15. Apr 2006, 05: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....
|