ZX Format
#07
05 декабря 1997 |
|
Программистам - Алгоритмы работы и примеры процедур для быстрых вычислений на асемблере: Умножение и деление 3-х байтовых чисел,
Быстрые вычисления в ассемблере music by COOPER (C) GreenFort _ Да, сколько проблем с этой математи- кой, а ведь надо, и надо просто повсе- местно. То векторная графика дает о себе знать, то подсчет очков в своей игрушке, а то и расчет положения светил на небос- воде. Так или иначе, всегда возникают си- туации, когда скорости ПЗУшного калькуля- тора явно недостаточно. Мы предлагаем вашему вниманию цикл ста- тей, посвященных математическим операци- ям. Подразумевается, что человек читающий эти строки уже усвоил азы программирова- ния на Ассемблере. Начнем с простого: 1. ДЕЛЕНИЕ. Принцип работы процедуры деления основан на делении в столбик, единственное отли- чие только в системе счисления: она дво- ичная. 1.1 Пример_простейшей_процедуры_деления: НА ВХОДЕ : C = Делимое, В = Делитель НА ВЫХОДЕ: L = результат, A = остаток ;L=C/B: DIVIS XOR A ;обнуление текущего ос- ;татка DIVIS2 LD L,#01 ;счетчик (сдвиг 8 раз) D1 RL C ;чтение текущего разряда RLA ;накопитель разрядов CP B ;какой результат текущего ;разряда JR C,ZER ;переход,если текущий ;разряд=0 SUB B ;тек.разряд=1,снятие с ;накопителя SLI L ;занесение разряда=1 JR NC,D1 ;переход,если счетчик не ;переполнился RET ;выход ZER SLA L ;занесение разряда=0 JR NC,D1 ;переход,если счетчик не ;переполнился RET ;выход L - используется как счетчик и хранит результат. A - остаток деления, из C последова- тельно считываются разряды в регистр A. B - остается неизменным после деления. Процедурку можно, кстати, раскрыть. Если вам нужна большая точность деле- ния,то можно продолжить делить. Пример: LD C,что делить будете LD B,на что делить будете CALL DIVIS;первичное деление ;C=0,A-остаток LD H,L ;сохранение результата CALL DIVIS2 ;вторичное деление ;без обнуления остатка езультат в HL: H = целая часть результата L = дробная часть результата Получаемая точность: +-(1/256),т.е. два знака после запятой обеспечивается. 1.2 Процедурка_деления_3-х_байтовых_чисел На входе : A,H,L - три байта делимого B,D,E - три байта делителя На выходе: A,H,L - результат ;A,H,L=(A,H,L)/(B,D,E) DIVISIO LD C,A ;старший байт делимого ;храним в C XOR A ;обнуление накопителя EXX ;резрядов LD HL,#01 ;счетчик (на 24) и LD B,H ;трехбайтовый хранитель EXX ;результата DIV1SLA L ;выборка разряда RL H RL C RLA CP B ;накопитель больше ;делителя? JR C,DIV2 ;если меньше,то резуль- ;тат 0) JR NZ,DIV3;в случае,если больше ; результат=1 накопитель уменьшается EX AF,AF' ;сохранение A LD A,C ;аналогично проверка CP D ;младших двух байт на- JR C,DIV22;копителя и делителя JR NZ,DIV32 LD A,H CP E JR C,DIV22 DIV32 EX AF,AF' ;накопитель=делитель DIV3EX AF,AF' LD A,L ;накопитель-делитель LD L,H ;(младшие 2 разряда) LD H,C AND A SBC HL,DE LD C,H LD H,L LD L,A JR NC,DIV33 EX AF,AF' ;накопитель-делитель SUB B ;старший разряд при DEC A ;переполнении младших DIV34 EXX ;занесение врезультат SLI L ;текущий бит=1 RL H RL B EXX JP NC,DIV1;счетчик еще не кон- ;чился JP DIVEXIT;счетчик переполнился ;конец деления DIV22 EX AF,AF' ;занесение в результат=0 DIV2EXX SLA L RL H RL B EXX JP NC,DIV1;счетчик еще не кон- ;чился DIVEXIT EXX ;счетчик переполнился PUSH HL ;конец деления LD A,B EXX POP HL RET DIV33 EX AF,AF' ;накопитель-делитель SUB B ;старший разряд без JP DIV34 ;переполнения младших Затем довольно удобно использовать ре- зультат для сложения или вычитания: Сложение результата с 3-х байтовым числом . CALL DIVISIO LD B,1-й байт, который прибавляем LD DE,2 и 3 байт, которые прибавляем ADD HL,DE ADC A,B . 2. УМНОЖЕНИЕ. Умножение, как и деление базируется на умножении в столбик. 2.1 Простейшая_процедурка_умножения. Пример: ;HL=B*C LD HL,#0 ;подготовка резултата LD E,B ;коэф.текущего разряда LD D,H LD B,#08 ;счетчик MCYCSRL C ;выборка разряда второ- ;го множителя JP NC,NOADD ;разряд=0 (DE*0=0) ADD HL,DE ;разряд=1 (DE*1=DE) NOADD SLA E ;смена коэффициента раз- RL D ;ряда на след. разряд DJNZ MCYC ;цикл на 8 RET ;выход Конечно, сразу бросается в глаза, что и эту конструкцию можно раскрыть. 2.2 Умножение_3-х_байтовых_чисел. ;A,H,L=A,H,L*B,D,E MULTI EXX LD HL,FLAG;сброс переноса RES 0,(HL) LD B,24 ;счетчик LD HL,#0 ;результат (C,H,L) LD C,H PF2 EXX SRL B ;выборка разряда RR D ;второго множителя RR E JR NC,PF3 ;разряд=0,переход на ;выборку следующего разряда EX AF,AF' ;сложение ответа с PUSH HL ;текущим коэф.разряда EXX POP DE ADD HL,DE ADC A,C JP NC,NOFLAG ;результат не помещается в трех байтах! LD A,(FLAG) ;обработчик переполне- OR 1 ;ния LD (FLAG),A RET NOFLAG LD C,A EXX EX AF,AF' -PF3 SLA L ;переход к следующему RL H ;текущий коэф.(AHL*2) RLA EXX DJNZ PF2 ;цикл на 24 LD A,C RET ;выход FLAGDB 0 1 в переменной FLAG в случае переполне- ния результата;хотя очень часто программы все продуманы и необходимости в нем нет. Все возможные последующие операции(сложе- ние,вычитание) с ответом такие-же,как и в делении. Если разберетесь, то мы думаем,вы без особого труда сами сможете переделать процедуры и под большее количество байт для повышения точности расчетов. Напоминаем, что процедурки для 3-х бай- товых чисел вы можете использовать как для подсчета целых чисел, так и дробных. Продолжение следует.
Другие статьи номера:
Похожие статьи:
В этот день... 21 ноября