· Начало · Отвђтить · Статистика · Поиск · FAQ · Правила · Установки · Язык · Выход · WASM.RU · Noir.Ru ·

 WASM Phorum —› WASM.ASSEMBLER —› ASCII to FLOAT

<< . 1 . 2 . 3 . >>

Посл.отвђт Сообщенiе


Дата: Мар 30, 2004 20:59:15

Asterix
Тренеруйся, тренеруйся :)
Я толдычу уже несколько лет: книжки должны учить на 95 процентов как создавать мат. модели и писать алгоритмы и только на 5% давать описания прерываний и прочее.
Это алгоритм для первоклассника.
Что ты 5 минут посидел и всё что ли?
Тренеруйся.
Имей ввиду - операнд терабайт. Т.е. если даже в строке у тебя нет стольки разрядов - старшие, оставшиеся заполнить нулями (если у тебя безнаковые)
А то ишь! Свели всё программирование к поиску по Гуглам и описанию чужих функций :) Арбайтен :))


Дата: Мар 30, 2004 21:15:23 · Поправил: Asterix

[ The Svin: Имей ввиду - операнд терабайт. Т.е. если даже в строке у тебя нет стольки разрядов - старшие, оставшиеся заполнить нулями (если у тебя безнаковые)]

Нужно просто заранее обнулить переменную чтоб не добивать потом нулями.

Кажется нужно так, но сколько же кода это всё потребовало, мне кажется что мой первоначальный вариант гораздо проще ;-)
     invoke lstrlen, OFFSET szSrc
     lea esi, [szSrc+eax-1]
     push eax
     shr eax, 1
     sbb eax, eax
     test eax, eax
     pop eax
     jz @F
     inc eax
@@:
     shr eax, 1
     mov edx, eax
     lea edi, sDest
     push edi
     xor eax, eax
     mov ecx, 5
     cld
     rep stosw
     xor ebx, ebx
     adc ecx, 2
     pop edi
     std
@@:
     lodsb
     shl ebx, 8
     xor eax, 030h
     or ebx, eax
     loop @B
     xchg eax, ebx     
     xchg ah, al
     aad_16
     mov BYTE PTR [edi], al
     xor ebx, ebx
     xor eax, eax
     adc ecx, 2
     inc edi
     dec edx
     jnz @B
@@:
    fbld sDest


Поправил.. Еще немного соптимизировал :-)


Дата: Мар 30, 2004 23:22:56

Asterix
Загляни на вторую страницу раздела посвященного алгоритмам, там есть темы Int_to_Str и Str_to_Int. fbld инструкция доволно тормозная(у меня 80 тактов выполняется). Думаю лучше перевести в Int, а потом fild использовать.


Дата: Мар 31, 2004 00:16:42

Black_mirror до квинтиллионов что ли?


Дата: Мар 31, 2004 00:44:29 · Поправил: Asterix

.


Дата: Мар 31, 2004 08:53:11

Здравый смысл подсказывает, что десятичное представление
чисел нужно лишь при взаимодействии с человеком.
Поскольку большинство людей неспособны генерировать\воспринимать
десятичные числа со скоростью мегабайтов в секунду, то перевод
это не та операция, которую нужно оптимизировать по скорости.
А раз так, то ее нужно оптимизировать по размеру - использовать BCD.

isn't it ?


Дата: Мар 31, 2004 10:48:55

> Здравый смысл подсказывает, что десятичное представление
чисел нужно лишь при взаимодействии с человеком.


В данном случае как раз нет ;-)


Дата: Мар 31, 2004 13:07:10

Ещё пока вообще никто ни показал ни доказал, что тут будет быстрее. Никаких сравнений я не видел. fbld медленная но при использовании её вообще отпадает надобность что то умножать и прибавлять. Поскольку знаковый QWORD может быть использован с fbld до 18и знаков в десятичной, получается что исползование fbld избавляет от до 18(m+a) где m и a такты синхронизации на умножение и сложение + контрольные такты. Кроме того одним простым циклом 64итное число не преобразовать, нужно будет делить на разрядные фракции, делать раздельное преобразование, один из результатов её раз умножать и потом складывать.

Но при fbld возникает необходимость в преобразовании в BCD террабайт. Это преобразование можно делать очень по разному и есть возможность сделать довольно быстро.

Пока же не доказательств математических ни тестов эмпирических тут не было приведено. Так, что рановато приклеивать тут ярлычки на тему "что быстрее".

Лучше давайте-ка потренеруемся раскладывать задачку на составляющие и находить модельки решения.

Одна задачка: как быстро перевести террабайт BCD ASCIIZ строку представляющую символьную запись десятичного числа.

Другая задачка - такую же строку (содержащую <= 18 символов) перевести в QWORD.

Asterix, молодец что пытаешься.


Дата: Мар 31, 2004 15:27:54 · Поправил: Asterix

Тут будет ещё проще, только я не понял fbstp оно не учитывает дробную часть
     fbstp sSrc
     lea esi, sSrc
     lea edi, [sBuffer+18]
     mov ecx, 9
     cld
@@:
     lodsb
     aam_16
     xchg ah, al
     or ax, 03030h
     dec edi
     dec edi
     mov WORD PTR [edi], ax
     loop @B
     mov ecx, 18
     mov al, '0'
     repe scasb
     dec edi


Дата: Мар 31, 2004 17:19:15

Я имел ввиду перевод ASCIIZ десятичной строки в QWORD а не BCD в ASCIIZ строку.
Повторюсь ещё раз. Предложено две альтернативы
1. Целочисленно перевести ASCIIZ в QWORD и сделать fild
fstp
2. Перевести ASCIIZ в BCD и сделать fbld fstp.
Главная нагрузка соответсвенно в первой части ложится на код преобразующий до 18и разрядов десятичную строку в QWORD, а во втором случае конвертирование в BCD.

