Этюды - В.Сироткин. Программа подсчета контрольной суммы.

ZX Review #3-4

(c) В.Сироткин, г.Краснокаменск.

 Программа подсчета контрольной
            суммы.

   В некоторых программах прямой
необходимостью является  контро-
лирование правильности и целост-
ности блока данных, загружаемого
или сохраняемого  на диск. Также
может быть необходим  динамичес-
кий  контроль  части самой прог-
раммы.
   Эту  проблему  можно   решить
подсчетом контрольной суммы.
   Есть разные алгоритмы и  раз-
ные подходы, но самым  действен-
ным из всех  является метод ЦИК-
ЛИЧЕСКОГО    ИЗБЫТОЧНОГО    КОДА
(CRC).
   Алгоритм  CRC  применяется  в
IBM-программах и позволяет выяв-
лять ошибки с точностью до  бай-
та. Ниже дан листинг  процедуры,
подсчитывающей контрольную  сум-
му алгоритмом CRC. (Пример  взят
из журнала 'РАДИО' за 1992 год и
дается без комментариев).
148.
;--- входные параметры:
;    HL -начальный адрес блока
;    DE -конечный адрес блока
;--- выходные данные:
;    BC -контрольная сумма блока

LEN     DEFB   0

START   PUSH HL
        INC  DE
        XOR  A
        LD (LEN),A
        LD BC,0
MET1    PUSH DE
        LD A,C
        XOR (HL)
        LD E,A
        PUSH BC
        PUSH HL
        LD BC,00
        LD D,8
MET2    PUSH BC
        LD A,C
        RRA
        LD A,B
        RRA
        LD B,A
        LD A,C
        RRA
        LD C,A
        POP HL
        LD A,E
        XOR L
        AND 1
        JR Z,MET3
        LD A,B
        XOR #A0
        LD B,A
        LD A,C
        XOR 1
        LD C,A
MET3    LD A,E
        RRCA
        AND #7F
        LD E,A
        DEC D
        JR NZ,MET2
        POP HL
        POP DE
        LD A,D
        XOR C
        LD C,A
        LD A,E
        XOR B
        LD B,A
        LD A,(LEN)
        INC A
        LD (LEN),A
        INC HL
        POP DE
        LD A,H
        CP D
        JR NZ,MET1
        LD A,L
        CP E
        JR NZ,MET1
        DEC DE
        POP HL
        RET
2
   Данная  подпрограмма  переме-
щаема, т.е. может работать в лю-
бых адресах, если  Вы,  конечно,
определите адрес с меткой  'LEN'
куда-нибудь за пределы  подпрог-
раммы.
   Достаточно точно отслеживает-
ся изменение байтов  в  обсчиты-
ваемой области.  Замечается даже
перестановка рядом лежащих  бай-
тов.  Что  касается   быстродей-
ствия, то блок длиной в 48 кило-
байт обсчитывается за 5 сек.

   Арифметические вычисления.

   Как  Вы  знаете,  в  ПЗУ  SOS
встроена мощная  программа КАЛЬ-
КУЛЯТОР, которая позволяет  про-
изводить как  простые  арифмети-
ческие  действия, так и действия
с  плавающей  запятой и тригоно-
метрические вычисления.
   Но  для  работы  КАЛЬКУЛЯТОРА
необходима особая область - СТЕК
КАЛЬКУЛЯТОРА,  да  и  работа   с
калькулятором довольно сложна  и
утомительна, особенно в програм-
мах, затирающих всю область ОЗУ.
   Иногда же требуются короткие,
но действенные подпрограммы, вы-
полняющие  арифметические   дей-
ствия над байтами.
   Далее  представлены несколько
подпрограмм,  которые  позволяют
обойтись без встроенного КАЛЬКУ-
ЛЯТОРА.  Все подпрограммы  могут
работать в любом месте ОЗУ, т.е.
релоцируемы.

   Сложение N-байтовых положи-
         тельных чисел.

   Для того, чтобы  сложить  два
числа длиною в N байтов, необхо-
димо в регистр "B" занести коли-
чество байтов в слагаемых.  Сла-
гаемые  заносятся  изначально  в
область с метками FIRST и SECND.
Результат поместится в область с
меткой FIRST.
148.
;  Подпрограмма сложения многобайтных беззнаковых
;  чисел

ADDN    LD B,N       ; в "B" - сколько байтов надо
                     ; сложить
        LD DE,FIRST  ; адрес первого слагаемого
        LD HL,SECND  ; адрес второго слагаемого
        XOR A        ; флаг переноса сбросим
SUM     LD A,(DE)    ; загрузим первый (младший)
                     ; байт числа
        ADC A,(HL)   ; сложим со вторым числом
        LD (DE),A    ; сохраним результат
        DEC B        ; все байты сложены ?
        RET Z        ; если все, то конец
        INC HL       ; нет, продолжим сложение
        INC DE
        JR SUM
; - -
N       EQU  ?     ; сколько байт складывать ?
FIRST   DEFB ?     ; область длиною в (?) байт
                   ; для первого числа
SECND   DEFB ?     ; область для второго числа
                   ; длиною (?)


     УМНОЖЕНИЕ однобайтных
   целых положительных чисел.

