Самую (желательно) быструю процедуру,кто подскажет?
Вид для печати
Самую (желательно) быструю процедуру,кто подскажет?
Обговори условия (разрядность, набор используемых регистров, константность операндов, нужные компоненты результата- частное/остаток, и т.д.)
Какое деление/умножение, знаковое, без? Последовательное или одновременное?
Некоторые алгоритмы есть тут - http://www.piter.com/lib/97857190003...il=wgasm09#n01. Насчет оптимальности не знаю, но меня убила процедура SQR размером 28 байт.
2:vitoz80/svs/rgb Кое-что есть в недрах ПЗУ, в "Как написать игру на ассемблере для ZX..." (см. раздел литературы этого сайта) есть, как помнится, знаковые умножение и деление, беззнаковый корень, аргументы берут в регистровых парах HL, DE, рез-т в HL. Судя по не сильной понятности, но небольшому размеру - не самые плохие, но вряд ли САМЫЕ быстрые; так как тамошнее умножение берет 2 любых -32786 .. 32767 - это довольно универсальные процедуры. А самые быстрые обычно не универсальны, это 16 бит * на 8, или один аргумент - всего несколько вариантов, там например 10,100,1000. Поэтому уточни условия работы процедуры, какие-нибудь особенности (если есть), которые позволяют упрощать и убыстрять расчеты.
Ооп... извиняюсь, процедуры из вышеупомянутой книги -- это как раз те, которые указал Shwartz.
Offtop: O_O издательство "Питер" дает бесплатно читать некоторые книги?????
Vitamin, спасибо....
кстати вот ето че за команда (итог)?
slia h
я вот чет непомню такую,или ваще незнаю :)
в первом файле
Добавлено через 1 минуту
ладно,буду разбираться,бог мне в помощь......
Добавлено через 3 минуты
всем спасибо.....
Добавлено через 8 минут
еще вопрос?
по какому порту страницы переключать 128к
и какое значение на какую страницу
(если можно пример)
все забыл.....
"Note: SLIA stands for semi-documented instruction Shift Left Inverted Arithmetic (operation codes 30h..37h prefixed by CBh, DDh CBh or EDh CBh) also known as SLL (Shift Left Logical). It shifts register to the left and sets the less significant bit to 1."
Примечание: SLIA означает полудокументированную команду Сдвиг влево инвертированный арифметический (коды #30..#37 с приставками #CB, #DD #CB, #FD #CB) также известной как SLI(Сдвиг Влево Инвертированный). Она сдвигает регистр влево и устанавливает наименее значащий бит в 1.
Две опечатки неточности: EDh <- #FD ; SLL <- SLI - прим. перев.
Добавлено через 2 минуты
По управлению портов, в том числе и по вашему вопросу с подробной иллюстрацией и комментом, отлично есть в "ZX Spectrum и TR-DOS для пользователей и программистов". Добрая душа сравнительно недавно передала его на вышеупомянутый сайт, в раздел литературы. Сам вот только полгода назад научился работать со страницами по первым главам этой книги, потому и рекламирую ;)
Добавлено через 7 минут
Блин, там гдюк на гдюке.
Ту процедуру с SLIA почитал... ну не может рез-т в D получиться. Надо как минимум jr nc, $+4 вместо $+3!
Добавлено...
Причем во многих процедурах, или я совсем уже отупел к полуночи, плз :v2_cry: , проверьте меня...
правильней будет не "наименее значащий бит" - а младший (нулевой)...
Точно, а то у меня какой-то дословный перевод... :)
Искал алгоритм поразрядного деления, и случайно наткнулся на этот шедевр:
Может кто-то обьяснит, куда девалась проверка флага переноса после rla? Или я просто много хочу на ночь глядя? В процедуре деления, где делимое равно или меньше делителя, эта проверка не нужна, т.к. разрядность рабочего регистра остатка больше или равна числу сдвигов. В случае же, когда разрядность делителя меньше делимого, эта проверка требуется, иначе деление на число >= $80 приведет к глюку.Код:2.4 Classic 24-bit / 8-bit Unsigned
Input: HLD = Dividend, E = Divisor, A = 0
Output: HLD = Result, A = Remainder
slia d ; unroll 24 times
add hl,hl ; ...
rla ; ...
sub e ; ...
jr nc,$+3 ; ...
add a,e ; ...
dec d ; ...
В самом деле, возможен глюк при делении на число >$80 (не всегда). Значит ошибка в алгоритме. Надо же! А ведь я столько времени пользовался похожим алгоритмом, который тоже не проверяет перенос после сдвига рабочего регистра остатка.
Когда делитель >$80, а в рабочем регистре остатка хранится число >=$80, но меньше делителя, то пробное вычитание окажется неуспешным, а на следующем проходе цикла рабочий регистр остатка будет сдвинут влево, т.е. там образуется число >=$100. Однако 8-разрядный аккумулятор не может хранить такое число, и старший разряд попадет во флаг C.
В такой ситуации пробное вычитание должно обязательно быть успешным, т.к. $100>$FF (максимальное значение делителя). Однако поскольку старший разряд, находящийся во флаге C, данным алгоритмом не учитывается, то пробное вычитание снова окажется неуспешным. В результате в частное и в рабочий регистр остатка попадет неверная информация, делающая дальнейшую работу алгоритма ошибочной.
Еще одна ошибка приведенного алгоритма - это то, что нужно применять ADC HL,HL, а не ADD HL,HL.
---
Вот вариация без недокументированных команд и чуть быстрее (на одну команду в цикле):
Код:2.4 Classic 24-bit / 8-bit Unsigned
Input: HLD = Dividend, A = Divisor
Output: HLD = Result, A = Remainder
neg
ld e,a
xor a
rl d ; unroll 24 times
adс hl,hl ; ...
rla ; ...
add a,e ; ...
jr c,$+3 ; ...
sub e ; ...
Совершенно верно. Что самое интересное, в приведенном документе все алгоритмы деления, у которых разрядность делителя меньше делимого, будет данный глюк. Возможно, автор взял за основу самый первый алгоритм, где делитель равнялся делимому, и на основе него настругал более разрядные, но не подумал, что может быть переполнение регистра остатка.
Пусть меня навсегда забанят из этого форума, но вы #$%^*@е извращенцы, все кто тут отписался... в _плохом_ смысле слова...
Mat1sha, жжош:v2_lol:
Mat1sha, ты зачем в программирование лезешь?
Mat1sha, именно такие "извращенцы" и пишут красивые демы и игры :)
Блин, никак не получается 8-ю битами поделить большие числа (ну скажем #AD на #F0) чтоб с остатком как положено (должно быть #00B8)
Что за фигня
Своим совершенно непонятным постом Вы ввели читателей в полный ступор.
Во-первых, даже очень большие числа можно поделить всего 4-мя битами, что и делали калькуляторы, которые в начале 70-тых были именно 4-х разрядными, т.к они считали в двоично-десятичной арифметике, а для представления одного числа 4-х разрядов вполне достаточно (кстати именно из-за этого в Intel процессорах сохранился такой пережиток как десятичная коррекция DAA).
Во-вторых, вообще непонятно о чём тут речь. Если только кто-то не изобрёл новую форму представления чисел в 8-ми разрядном компьютере и речь об этом. До сих пор было известно только представление целых чисел и представление дробных чисел в форме плавающей запятой (с мантиссой и порядком).
Но у Вас указаны целые числа, а результат Вы, похоже, ожидаете от деления дробных чисел. Есть процессоры, что умеют делить числа с плавающей запятой, но Z80 это не может. Кстати, этот недостаток Z80 легко исправить подключив к ZX-Spectrum 8-ми разрядный сопроцессор AMD AM911-1.
Из Вашего текста следует, что остаток от деления 0ADH на 0F0H это 0B8H. Наберите в любом макроассемблере строку
RESULT EQU 0ADH mod 0F0H
и Вы убедитесь, что остаток равен 0ADH, что абсолютно ясно и без ассемблера.
Число 0B8H получится только, если использовать программу деления чисел представленных в виде чисел с плавающей запятой и это не остаток, а результат дробного деления, причём почему-то умноженный на 256 и конвертированный снова в HEX. А программа целочисленного деления должна давать 0, т.к это положительные числа и делимое меньше делителя.
Шынни, кто написал такой неправильный шестнадцатеричный калькулятор?
Шестнадцатеричные числа по определению целые. Потому выражение в скобках равно нулю и результат тоже д.быть 0. Если включён шестнадцатеричный режим калькулятора, то и считать надо по правилам шестнадцатеричной арифметики.
Шестнадцатеричная арифметика бывает беззнаковой, без ограничения размерности (так считает калькулятор Windows) и 16-ти разрядной знаковой, когда бит D15 это знак (именно так считает HEX-выражения макроассемблер Microsoft). А 8-ми битовая HEX-арифметика не бывает знаковой. Потому DA00/F000=2, а DA/F0=0.
Только не надо утверждать, что это якобы десятичный калькулятор, но допускающий ввод чисел в HEX-виде.
barsik, ты ошибку пишешь
делить надо так
#ad00/#f0
тогда будет #b8
иначе фигня
Я отвечаю именно на то, что написано.
С такими (совсем другими) входными данными и проблемы нет, т.к нужный результат даст любая процедура деления, в том числе и тривиальная с вычитанием в цикле.
А действительно, чтоб не мучиться с программными арифметическими и даже тригонометрическими вычислениями, полезно поиметь арифметический сопроцессор http://www.cpushack.com/2010/09/23/a...-then-and-now/
barsik, Ожидаю 8bit/8bit=8bit.8bit
#AD/#F0=#00B8
Конечно решается и 16bit/8bit (как жерри написал) но хочется 8 циклов заворачивать на целую и 8 на дробную части, а не 16
То же самое как раз и получится, если делимое умножить на 256 (или сдвинуть влево на 8 разрядов) и затем выполнить деление 16-ти разрядного числа на 8-ми разрядное. Но непонятно для чего нужна дробь не десятичная, а в 256-тых долях.
Мне как-то нужны были десятые и сотые, причём в десятичном виде и, если МНИП, я делал так. Делил нацело, получал целую часть, а затем делил остаток и получал дробную часть.
Я так и понял, что Вам сказать нечего.
Вот тут прога http://zx-pk.ru/threads/9031-etyudy/page71.html (пост #710, наверное надо сюда перенести, модер или кто там если можно плиз, всё что на тему - сюда)
Она и делает 8/8=8.8
Но только с беззнаковыми (и меньше 127) числами.
Работает, но научить делить больше 127 (рассматривая как беззнаковые) не получается что-то, (как-то надо заюзать флаг C в качестве доп.разряда, но я не придумал как это сделать компактно)
Если Вы написали этот калькулятор, это вовсе не значит, что он правильный. А вот калькулятор Windows правильный и все сотни макрассемблеров, в которых вычисляются HEX-выражения тоже правильные.
Я ещё меньше желаю с Вами разговаривать, потому что давно заметил, что "Вы самый умный на форуме" и неспособны к нормальному общению. Сожалею, что откомментировал вашу вопиюще бредовую картинку HEX-калькулятора. Закончили.
Ссылки нет. Или тему укажите.
Виноват, по копипасту промахнулся. Поправил сообщение (если что и тут шлёпну на всяк случай :-) http://zx-pk.ru/threads/9031-etyudy/page71.html)
- - - Добавлено - - -
Точно, делим 173 (#ad) на 240 (#f0) получаем 0,7208333....
Что если умножить на 256 будет #b8 (т.е как раз нужное 0.7 от #100, дробная часть)
блин какой ты нудный чтоли
есть 8bit/8bit = 8bit.8bit
т.е по факту результат всегда занимает больше чем исходные данные
а может еще и видеокарту с 512 мб памяти к спеку прикрутить?Цитата:
А действительно, чтоб не мучиться с программными арифметическими и даже тригонометрическими вычислениями, полезно поиметь арифметический сопроцессор http://www.cpushack.com/2010/09/23/a...-then-and-now/
- - - Добавлено - - -
lol, Destr, а у тебя что получается?
у тебя результат весит 16бит как ты его хочешь получить в 8 итераций?
потому и приходится расширять 8битное число до 16битного чтобы результат получил нормальный вид.
jerri, Так я ведь привёл ссыль на прогу которая всё делает как надо, но пока делимое и делитель не больше 127
Из 2 восмибитных регистров получается 16 битная пара где целая и дробная части по 8 бит (именно дробная, не остаток)
А вот как её переделать чтоб правильно делила любые 8-ми битные значения (с условием что они не знаковые, т.е. #F0 это именно 240 а не -16) - вот не получается. Думал поможете, а меня тут дебилом выставляют и 3dfx всякие советуют...
Про итерации: их 2 по 8. Делать 2 по 16 это уже не тру. А если 1 по 16 то можно получить либо целую часть, либо дробную, так вроде
Я честно говоря думал так и надо, типа сначала берется модуль потом делится. Но если в этом трудности то убери в RL H,H один H и первый dup 7 на 8 исправь. Будет деление 8/8=8.8
ты кота не слушай
ты кота делай
если прога делает все как надо то ты ее и используй
а то у тебя неправильный взгляд на вещи
ты когда делишь #ad/#f0 и получаешь 0.
то ты все делаешь правильно.
просто смотришь не так
поскольку тебе надо делить целое число 8.8
и ты его расширяешь #ad.00/f0
ну а насчет проги. я хз. они все работают по одному принципу
:v2_dizzy_facepalm:
Нет Гейца кроме Гейца, и barsik пророк его! Убить огнём всех еретикалькулирующих!! :v2_dizzy_fire: :v2_dizzy_fire: :v2_dizzy_fire:
Цитата:
По легенде, сжигая Александрийскую библиотеку, халиф Умар руководствовался следующей логикой: "если написанное в этих книгах противоречит Корану, то они обязательно должны быть сожжены, так как это - богохульство. Если же они повторяют то, что написано в Коране, они опять же должны быть сожжены. Потому что если они уже есть в Коране, какая в них нужда?"
krt17, В том и беда что не выходит
Старик, уж от тебя не ожидал. По твоей логике вышеприведёная прога при 3/10 (например) должна получать тоже нуль, а она как путняя даёт результат 0.3 (в H будет #00 - целая часть, в L будет #4C - дробная часть, т.е ровно 0.3 от 256. Теперь если прибавить это число к например координате которая двубайтна (тоже целая и дробная части) получим смещение по ней на три десятых. Шлёпая такое приращение раз во фрейм и беря для печати старшую часть координаты можно получить плавное движение по 0.3 пикселя за фрейм (на глаз это так и будет выглядеть, фрейм ведь), ты вроде все эти вещи сам прекрасно знаешь).
Всё это деление и мучаю для кота (до этого юзал таблицу, аж в 512 байт, но решил что так не тру, да и для других дел с деленим нужно разобратся)
- - - Добавлено - - -
barsik, Троллишь что-ли? Или реально не разбираешься в вопросе?
Я хоть не математик, но фейспалмы которые ты тут собрал сам-бы пополнил, но пока держусь.
Для справки - любое кол-во битов (хоть 16, хоть 8, хоть 5) как слово в предложении - зависит от контекста. Т.е. можно рассматривать как целое число, или как знаковое. А ещё это может быть и float. Или вообще код символа. Или команда. Так что "Шестнадцатеричные числа по определению целые" справедливо только для ОБЩЕГО случая (т.е ты увидел #de23 и смело говоришь - это 56867. Всё. Дальнейшее зависит от того что конкретно делает в проге это значение)