Вход

Просмотр полной версии : Арифметические процедуры на ассемблере



spensor
30.11.2006, 14:46
Не подскажет ли многоуважаемый All где можно найти информацию по программированию арифметических процедур на ассемблере? Желателен линк на сайт или книгу. В свое время в спектрумовских E-zine часто публиковались процедуры быстрого умножения/деления, перемножения матриц и тому подобного. А интересуют процедуры и попроще, например знаковое сложение/вычитание. В общем подскажите где подобное можно найти. В принципе даже неважно под Z80 или под что-то другое.

Sinus
30.11.2006, 15:34
http://www.google.com/search?hl=en&safe=off&sa=X&oi=spell&resnum=0&ct=result&cd=1&q=z80+arithmetic+operations&spell=1
--> http://map.tni.nl/sources/external/z80bits.html

ещё много есть док про Техасс Инструментс (калькулятор такой был на z80).
в них очень много чего есть.

и ещё можешь посмотреть в каком-нибудь опенсорсовом компилере C который может генерить код под z80 посмотреть математическую либу (в соседней ветке как раз компилеры обсуждаются)

axor
30.11.2006, 15:35
Не подскажет ли многоуважаемый All где можно найти информацию по программированию арифметических процедур на ассемблере? Желателен линк на сайт или книгу. В свое время в спектрумовских E-zine часто публиковались процедуры быстрого умножения/деления, перемножения матриц и тому подобного. А интересуют процедуры и попроще, например знаковое сложение/вычитание. В общем подскажите где подобное можно найти. В принципе даже неважно под Z80 или под что-то другое.
Ссылок на теорию нет. Есть практика. Позаимствовано у Алко. Он в свою очередь тоже у кого-то взял, может чего и своего добавил.

psb
30.11.2006, 15:35
например знаковое сложение/вычитание.
оно выполняется точно так же как и обычное, главное пределы соблюсти, чтоб неперолнения не возникало. т.е. обычным add и sub.

elf/2
30.11.2006, 15:49
где можно найти информацию по программированию арифметических процедур на ассемблере? Желателен линк на сайт или книгу
http://baze.au.com/misc/z80bits.html
автор: Milos "baze" Bazelides

содержание:

1 Integer Multiplication
* 1.1 Restoring 8-bit * 8-bit Unsigned
* 1.2 Restoring 16-bit * 8-bit Unsigned
* 1.3 Restoring 16-bit * 16-bit Unsigned
* 1.4 Square Table Driven 8-bit * 8-bit Signed
* 1.5 Square Table Driven 6-bit * 6-bit Signed
* 1.6 Logarithmic Table Driven 8-bit * 8-bit Signed
2 Integer Division
* 2.1 Restoring 8-bit / 8-bit Unsigned
* 2.2 Restoring 16-bit / 8-bit Unsigned
* 2.3 Restoring 16-bit / 16-bit Unsigned
* 2.4 Restoring 24-bit / 8-bit Unsigned
* 2.5 Restoring 24-bit / 16-bit Unsigned
* 2.6 Restoring 32-bit / 8-bit Unsigned
3 Integer Square Root
* 3.1 Basic 8-bit Square Root
* 3.2 Basic 16-bit Square Root
* 3.3 Restoring 16-bit Square Root
* 3.4 16-bit Square Table Bisection
4 Random Number Generators
* 4.1 8-bit Random Number Generator
* 4.2 16-bit Random Number Generator
5 Conversions Between Numbers and Strings
* 5.1 16-bit Integer to ASCII (decimal)
* 5.2 16-bit Integer to ASCII (hexadecimal)
* 5.3 Memory dump (hexadecimal)
6 Cyclic Redundancy Checks (CRC)
* 6.1 16-bit CRC-CCITT
* 6.2 Table Driven 16-bit CRC-CCITT
* 6.3 32-bit CRC-32
* 6.4 Table Driven 32-bit CRC-32

elfh
02.12.2006, 03:33
Ссылок на теорию нет. Есть практика. Позаимствовано у Алко. Он в свою очередь тоже у кого-то взял, может чего и своего добавил.

Прикольно, math_lib - это мой файл ;). Но процедуры почти все не я писал. И пользовался не всеми.

Знахарь
02.12.2006, 17:32
Вот! значит массы оценили и велосипед не изобретали - остается пользовать

