Einzelnen Beitrag anzeigen

Amateurprofi

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

AW: Binärdarstellung einer Zahl mit einer einzigen Stringallokation

  Alt 26. Mai 2012, 20:22
Wegen Speicher ... macht es doch so wie IntToStr oder Format?

ein array[0..31] of Char als Puffer auf'm Stack,
dann einmal die Zeichen berechnen und den Puffer befüllen,
gleichzeitig werden die Bits automatisch gezählt
und zum Schluß ein SetString, wo nur einmal Speicher allociert wird.
Wirklich schnell ist das aber auch nicht.
Warum?:
Man schreibt die Daten in den Puffer und das SetStr kopiert sie dann in den String.
Besser ist, die Länge des Strings zu definieren und dann direkt in den String zu schreiben.

Die beiden nachstehenden Routinen machen das alles recht flink.
Die zweite Routine ist deutlich schneller weil bummelige Shifts vermieden werden und weil vorwärts geschrieben wird.
Die Tabelle zeigt für die Werte 0, 2^0..31 von links nach rechts
- den Wert
- benötigte CPU-Takte für gammatesters Routine (#11)
- dto für meine Routine (#9)
- dto für die erste der untenstehenden Routinen
- dto für die zweite der untenstehenden Routinen

Code:
         0 238 110 126 126
         1 578 110 126 136
         2 476 136 136 126
         4 526 162 144 144
         8 500 186 144 144
        16 502 212 152 144
        32 510 238 160 152
        64 518 262 162 160
       128 526 288 162 160
       256 534 322 170 170
       512 544 340 178 170
      1024 552 364 204 178
      2048 570 390 194 178
      4096 586 408 196 186
      8192 594 442 212 186
     16384 604 466 212 194
     32768 620 484 220 188
     65536 628 518 228 204
    131072 630 536 230 204
    262144 646 562 238 204
    524288 730 646 246 204
   1048576 738 672 246 204
   2097152 740 704 272 212
   4194304 756 722 262 220
   8388608 782 756 272 220
  16777216 790 790 288 228
  33554432 806 798 280 228
  67108864 806 824 296 228
 134217728 832 850 296 238
 268435456 850 892 314 246
 536870912 884 900 306 246
1073741824 892 926 314 254
2147483648 908 952 322 254
Delphi-Quellcode:
FUNCTION IntToBin3(v:Cardinal):string;
asm
            push ebx
            push eax // V
            push edx // @Result
            // Benötigte Länge in EBX
            xor ebx,ebx
            bsr ebx,eax // Länge-1
            lea ebx,[ebx+1] // Länge
            // Result löschen
            mov eax,edx
            call System.@UStrClr
            // Kurzfassung von NewUniCodeString
            lea eax,[ebx*2+12+2] // Länge*2 + SizeOf(StrRec) + 2
            call System.@GetMem
            mov edx,DefaultUnicodeCodePage
            and edx,$FFFF // nur LoWord
            or edx,$20000 // elemSize
            mov [eax],edx // StrRec.codePage und .elemSize
            mov [eax+4],1 // StrRec.refCnt
            mov [eax+8],ebx // StrRec.Length
            lea eax,[eax+12] // @NewString
            // @NewString in Result stellen
            pop edx
            mov [edx],eax // Result
            // Ende 00 ans Stringende schreiben
            lea eax,[eax+ebx*2] // @NewString[Len+1]
            mov word [eax],0 // Str-Terminator
            // V als Binärstring in Result schreiben
            pop edx // V
@Loop: lea eax,[eax-2]
            shr edx,1
            setc bl
            lea ebx,[ebx+$30]
            mov [eax],bx
            jne @Loop
            pop ebx
end;
Delphi-Quellcode:
FUNCTION IntToBin4(v:Cardinal):string;
asm
            push ebx
            push eax // V
            push edx // @Result
            // Benötigte Länge in EBX
            xor ebx,ebx
            bsr ebx,eax // Länge-1
            lea ebx,[ebx+1] // Länge
            // Result löschen
            mov eax,edx
            call System.@UStrClr
            // Kurzfassung von NewUniCodeString
            lea eax,[ebx*2+12+2] // Länge*2 + SizeOf(StrRec) + 2
            call System.@GetMem
            mov edx,DefaultUnicodeCodePage
            and edx,$FFFF // nur LoWord
            or edx,$20000 // elemSize
            mov [eax],edx // StrRec.codePage und .elemSize
            mov [eax+4],1 // StrRec.refCnt
            mov [eax+8],ebx // StrRec.Length
            lea eax,[eax+12] // @NewString
            mov word[eax+ebx*2],0 // Str-Terminator
            // @NewString in Result stellen
            pop edx
            mov [edx],eax // Result
            // V als Binärstring in Result schreiben
            pop edx // V
            lea eax,[eax+ebx*2] // Hinter String
            neg ebx
            lea ecx,[ebx+32] // ( v so nach links verschieben,
            shl edx,cl // Nit 31 steht )
            jmp @Entry
@Loop: add edx,edx
@Entry: sets cl // Sign Flag in BL
            lea ecx,[ecx+$30] // in Char wandeln
            mov [eax+ebx*2],cx // Char ib String schreiben
            add ebx,1
            jne @Loop // weiter bis edx leer ist
            pop ebx
end;
Gruß, Klaus
Die Titanic wurde von Profis gebaut,
die Arche Noah von einem Amateur.
... Und dieser Beitrag vom Amateurprofi....
  Mit Zitat antworten Zitat