Offline |
 |
Joined: Tue May 08, 2007 12:44 am Posts: 360
|
Извините, что встреваю, могу рассказать баян. В FastMM для Delphi видел классную функцию CardinalToStrBuf, обходящуюся без деления вообще: Code: {Converts a cardinal to string at the buffer location, returning the new buffer position. Note: Only supports numbers up to 2^31.} function CardinalToStrBuf(ACardinal: Cardinal; APBuffer: PAnsiChar): PAnsiChar; asm {On entry: eax = ACardinal, edx = ABuffer} push edi mov edi, edx //Pointer to the first character in edi {Calculate leading digit: divide the number by 1e9} add eax, 1 //Increment the number mov edx, $89705F41 //1e9 reciprocal mul edx //Multplying with reciprocal shr eax, 30 //Save fraction bits mov ecx, edx //First digit in bits <31:29> and edx, $1FFFFFFF //Filter fraction part edx<28:0> shr ecx, 29 //Get leading digit into accumulator lea edx, [edx + 4 * edx] //Calculate ... add edx, eax //... 5*fraction mov eax, ecx //Copy leading digit or eax, '0' //Convert digit to ASCII mov [edi], al //Store digit out to memory {Calculate digit #2} mov eax, edx //Point format such that 1.0 = 2^28 cmp ecx, 1 //Any non-zero digit yet ? sbb edi, -1 //Yes->increment ptr, No->keep old ptr shr eax, 28 //Next digit and edx, $0fffffff //Fraction part edx<27:0> or ecx, eax //Accumulate next digit or eax, '0' //Convert digit to ASCII mov [edi], al //Store digit out to memory {Calculate digit #3} lea eax, [edx * 4 + edx] //5*fraction, new digit eax<31:27> lea edx, [edx * 4 + edx] //5*fraction, new fraction edx<26:0> cmp ecx, 1 //Any non-zero digit yet ? sbb edi, -1 //Yes->increment ptr, No->keep old ptr shr eax, 27 //Next digit and edx, $07ffffff //Fraction part or ecx, eax //Accumulate next digit or eax, '0' //Convert digit to ASCII mov [edi], al //Store digit out to memory {Calculate digit #4} lea eax, [edx * 4 + edx] //5*fraction, new digit eax<31:26> lea edx, [edx * 4 + edx] //5*fraction, new fraction edx<25:0> cmp ecx, 1 //Any non-zero digit yet ? sbb edi, -1 //Yes->increment ptr, No->keep old ptr shr eax, 26 //Next digit and edx, $03ffffff //Fraction part or ecx, eax //Accumulate next digit or eax, '0' //Convert digit to ASCII mov [edi], al //Store digit out to memory {Calculate digit #5} lea eax, [edx * 4 + edx] //5*fraction, new digit eax<31:25> lea edx, [edx * 4 + edx] //5*fraction, new fraction edx<24:0> cmp ecx, 1 //Any non-zero digit yet ? sbb edi, -1 //Yes->increment ptr, No->keep old ptr shr eax, 25 //Next digit and edx, $01ffffff //Fraction part or ecx, eax //Accumulate next digit or eax, '0' //Convert digit to ASCII mov [edi], al //Store digit out to memory {Calculate digit #6} lea eax, [edx * 4 + edx] //5*fraction, new digit eax<31:24> lea edx, [edx * 4 + edx] //5*fraction, new fraction edx<23:0> cmp ecx, 1 //Any non-zero digit yet ? sbb edi, -1 //Yes->increment ptr, No->keep old ptr shr eax, 24 //Next digit and edx, $00ffffff //Fraction part or ecx, eax //Accumulate next digit or eax, '0' //Convert digit to ASCII mov [edi], al //Store digit out to memory {Calculate digit #7} lea eax, [edx * 4 + edx] //5*fraction, new digit eax<31:23> lea edx, [edx * 4 + edx] //5*fraction, new fraction edx<31:23> cmp ecx, 1 //Any non-zero digit yet ? sbb edi, -1 //Yes->increment ptr, No->keep old ptr shr eax, 23 //Next digit and edx, $007fffff //Fraction part or ecx, eax //Accumulate next digit or eax, '0' //Convert digit to ASCII mov [edi], al //Store digit out to memory {Calculate digit #8} lea eax, [edx * 4 + edx] //5*fraction, new digit eax<31:22> lea edx, [edx * 4 + edx] //5*fraction, new fraction edx<22:0> cmp ecx, 1 //Any non-zero digit yet ? sbb edi, -1 //Yes->increment ptr, No->keep old ptr shr eax, 22 //Next digit and edx, $003fffff //Fraction part or ecx, eax //Accumulate next digit or eax, '0' //Convert digit to ASCII mov [edi], al //Store digit out to memory {Calculate digit #9} lea eax, [edx * 4 + edx] //5*fraction, new digit eax<31:21> lea edx, [edx * 4 + edx] //5*fraction, new fraction edx<21:0> cmp ecx, 1 //Any non-zero digit yet ? sbb edi, -1 //Yes->increment ptr, No->keep old ptr shr eax, 21 //Next digit and edx, $001fffff //Fraction part or ecx, eax //Accumulate next digit or eax, '0' //Convert digit to ASCII mov [edi], al //Store digit out to memory {Calculate digit #10} lea eax, [edx * 4 + edx] //5*fraction, new digit eax<31:20> cmp ecx, 1 //Any-non-zero digit yet ? sbb edi, -1 //Yes->increment ptr, No->keep old ptr shr eax, 20 //Next digit or eax, '0' //Convert digit to ASCII mov [edi], al //Store last digit and end marker out to memory {Return a pointer to the next character} lea eax, [edi + 1] {Restore edi} pop edi end;
Тип Cardinal в Delphi -- это DWORD.
|
|