Дмитрий2012
11.05.2017, 20:22
Понадобились процедуры деления и умножения трехбайтовых чисел. На просторах инета нашел необходимые процедуры деления и умножения в журнале ZX FORMAT 7.Попробовал процедуру деления. Она к сожалению она почему-то оказалась не рабочей. С умножением еще не разбирался. В примере делю число 254639H на 00E489H получаем в аккумуляторе 29H а в HL 0C0FCH. Судя по комментариям в коде результат деления должен быть в регистрах A,H,L т.е в A -0 , в HL должно быть 0029H. Может кто посмотрит код и подскажет где ошибка закралась? или поделится готовыми библиотеками деления, умножения трехбайтовых чисел?

AlexG
11.05.2017, 22:25
Понадобились процедуры деления и умножения трехбайтовых чисел. На просторах инета нашел необходимые процедуры деления и умножения в журнале ZX FORMAT 7.Попробовал процедуру деления. Она к сожалению она почему-то оказалась не рабочей. С умножением еще не разбирался. В примере делю число 254639H на 00E489H получаем в аккумуляторе 29H а в HL 0C0FCH. Судя по комментариям в коде результат деления должен быть в регистрах A,H,L т.е в A -0 , в HL должно быть 0029H. Может кто посмотрит код и подскажет где ошибка закралась? или поделится готовыми библиотеками деления, умножения трехбайтовых чисел?
Может баян:
"Гуртовцев А.Л... Программы для микропроцессоров. [Djv- 2.3M] Справочное пособие. Авторы: Аркадий Лазаревич Гуртовцев, Сергей Викторович Гудыменко.
(Минск: Вышэйшая школа, 1989)
Скан, обработка, формат Djv: Boroda3, 2006"

КРАТКОЕ ОГЛАВЛЕНИЕ:
Предисловие (3).
Условные сокращения (6).
Методологические замечания (8).
1. Программы арифметики с фиксированной запятой (12).
2. Программы арифметики с плавающей запятой (105).
3. Программы преобразования представлений чисел (145).
4. Программы вычисления элементарных функций (176).
5. Программы обработки структур данных (211).
6. Программы системного обеспечения (245).
http://publ.lib.ru/ARCHIVES/G/GURTOVCEV_Arkadiy_Lazarevich/_Gurtovcev_A.L..html
http://publ.lib.ru/ARCHIVES/G/GURTOVCEV_Arkadiy_Lazarevich/Gurtovcev_A.L..._Programmy_dlya_mikroprocessorov.( 1989).[djv-fax].zip

drbars
12.05.2017, 09:09
Дмитрий2012, ты хоть подробно напиши что на что делить... 24bit/16bit или 24bit/8 ?



2.4 Restoring 24-bit / 8-bit Unsigned

Input: E:HL = Dividend, D = Divisor, A = 0
Output: E:HL = Quotient, A = Remainder

add hl,hl ; unroll 24 times
rl e ; ...
rla ; ...
cp d ; ...
jr c,$+4 ; ...
sub d ; ...
inc l ; ...

2.5 Restoring 24-bit / 16-bit Unsigned

Input: A:BC = Dividend, DE = Divisor, HL = 0
Output: A:BC = Quotient, HL = Remainder

slia c ; unroll 24 times
rl b ; ...
rla ; ...
adc hl,hl ; ...
sbc hl,de ; ...
jr nc,$+4 ; ...
add hl,de ; ...
dec c ; ...

Дмитрий2012
12.05.2017, 17:03
Может баян:
"Гуртовцев А.Л... Программы для микропроцессоров. [Djv- 2.3M] Справочное пособие.

Спасибо за ссылку на интересную книжку,не попадалась мне еще такая.


Дмитрий2012, ты хоть подробно напиши что на что делить... 24bit/16bit или 24bit/8 ?
В идеале нужна функция деления 32bit/24bit В данный момент меня устроила бы и 24bit /24bit
Задача состоит в том, чтобы данные 32bit переменной в которой тикает время в миллисекундах перевести в часы - минуты – секунды - милисек.
думаю делать так:

час = милисек div 3600000
мин = (милисек mod 3600000) div 60000
сек = (милисек mod 60000) div 1000
милисек = милисек mod 1000

