Посоветуйте, пожалуйста, алгорифм для преобразования короткого вещественного в строку. (У меня есть один, просто хочется сравнить их оптимизированность). Спасибо.
1. последовательными делениями на 10 Код (Text): ConvertNumberToString: __asm { mov ebx,NumOfSymbols;//EBX is a dot position counter lea edx,StrOut+4933 ;//Initialization fninit fstcw word ptr CRu ;//Control word for rounding to nearest number fstcw word ptr CRd or word ptr CRd,0xc00;//Control word for rounding to null fld tbyte ptr Number ftst ;//Checking sign fstsw ax sahf mov Sign,0 jnc Plus1 mov Sign,-1 fabs ;//Find Abs(Num) Plus1: fild dword ptr NumOfSymbols fldl2t fmulp st(1),st(0) fld st(0) fldcw word ptr CRd frndint fsubr st(0),st(1) f2xm1 fld1 faddp st(1),st(0) fscale fxch st(1) fstp st ;//ST0=10**NumOfSymbols fldcw CRu ;//Set rounding mode fmulp st(1),st(0) ;//Number*10**NumOfSymbols to use Number Mod 10 fld st(0) fstp tbyte ptr Number;//Save Number frndint fld qword ptr _10_ fxch st(1) Cycle: fldcw CRu FindRem: fprem fcomi st(0),st(1) jnc FindRem ;//Get full remainder fistp dword ptr temp mov eax,temp ;//EAX=Current digit or integer indeterminance test eax,eax js Error ;//EAX contains integer indefinity: Number is not a number or is infinity or denormalized number or al,0x30 ;//Convert digit to ASCII dec edx ;//Decrease position of symbol mov byte ptr [edx],al fld tbyte ptr Number fdiv st(0),st(1) ;//Get quotient fld st(0) fstp tbyte ptr Number;//Save Number fldcw CRd ;//Set rounding to null frndint dec ebx ;//Decrease position jnz DoNotPutDot ;//If not zero then dot is not in this position dec edx ;//Else decrease digit position counter mov byte ptr [edx],'.';//and put the dot DoNotPutDot: ftst fstsw ax sahf jnz Cycle ;//If quotient is non-null, continue cycle cmp ebx,0 jng DotAlreadyPut PutZeros: dec edx ;//If the dot is not put yet mov byte ptr [edx],0x30;//Then fill the rest of positions with zeros dec ebx jnz PutZeros ;//Continue the cycle if it isn't time to put dot sub edx,2 mov word ptr [edx],('.'*256+0x30);//Put string "0." DotAlreadyPut: cmp Sign,0 je Plus2 ;//If the number is greater than zero, the minus sign is not needed dec edx mov byte ptr [edx],'-';//If Number<0 the first symbol is '-' Plus2: mov StrAddr,edx ;//Save string address 2. через BCD-представление. тут можно заюзать MMX+XMM. Код (Text): jmp ConvertFloatToASCII Zero: mov dword ptr [edi],'0' jmp End ConvertFloatToASCII: lea edi,StrOut fninit fld tbyte ptr [Number] ftst fstsw ax sahf je Zero jnc Plus mov [edi],'-' add edi,1 fabs Plus: add edi,1 fldcw word ptr [_77F_] fldlg2 fld st(1) fyl2x frndint fld st(0) fbstp tbyte ptr [lgNum] fild [_15_] fsubrp st(1),st(0) fldl2t fmulp st(1),st(0) fld st(0) fldcw word ptr [_F7F_] frndint fsubr st(0),st(1) f2xm1 fld1 faddp st(1),st(0) fscale fstp st(1) fldcw word ptr [_37F_] fmulp st(1),st(0) fbstp tbyte ptr [BCDNum] mov eax,dword ptr [BCDNum] mov ecx,dword ptr [BCDNum+4] bswap eax bswap ecx mov dword ptr [BCDNum+4],eax mov dword ptr [BCDNum],ecx movq xmm0,qword ptr [BCDNum] movaps xmm1,xmm0 pand xmm0,_0F_0F_ psrlq xmm1,4 pand xmm1,_0F_0F_ punpcklbw xmm1,xmm0 por xmm1,_30_30_ movups [edi],xmm1 movzx eax,byte ptr [edi] mov byte ptr [edi],'.' mov byte ptr [edi-1],al mov byte ptr [edi+16],'e' mov eax,dword ptr [lgNum+6] rol eax,1 add eax,eax add eax,'+' mov dword ptr [edi+17],eax mov eax,dword ptr [lgNum] bswap eax movd xmm0,eax movaps xmm1,xmm0 psrlq xmm1,4 pand xmm0,_0F_0F_ pand xmm1,_0F_0F_ punpcklbw xmm1,xmm0 por xmm1,[_30_00_] movups [lgNum],xmm1 mov ebx,edi lea edi,lgNum mov eax,0x30 mov ecx,32 repe scasb mov esi,edi sub esi,1 add ecx,1 mov edi,ebx add edi,18 rep movsb End:
А может попробовать в целых числах? Через внутреннее бинарное представление числа? Разбить на мантиссу и коэффициент порядка...
SII Порядок и характеристику можно получить напрямую. А мантиссу можно считать побитно как степени двойки (суммировать до нужно точности в целых числах). В Вики есть пример перевода двоичного-float в десятичный-float. По нему вполне понятно как это сделать, ИМХО. http://ru.wikipedia.org/wiki/Систем....81.D1.8F.D1.82.D0.B8.D1.87.D0.BD.D1.83.D1.8E
10110111, а можно посмотреть как во 2-ом варианте определены данные? Код (Text): fild [_15_] 15 - в шестнадцатеричной или в десятичной системе ???
Да, ступил, не дав данные. Просто это был эксперимент на сях с асм вставками, и все XMM-данные были введены __emit'ами, вот и мне и было лень преобразовывать данные к читабельному виду. =) Код (Text): align 16 _30_30_: dd 4 dup(0x30303030) _30_00_: dd 2 dup(0x30303030) dd 2 dup(0) _0F_0F_: dd 4 dup(0x0f0f0f0f) _77F_: dd 0x77f _F7F_: dd 0xF7F _37f_: dd 0x37f _15_: dd 15 Цель эксперимента была - минимизировать ветвления. Если у кого-нибудь получится исключить имеющиеся, будет интересно посмотреть.
Во, придумал: Заменяем это Код (Text): jnc Plus mov [edi],'-' add edi,1 fabs Plus: add edi,1 на: Код (Text): mov [edi],'-' ; if this is unneeded (Number>0), it will be overwritten by first digit adс edi,0 ;if (!carry) add 0; else add 1; fabs ;if Number>0 this doesn't do anything add edi,1 и получаем код вообще почти без ветвлений =) ЗЫ: Правда, ещё стоит проверять на нечисла - после "Je Zero" надо "Jp NAN", но это уже особые случаи.
Кстати: вместо Код (Text): _77F_: dd 0x77f _F7F_: dd 0xF7F _37f_: dd 0x37f лучше Код (Text): _77F_: dw 0x77f _F7F_: dw 0xF7F _37f_: dw 0x37f
Лет 10 назад работал на Spectrum, проц z80 не умеет даже делить, а сопроцессор математики реализовался программным путём - разбирать это было интересно...
тока не забудь, что XMM будут работать тока при включенном бите в CR4. Я, когда запускал этот код под DOS, долго недоумевал, в чем причина зависаний.
10110111, а каким отладчиком Вы пользуетесь? Все, которые у меня есть, либо не показывают XMM регистры, либо показывают их в форме вещественного числа.