То что ты написал (в последнем посте), это конвертирование из BCD в ASCIIZ.
А вот что никто пока не предложил (кроме твоего самого первого варианта с использыванием FPU) так это перевода из
ASCIIZ (до квинтиллионов) в QWORD.
Black_mirror утверждает, что так будет быстрее.
Однако никто ещё не показал насколько быстрее будет перевести строку содержащую до 18и символов в 64х разрядное целое. (С использование FPU это стопудово будет медленнее, достаточно умножить длительности (fimul mem + fiadd mem) на 18 чтобы понять это).


Дата: Мар 31, 2004 20:25:35

The Svin
stof1:;(str +4)
	mov esi,[esp+4]
	xor edi,edi
	xor ecx,ecx
	xor eax,eax
    .loop:
	add ecx,ecx
	adc edi,edi
	mov ebx,ecx
	add ecx,ecx
	mov edx,edi
	adc edi,edi
	add ecx,ecx
	adc edi,edi
	add ecx,ebx
	adc edi,edx
	lodsb
	sub al,'0'
	add ecx,eax
	adc edi,0
	cmp al,9
	jbe .loop
	push edi
	push ecx
	fild qword [esp]
	add esp,8
	ret 4

stof2:;(str +4)
	mov esi,[esp+4]
	fld [.ten]
	fldz
	xor eax,eax
	push eax
    .loop:
	fmul st0,st1
	fiadd dword [esp]
    .load:
	lodsb
	sub al,'0'
	cmp al,9
	mov [esp],eax
	jbe .loop
	fstp st1
	add esp,4
	ret 4
    .ten dd 10.0


Для процессора AthXP1900+(частота системной шины 133, память DDR333, частота процессора 1600), при переводе 18-значного числа, получены следующие результаты:
stof1 - выполняется 182 такта(вместе с вызовом функции)
stof2 - выполняется 191 такт
(первоначальный вариант stof1 с двумя целочисленными умножениями в цикле выполнялся 200 тактов)
Код Asterix'а с fbld(с этой страницы) у меня выполняется где-то 450 тактов(виду отсутствия, lstrlen был заменен на mov eax,18). А самый первый вариант(без fbld) - 241 такт.


Дата: Мар 31, 2004 21:26:49 · Поправил: Asterix

Black_mirror

Спасибо за код и выкладки.
А что можешь сказать по поводу обратной операции(float2string),
что здесь лучше использовать?

Зы: не такой уж медленный, оказывается, мой первый вариант ;-)


Дата: Мар 31, 2004 23:24:06

Код появился, хорошо, это радует :)
Только почему то без комметариев. Почему у нас по поводу всякой политики MS всегда килограмм слов а на объяснение арифметики мы их жалеем?

Black_mirror
Обрати внимание на это кусок в первой процедуре:
0.	lodsb
1.	sub al,'0'
2.	add ecx,eax
3.	adc edi,0
4.	cmp al,9
5.	jbe .loop

6.	push edi
7.	push ecx

	fild qword [esp]

lodsb на шаге 0 загружает очередной символ строки.
А проверяется не является ли он нулём лишь на 5ом.
При этом если это последний символ (0) то
а) на шаге 1 из него сделают D0
б) на шагах 2 и 3 D0 благополучно прибавится к 64 битному числу
в) и на шаге 6, 7 это число больше нужного на D0 благополучно передаётся на загрузку.
Так, что условия выхода я бы поменял. Либо нужно загрузить
-D0h в есx edi начально.
Кроме того получается лишняя итерация.
Кроме того заменил бы lodsb на mov al,[esi] add esi,1
если речь идёт о скорости.
Результат с fbld медленный по простой причине, мы пока не видим качественного перевода в BCD.

По поводу первой процедуры есть простое замечание:
Используем тот факт, что если в al у нас символ строки, то
зная что она определена на множестве [30h,31h...39h,0]
при вычитании из него 30h CF установится только в том случае,
если это 0. Таким образом переводя символ в бинарное значение
очередного десятичного разряда мы можем одновременно и определить
не является ли это концом строки.
Из этого следует что преобразование должно быть в конце (последней командой
перед управляющей) а прибавление уже в следующей итерации.


Дата: Мар 31, 2004 23:49:02

Что-то я не пойму, что с точностью, протестил
разные варианты и получил такие результаты:

Исходная строка - "31029294951234567"
3.1029294951234585600e+17 by Black_mirror вариант 1

3.1029294951234565120e+16 <-первый вариант (aaa заменил на and eax, 00000000Fh)
3.1029294951234565120e+16 <-BCD


Дата: Мар 31, 2004 23:58:20 · Поправил: Black_mirror

The Svin
Баг исправил, и это сэкономило еще 6 тактов:
stoi64:;(str +4)
	mov esi,[esp+4]
	xor edi,edi
	xor ecx,ecx
	xor eax,eax
    .loop:
	add ecx,ecx
	adc edi,edi
	mov ebx,ecx
	add ecx,ecx
	mov edx,edi
	adc edi,edi
	add ecx,ecx
	adc edi,edi
	add ecx,ebx
	adc edi,edx

	add ecx,eax
	adc edi,0
	mov al,[esi]
	sub al,'0'
	inc esi
	cmp al,9;проверяется цифра это или нет
	jbe .loop;поэтому здесь такой переход

	push edi
	push ecx
	fild qword [esp]
	add esp,8
	ret 4

<< . 1 . 2 . 3 . >>


Powered by miniBB 1.6 © 2001-2002
Время загрузки страницы (сек.): 0.088