сразу же застрял на делении многобайтных чисел:( сам такую процедуру пока не осилю написать, вот и ищу готовую. Что попадаются в инете и журналах не работают. Толи опечатки там есть, то ли я что не так делаю...

blackmirror
12.05.2017, 17:26
Дмитрий2012, на первом шаге можно вычислять (ms/128)/(3600000/128), тогда делить более чем на 16 разрядные числа не придётся. А это время больше нигде не нужно, то может его лучше хранить и увеличивать по компонентам.

shurik-ua
12.05.2017, 17:27
а ассемблер для какого процессора ?

Дмитрий2012
12.05.2017, 17:32
Дмитрий2012, на первом шаге можно вычислять (ms/128)/(3600000/128), тогда делить более чем на 16 разрядные числа не придётся. А это время больше нигде не нужно, то может его лучше хранить и увеличивать по компонентам.
я об этом даже не подумал, спасибо за подсказку. Если ничего с делением 32 битных чисел не выйдет попробую такой вариант.

Ну а на будущее хотелось бы все-равно иметь процедуры деления 32bit чисел.


а ассемблер для какого процессора ?
для Z80

NEO SPECTRUMAN
12.05.2017, 17:44
В идеале нужна функция деления 32bit/24bit В данный момент меня устроила бы и 24bit /24bit
Задача состоит в том, чтобы данные 32bit переменной в которой тикает время в миллисекундах перевести в часы - минуты – секунды - милисек.
можно без деления
4 таблицы по 1.5К (может даже меньше тк младшие 2 байта не могут указывать количество часов)
для каждого байта 32 битного числа
в которых лежит декодированое значения часов минут секунд
(2 байта часы, 1 байт минуты, 1 байт секунды, 2 байта миллисекунды)

потом складываем полученные 4 значения с учетом переполнений
и фсе

возможно будет быстрее даже

char
12.05.2017, 20:54
милисек = [32bit] / 1000
/1000 = /8/125
/8 это 3 сдвига вправо и тогда 24 часа входят в [24bit]

итого, нужна процедура деления [24bit] на 125 или 3 деления подряд на 5

получить секунды, это дальше делить на 60, это 2 сдвига и процедура деления на 15 [или на 5, а потом на 3]

минуты - аналогично

в остатке - часы

кактотак? :)

- - - Добавлено - - -

еще как вариант, сдвинуть вначале = /8, получив [24bit]

и далее только вычитанием

-450000 до переполнения = часы
-7500 до переполнения = минуты
-125 до переполнения = секунды
остаток = миллисекунды (деленные на 8)

NEO SPECTRUMAN
12.05.2017, 23:29
4 таблицы по 1.5К (может даже меньше тк младшие 2 байта не могут указывать количество часов)
для каждого байта 32 битного числа

точнее
000000FF = 0-255мс (1 таблица 256 байт)
0000FF00 = 0-999мс (2 таблицы) 0-59с (1 таблица) 0-1мин (1 таблица или сравнение)
00FF0000 = 0-999мс (2 таблицы) 0-59с (1 таблица) 0-59мин (1 таблица) 0-4час (1 таблица или сравнение)
FF000000 = 0-999мс (2 таблицы) 0-59с (1 таблица) 0-59мин (1 таблица) 0-1188 часов (2 таблицы)

итого
16 таблиц по 256 байт
4К таблиц

или
14 таблиц по 256 байт
3.5К таблиц

если не нужны миллисекунды то можно выкинуть 1.75К

Дмитрий2012
13.05.2017, 12:28
Спасибо всем за предложенные алгоритмы, возьму на заметку.
Остановился пока на варианте, который реально могу реализовать сам с моим уровнем знания ассемблера, использующем алгоритм с процедурой деления Unsigned 24 / 16

Time – время в миллисекундах
ms=(time mod 1000)
time1=(time div 1000)
sec=(time1 mod 60)
time2=(time1 div 60)
min=(time2 mod 60)
time3=(time2 div 60)
hour=(time3 mod 24)

blackmirror
13.05.2017, 13:16
Дмитрий2012, если время потом нужно вывести, то как предложил char можно сделать табличку с константами 864000000, 86400000, 36000000, 3600000, 600000, 60000, 10000, 1000, 100, 10, 1 и подсчитывая сколько раз их можно вычесть без переполнения, сразу получать нужные цифры. Причём первые три константы имеют нулевой младший байт, что позволяет вычитать только старшие три байта, после этого останется число не более 36000000, которое не влезает в три байта, но если его и остальные константы умножить на 2, то на этом шаге тоже можно будет обойтись 24-битным вычитанием, после вычитания 2*10000 можно перейти к 16-битному вычитанию, а после вычитания 2*100 остаётся 8-битное, ну а для последней цифры цикл уже не нужен, нужно только поделить остаток на 2. Есть сильное подозрение, что данный алгоритм будет работать быстрее чем деление на 1000, 60, 60 и 24.

char
13.05.2017, 14:51
а вообще, все это жесткая порнуха; кто миллисекунды увеличивает? на прерываниях? ну и делается это тогда отдельными счетчиками на мсек/сек/мин/час, увеличивающимися друг за другом, зачем вообще процессор и такты излишне жечь делением?! )