;  Множимое заносится в регистр 'D'
;  Множитель в регистр 'C'
;  Результат в регистре  'BC'

START   LD B,0      ; сброс старшего байта
                    ; результата
        LD E,8      ; число битов в байте
NXBIT   LD A,C      ; множитель
        RRA         ; очередной бит в флаге 'C'
        LD C,A      ; вернем множитель
        DEC E       ; счетчик уменьшим

        RET M       ; все биты ? ДА- выйдем

        LD A,B      ; старший байт результата
        JR NC,NOADR ; флаг 'C'множителя =0
        ADD A,D     ; суммируем множитель
NOADR   RRA         ; сдвинем частичную сумму
        LD B,A      ; вернем старший байт
        JR NXBIT    ; умножение следущего бита


 ПРОГРАММА ДЕЛЕНИЯ ОДНОБАЙТНЫХ
   ЦЕЛЫХ ПОЛОЖИТЕЛЬНЫХ ЧИСЕЛ.

; делимое помещают в регистр 'E'
; делитель помещают в регистр 'D'
; частное получается в регистре 'H'
; в регистре 'C' образуется положительный остаток от
; деления

START  LD HL,08     ; 8 бит в байте
       LD C,0       ; сброс регистра остатков
NEXT   LD A,E       ; делимое сдвинем
       RLA          ; влево
       LD E,A       ; на 1 бит
       LD A,C       ; сдвиг остатка
       RLA          ; влево на 1 бит
       SUB A,D      ; вычтем делитель
       JR NC,NOADR  ; остаток положительный ?
       ADD A,D      ; востановление отрицательного
                    ; остатка
NOADR  LD C,A       ; остаток запомним
       CCF          ; образуем бит частного
       LD A,H       ; запоминание
       RLA          ; очередной
       LD H,A       ; цифры частного
       DEC L        ; декремент счетчика битов
       JR NZ,NEXT   ; цикл
       RET          ; выход
;3 подпрограмма выполняется за 660 тактов.


   ПРОГРАММА УМНОЖЕНИЯ ЦЕЛОГО
     ОДНОБАЙТНОГО ЧИСЛА НА
    ЦЕЛОЕ ДВУХБАЙТНОЕ ЧИСЛО
     (числа положительные).

; 2-х байтное множимое поместить в 'DE'
; 1-байтный множитель в 'A'
; результат получим в регистрах :
;            в 'A' старший байт произведения
;            в 'HL' младшие 16 бит произведения

START   LD HL,0       ; сброс регистра произведения
        LD C,8        ; счетчик битов
NXBIT   ADD HL,HL     ; частичная сумма
        RLA           ; сдвинем множитель
        JR NC,NOADR   ; анализ бита множителя
        ADD HL,DE     ; суммируем множимое
NOADR   ADC 0         ; учет переноса
        DEC C         ; все 8 бит множителя ?
        JR NZ,NXBIT   ; нет, продолжим
        RET           ; выход
;------------------------------
2

    ПРЕОБРАЗОВАНИЕ ДВОИЧНОГО
   ЧИСЛА В ДВОИЧНО-ДЕСЯТИЧНОЕ.

   Для  отображения  результатов
вычислений   необходимо    числа
привести в  удобный  для  вывода
вид, т.е. преобразовать число  в
десятичный код. Например, двоич-
ное число 00001111 (#0F)  удобно
представить  в  виде  0001  0101
(#15), т.е. преобразовать его  в
двоично-десятичную  форму.  Этим
занимается следующая подпрограм-
ма.
148.
; BCD2B- подпрограмма перевода 2-х байтного числа.
; Двоичное число должно быть в регистре 'HL'.
; Результат :
;           в 'A' - десятки тысяч;
;           в 'B' - тысячи и сотни;
;           в 'C' - десятки и единицы.
; Во время работы вызывается процедура CONV из
; подпрограммы BCD1B - перевод однобайтного числа,
; в которой;
; в 'H' - число для перевода , 'L'=0
; Результат работы: в 'A' - разряды сотен;
;                   в 'B' - десятки и единицы

; Вход в процедуру преобразования 2-х байтного числа:

BCD2B   LD E,17     ; счетчик 1-го цикла
        CALL CONV   ; вычислить младший BCD байт
        LD C,A      ; сохранить в 'C'
        LD E,17     ; счетчик 2-го цикла
        JR PRODOL   ; переход на вычисление

; процедура для преобразования 1-байтного числа

BCD1B   LD E,9      ; цикл для 1-байтного числа

PRODOL  CALL CONV   ; вычислить два старших байта
        LD B,A      ; сохранить средний байт
        LD A,L      ; старший байт
        RET         ; выйти вообще
;-----
CONV    XOR A       ; очистить
SBIT    DEC E       ; уменьшим счетчик цикла
        RET Z       ; цикл весь - выйти
        ADD HL,HL   ; сдвинем старшие разряды в
                    ; перенос
        ADC A,A
        DAA         ; скорректируем
        JR NC,SBIT  ; результат больше 99 ?
        INC HL      ; да - увеличим на 1
        JR SBIT     ; вернемся в вычисления
2
********************************