p.s. В любом случае -- это прямой перенос на asm алгоритма, сделанного под C. Который делалася так, чтобы продемонстрировать идею РПП и получить разумно-быструю функцию для любой архитектуры без необходимости что-то дотачивать (это всё поначалу вообще на AT89C55 гонялось). На асме можно и по-другому сделать, посмотрите тему в RU.ALGORITHMS -- с чего тема началась. Там «цифра за цифрой», что не очень уобно реализуется на C, но на асме, мне кажется, может позволить частично объединить регистры (как при делении, когда две переменные сдвигаются вместе и частное вдвигается на место делимого). Кажется, именно такой алгоритм на асме для AVR где-то вте же годы написал Александр Труш, только там из 3-байтового числа корень извлекался.
_________________ Лень в виде мании величия: «ты гений, зачем стараться?». В виде комплекса: «всё равно не выйдет, зачем упираться?». Как логика: «если достаточно, зачем знать и уметь больше?». Цель одна: остановить. Не любит тепло работающих мышц и шум работающего мозга.
Сейчас скомпилил в avr-gcc указанный С-шный исходник, так тело цикла 1:1 тому, что я дал выше (начиная от метки loop и заканичая сдвигом mask на два), а вот с организацией цикла он прави не прав одновремённо. У AVR-то регистров немеряно. Конец цикла он проверяет не по 0 в mask, а тупо по счётчику, так как при данном начальном значении mask и сдвигах на 2 тело цикла будт пройдено 16 раз (кстати, в дів раза меньше, чем при делении 32/32, так что способ извлечения корня y = (x + y/x) / 2, требующий нескольких делений, явно отстаёт). Но он почемуто решил, что счётчик нужно сделать двухбайтовым. Так что можно ещё так изменить
Код:
... инициализация ldi counter, 16 ; <----------
loop: movw ... ... skip: ... rol mask3 ; конец сдвига маски
dec counter ; <---------- brne loop
Ещё тройка тактов в цикле экономится, на всём корне при 16МГц тактовой ещё микросекунды три выиграется. С учётом всех изменений микросекунд в 40 в наихудшем случае влезет. В среднем, думаю, 35. И именно из этого уже ничего не выжать. Надо смтреть в сторону «цифра за цифрой» (бит за битом), читайте Винокурова в той теме.
_________________ Лень в виде мании величия: «ты гений, зачем стараться?». В виде комплекса: «всё равно не выйдет, зачем упираться?». Как логика: «если достаточно, зачем знать и уметь больше?». Цель одна: остановить. Не любит тепло работающих мышц и шум работающего мозга.
Заголовок сообщения: Re: квадратный корень на асме AVR
Добавлено: Вс апр 03, 2011 09:10:30
Жалко столько регистров использовать )). У меня ж они не только для расчёта используются. Ща проверим быстродействие. И всё таки какой древний алгоритм, а раз выжил - значит хороший.
Заголовок сообщения: Re: квадратный корень на асме AVR
Добавлено: Вс апр 03, 2011 09:45:23
Программа была переделана по вашим рекомендациям. Скорость расчёта улучшилась с 65 до 35 мкс. Вот конечная версия. На этом можно остановиться, я думаю. Всем большое спасибо.
Ну так если регистры очень нужны где-то ещё, то всё равно будет по скорости лучше и по объёму кода не хуже в начале четыре регистра push-нуть, задействовать их для вычислений, потом назад pop-нуть.
Вот глянул первоначальный вариант - там sqr инициализируетя нулями (4*sts = 16байт, но половина из них уйдёт и на инициализацию регистров) потом в цикле дважды считывается (8*lds = 32 байта) и один раз сохраняется (4*sts = 16 байт). По об́ъёму кода это во много раз больше, чем 4*push+4*pop (16байт). Ну а по скорости так само собой. Доп расхода памяи на стек нет, на это уйдёт та память, которая была нужна для временной переменной sqr, причём в другое время этот стек будет для чего-то другого использован.
_________________ Лень в виде мании величия: «ты гений, зачем стараться?». В виде комплекса: «всё равно не выйдет, зачем упираться?». Как логика: «если достаточно, зачем знать и уметь больше?». Цель одна: остановить. Не любит тепло работающих мышц и шум работающего мозга.
_________________ Лень в виде мании величия: «ты гений, зачем стараться?». В виде комплекса: «всё равно не выйдет, зачем упираться?». Как логика: «если достаточно, зачем знать и уметь больше?». Цель одна: остановить. Не любит тепло работающих мышц и шум работающего мозга.
Число с нечётным числом бит всегда можно превратить в число с чётным их числом, добавив слева нулевой бит
В маске поднят младший бит из самой старшей пары бит. Для 10-битного числа маска будет 0x100 33-битное число рассматривайте как 34-битное, маска будет 0x100000000ULL
p.s. Маска представляет собой квадрат числа с единственной единичкой. Начальная маска -- квадрат числа с единичкой в старшем разряде (максимального) ожидаемого корня. Так и получается, что маска прыгает через два бита и всегда в младшем бите из пары. 0x8000 (старшая единичка в 16-битном числе результата) в квадрате давало маску 0x40000000. Если описания по ссылкам почитать, это должно быть ясно.
_________________ Лень в виде мании величия: «ты гений, зачем стараться?». В виде комплекса: «всё равно не выйдет, зачем упираться?». Как логика: «если достаточно, зачем знать и уметь больше?». Цель одна: остановить. Не любит тепло работающих мышц и шум работающего мозга.
Народ хелп!! При числе 2С52С0000 и больше выдаёт какую-то хрень((
Алгоритм работает нормально, если какая-то программа выдаёт хрень -- надо искать в ней ошибку. Раз число вылезло за 32 бита, нужно подправить типы и маску.
Вот делаем маску изначально меньше и ограничиваем маской диапазон входных чисел в 34 бита, куда влезет 2C52C0000 (макс. значение 34-битного входа 3 FFFF FFFF, а с учётом округления алгоритм будет выдавать правильные ответы до 4 0002 0000, но это ему просто повезёт по причине реально 64-битных вычислений):
В последней строке ответ неправильный, но тут уже не выдержан диапазон аргумента, а алгоритм ни при чём.
_________________ Лень в виде мании величия: «ты гений, зачем стараться?». В виде комплекса: «всё равно не выйдет, зачем упираться?». Как логика: «если достаточно, зачем знать и уметь больше?». Цель одна: остановить. Не любит тепло работающих мышц и шум работающего мозга.
Это плохо. То, что непонятно как само заработало, с тем же успехо само и перестанет. Кто в доме хозяин?
_________________ Лень в виде мании величия: «ты гений, зачем стараться?». В виде комплекса: «всё равно не выйдет, зачем упираться?». Как логика: «если достаточно, зачем знать и уметь больше?». Цель одна: остановить. Не любит тепло работающих мышц и шум работающего мозга.
Это и плохо, что забыл Грабли нужно помнить. В следующий раз при редактировании может нечаянно назад поменяться. Впрочем, тогда и память может освежиться.
_________________ Лень в виде мании величия: «ты гений, зачем стараться?». В виде комплекса: «всё равно не выйдет, зачем упираться?». Как логика: «если достаточно, зачем знать и уметь больше?». Цель одна: остановить. Не любит тепло работающих мышц и шум работающего мозга.
Вы не можете начинать темы Вы не можете отвечать на сообщения Вы не можете редактировать свои сообщения Вы не можете удалять свои сообщения Вы не можете добавлять вложения