Дмитрий2012
13.05.2017, 15:45
Дмитрий2012, если время потом нужно вывести, то как предложил char можно сделать табличку с константами
Пока "мотаю на ус" С табличками не знаком, никогда не использовал их. Возможно попробую и такой вариант для саморазвития, как только сделаю вариант с делением.


а вообще, все это жесткая порнуха; кто миллисекунды увеличивает? на прерываниях?
миллисекунды считает "железка" и хранит у себя. И в одном из пунктов меню утилиты, которую пишу для этой "железки" процессор занят только выводом на экран этого времени. Можно сказать это простой "показометр". Так что в данном случае не критично как перекодировать время. Главное, чтобы правильно на экран выводилось в часах, минутах, секундах ... :)

krt17
13.05.2017, 18:53
Немного с опозданием но закину свои 66 байт

device zxspectrum48
org #8000
start
ld hl,(tick)
ld de,(tick+2)
ld c, 10
call div41
ld c, 100
call div41
ld (hdr),a
ld c, 60
call div41
ld (sec),a
ld c, 60
call div41
ld (min),a
ld (hour),hl
jr $
tick db 0,10,0,0
hdr db 0
sec db 0
min db 0
hour dw 0
div41
;dehl/c=dehl(a)
xor a
ld b, #20
.l1
add hl,hl
rl e
rl d
rla
cp c
jr c,.l2
sub c
inc l
.l2
djnz .l1
ret
savesna "time.sna",start
Около 8к тактов, разделяет на сотые, секунды, минуты и часы. Буду рад если окажется полезным.

NEO SPECTRUMAN
13.05.2017, 19:12
С табличками не знаком, никогда не использовал их.

к примеру нарисую умножение на 3 по табличке


ld h,$c0 ;старший адрес таблички

ld l,a ;то что нужно умножить

ld a,(hl) ;получаем результат

;сама табличка
org $c000
defb 0*3
defb 1*3
defb 2*3
defb 3*3
....
;и так до
defb 255*3


если нам не хватает 8 бит для результата

ld h,$c0 ;старший адрес таблички

ld l,a ;то что нужно умножить

ld с,(hl) ;получаем младший байт результат

inc h ; меняем табличку

ld b,(hl) ;получаем старший байт результата

;сама табличка
org $c000
defb (0*3) % 256 ;% - остаток от деления. в sjasmplus можно low (0*3)
defb (1*3) % 256
defb (2*3) % 256
defb (3*3) % 256
....
;и так до
defb (255*3)% 256

org $c100
defb (0*3) / 256 ; в sjasmplus можно high (0*3)
defb (1*3) / 256
defb (2*3) / 256
defb (3*3) / 256
....
;и так до
defb (255*3) / 256




с таким же успехом можно делать таблички в другой плоскости (правда с некоторыми ограничениями)
в l заносить номер таблички
а в h подставлять данные для обработки


таким образом можно запихнуть любое количество операций любой сложности с одной переменной
(нет можно и с несколькими конечно но это уже сложней и памяти жрет неимоверно)

Shiny
13.05.2017, 19:21
http://i33.fastpic.ru/big/2017/0513/eb/c40f8e8328684daaa337f75d967eb8eb.png

NEO SPECTRUMAN
13.05.2017, 19:27
Шынни, для демок или игр да
а для поставленной задачи точность скорей всего уедет
да и для 32 битных чисел...

ладно не могу вспомнить
есть єта формула у меня или нет
поставлю спасибку

char
13.05.2017, 20:13
Немного с опозданием но закину свои 66 байт
Около 8к тактов, разделяет на сотые, секунды, минуты и часы. Буду рад если окажется полезным.

если за скоростью не бегать (можно /10 /100, а можно /8сдвигом /125), то нормально, почему нет :)

еще вместо повторения ld c,60, перед div41 дописать и вызывать можно div60 ld c,60 ;)

krt17
13.05.2017, 20:49
еще вместо повторения ld c,60, перед div41 дописать и вызывать можно div60 ld c,60
Ну поучавствую в соревновании кэпов, второй ld c,60 можно вообще не писать, он не меняется

если за скоростью не бегать (можно /10 /100, а можно /8сдвигом /125), то нормально, почему нет
Ну сотые напечатать нормально, че нет то, а 125-ые как то не нативно

char
13.05.2017, 20:56
там ему тысячные так-то нужны были, а не сотые...
сначала можно сохранить 3 мл. бита, а в конце, после трех add hl,hl, восстановить or'ом, ежели по уму делать :)