Задача #1
Найти значение функции M3=(B+E-73H)+M2-(M1+7AH)-D
LDA 8150
;M1→A
ADI 7A
;A:=A+7AH
MOV C, A
;A→C
LDA 8160
;M2→A
SUB C
;A:=A-C
SUB D
;A:=A-D
MOV C, A
;A→C
MOV A, B
;B→A
ADD E
;A:=A+E
SUI 73
;A:=A-73H
ADD C
;A:=A+C
STA 8170
;A→M3
Задача #2
Написать алгоритм задержки 255 мс ± 0,1%
Поскольку 1 такт занимает 0,5 мкс, то по пропорции: | 1 такт - 0,5·10-6
Х
|
тактов.
Учитывая погрешность 0,1%, результат должен составить 510000 ± 510 тактов.
Для такого кол-ва тактов будем использовать не один регистр, а регистровую пару DE.
Код задержки будет таким:
LXI
D
,
Y
CALL DEL
… … …
DEL
:
DCX
D
;5 тактов
MOV
A
,
D
;5 тактов
ORA
D
;4 такта
JNZ
DEL
;10 тактов, если условие выполняется, и 7 тактов, если не выполняется
RET
;10 тактов
Чтобы найти Yвоспользуемся формулой: 510000 = Y(5(
DCX)
+5(
MOV)
+4(
ORA)
+10(
JNZ)
) + 10(
RET)
.
510000 = 24·Y + 10 → Y = (510000–10) / 24 → Y = 21249,58 ≈ 21250 циклов. 2125010
= 530216
.
В программе использована команда ORAD, которая не влияет на содержимое аккумулятора, но влияет на флаг нулевого результата Z, по которому мы судим об окончании.
Окончательный код задержки будет выглядеть следующим образом:
LXI
D
, 5302
;10 тактов
CALL
DEL
;17 тактов
… … …
DEL
:
DCX
D
;5 тактов
MOV
A
,
D
;5 тактов
ORA
D
;4 такта
JNZ
DEL
;10 тактов, если условие выполняется, и 7 тактов, если не выполняется
RET
;10 тактов
В результате общее количество тактов будет: 24(один цикл)
·21250 + 10(
RET)
– 3(
JNZ)
+ 10(
LXI)
+ 17(
CALL)
= 510034 тактов.
Погрешность составит: .
Задача
#3
Вычислить ,
где АСР
и А
MIN
– среднее арифметическое и минимальное значение массива однобайтных чисел объёмом в 64 элемента.
Значения АСР
и А
MIN
могут быть в диапазоне: . Следовательно, Y
может быть в диапазоне: . Как видно, результат умещается в один регистр (байт).
Общий алгоритм программы выглядит так:
Алгоритм подпрограммы ADT (суммирования и нахождения минимального элемента):
Алгоритм подпрограммы DIV (деления через циклический сдвиг вправо с переносом):
Алгоритм подпрограммы REZ (нахождение значения Y):
<!-- так как среднее значение (АСР
) не превышает один байт, то оно находится не в паре DE, а в регистре D; это значение будет переправлено в регистр Н (пара HL уже не используется), чтобы освободить пару DE -->
Листинг программы расположен ниже:
CALL
ADT
;вызов подпрограммы ADT (суммирование и нахождение минимального
элемента)
MVI
B
, 06
;задание кол-ва сдвигов (B:=06H – 6 сдвигов равносильно
делению на 64)
CALL DIV
;вызов подпрограммы DIV (нахождение среднего значения)
CALL
REZ
;вызов подпрограммы REZ (вычисление результата Y)
STA
80
FF
;
пересылаем значение Y (окончательный результат) в ячейку 80FFH
RST 1
;выход из программы
ADT
: LXI H, 8100
;задание адреса первого элемента (HL:=8100H)
MVI
B
, 40
;задание кол-ва элементов (B:=64D=40H)
XRA A
;обнуление аккумулятора
LX
I
D
, 0000
;обнуление регистров E и D (пары DE) – старшего и младшего
байтов результата суммирования соответственно
MOV
C
,
M
;
будем считать первый элемент минимальным (С:=M(HL))
X1:
MOV
A
, M
;переслать в аккумулятор текущий элемент (A:=M(HL))
CMP
C
;сравниваем содержимое аккумулятора с текущим наименьшим
значением (A-C)
JP
X
2
;при TS=0 (A-C≥0 → A≥C) переход на Х2
MOV
C
,
A
;если же TS=1 (A-C<0 → A<C), сделать текущий элемент наименьшим
X
2:
ADD
D
;суммирование (A:=D+A)
MOV D, A
;пересылкаA→D
JNC X3
;перейти на Х3 если нет переполнения
INR
E
;произошло переполнение → прибавить 1 к старшему байту
результата суммирования
X3: INX H
;присвоить HL адрес следующей ячейки (HL:=HL+1)
DCR
B
;уменьшение счётчика кол-ва элементов на 1 (B:=B-1)
JNZ X1
;если элемент не последний - продолжить суммирование
RET
;выход из подпрограммы ADT
DIV
:
MOV
A
,
E
;пересылаем старший байт в аккумулятор (E→A)
RAR
;циклический сдвиг вправо через ТС
MOV
E
,
A
;возврат в Е старшего байта
MOV
A
,
D
;пересылаем младший байт в аккумулятор (D→A)
RAR
;циклический сдвиг вправо через ТС
MOV
D
,
A
;возврат в D младшего байта
ORA
A
;обнуление флага переполнения (ТС:=0)
DCR
B
;уменьшение счётчика кол-ва сдвигов на 1 (B:=B-1)
JNZ
DIV
;если сдвиг не последний – продолжить
RET
;выход из подпрограммы DIV
REZ
:
MOV
Н,
D
;пересылаем среднее значение в регистр Н
LX
I
D
, 0000
;обнуление регистров E и D (пары DE) - старшего и младшего
байтов результата Y соответственно
MOV
A
,
C
;
пересылаем минимальное значение в аккумулятор (C→A)
ADD A
;суммирование (A:=AMIN
+AMIN
=2AMIN
)
JNC
X
4
;перейти на Х4 если нет переполнения
INR
E
;
произошло переполнение → прибавить 1 к старшему байту
результата Y
X
4:
ADD
C
;
суммирование (A:=2AMIN
+AMIN
=3AMIN
)
JNC
X
5
;перейти на Х5 если нет переполнения
INR
E
;
произошло переполнение → прибавить 1 к старшему байту
результата Y
X
5:
MOV
D
,
A
;пересылаем младший байт из аккумулятора в регистр D
MVI
B
, 01
;задание кол-ва сдвигов (B:=01H – 1 сдвиг равносилен
делению на 2)
CALL DIV
;вызов подпрограммы DIV (деление на 2)
MOV
A
, Н
;пересылаем среднее значение в аккумулятор (Н→A)
ADD
D
;суммирование АСР
+ младший байт (3АMIN
/2)
JNC
X
6
;перейти на Х6 если нет переполнения
INR
E
;
произошло переполнение → прибавить 1 к старшему байту
результата Y
X
6:
MOV
D
,
A
;пересылаем младший байт из аккумулятора в регистр D
MVI
B
, 02
;задание кол-ва сдвигов (B:=02H – 2 сдвига равносильно
делению на 4)
CALL DIV
;вызов подпрограммы DIV (деление на 4)
MOV
A
,
D
;пересылаем значение Y в регистр аккумулятор (D→A)
RET
;выход из подпрограммы REZ
Задача
#4
Вычислить ,
где АСР
, AMAX
и А
MIN
– среднее арифметическое, максимальное и минимальное значение массива однобайтных чисел объёмом в 64 элемента.
Значения АСР
, AMAX
и А
MIN
могут быть в диапазоне: . Минимальное значение (Y=00
) может быть при АСР
= AMAX
= А
MIN
= 00.
Максимальное значение будет тогда, когда массив будет состоять из 63х элементов, равных FF
, и одного элемента, равного 00
; при этом: AMAX
=
FF
, А
MIN
= 00
, АСР
=
FC
. В таком случае значение Y
составит 1
F41016
, что выходит за пределы пары регистров и умещается в три байта. Значение Y
будет располагаться в ячейках памяти 80
FFH
, 80
FEH
, 80
FDH,
причем младший байт – в ячейке 80
FDH
, самый старший – в ячейке 80
FFH
.
Общий алгоритм программы выглядит так:
В программе используются подпрограммы ADT и DIV, алгоритм которых можно увидеть в задаче #3
. Подпрограмма деления (DIV) идеально подходит и для задачи #4
, а подпрограмму суммирования и нахождения минимального элемента массива (ADT) можно было бы дополнить нахождением и максимального элемента массива, если бы у на был хотя бы ещё один неиспользуемый регистр. Выйти из этой ситуации можно было бы используя ячейки ОЗУ для хранения промежуточных значений AMAX
и А
MIN
. Но, так как AMAX
требуется для расчёта лишь множителя, в программе была использована дополнительная подпрограмма нахождения максимального элемента и вычисления множителя (MAX).
Алгоритм подпрограммы REZ1 (вычисления множимого):
Алгоритм подпрограммы MAX (нахождение максимального элемента и вычисление множителя):
Алгоритм подпрограммы MULT (умножения и записи результата (Y
) в ОЗУ):
<!-- Операция умножения реализована посредством многократного суммирования (кол-во циклов суммирования = множитель-1). Поскольку множимое состоит из двух байт (находится в паре DE), то суммирование производится сначала для младших байтов (счётчик переполнения – в регистре H), а потом для старших байтов (счётчик переполнения – в регистре L). Таким образом, первый (младший) байт Y
находится в регистре D, второй байт – состоит из суммы старшего байта множимого (E) и счётчика переполнения младшего байта множимого (H), третий (старший) байт –
Листинг программы приведён ниже:
CALL
ADT
;вызов подпрограммы ADT (суммирование и нахождение
минимального элемента)
MVI
B
, 06
;задание кол-ва сдвигов (B:=06H – 6 сдвигов равносильно
делению на 64)
CALL DIV
;вызов подпрограммы DIV (нахождение среднего значения)
CALL
REZ
1
;вызов подпрограммы REZ1 (вычисление (4ACP
– AMIN
/4))
CALL
MAX
;вызов подпрограммы MAX (вычисление AMAX
/2)
CALL
MULT
;вызов подпрограммы MULT (умножение)
RST 1
;выход из программы
ADT
: LXI H, 8100
;задание адреса первого элемента (HL:=8100H)
MVI
B
, 40
;задание кол-ва элементов (B:=64D=40H)
XRA A
;обнуление аккумулятора
LX
I
D
, 0000
;обнуление регистров E и D (пары DE) – старшего и младшего
байтов результата суммирования соответственно
MOV
C
,
M
;
будем считать первый элемент минимальным (С:=M(HL))
X1:
MOV
A
, M
;переслать в аккумулятор текущий элемент (A:=M(HL))
CMP
C
;сравниваем содержимое аккумулятора с текущим наименьшим
значением (A-C)
JP
X
2
;при TS=0 (A-C≥0 → A≥C) переход на Х2
MOV
C
,
A
;если же TS=1 (A-C<0 → A<C), сделать текущий элемент
наименьшим
X
2:
ADD
D
;суммирование (A:=D+A)
MOV D, A
;пересылкаA→D
JNC X3
;перейти на Х3 если нет переполнения
INR
E
;произошло переполнение → прибавить 1 к старшему байту
результата суммирования
X3: INX H
;присвоить HL адрес следующей ячейки (HL:=HL+1)
DCR
B
;уменьшение счётчика кол-ва элементов на 1 (B:=B-1)
JNZ X1
;если элемент не последний - продолжить суммирование
RET
;выход из подпрограммы ADT
DIV
:
MOV
A
,
E
;пересылаем старший байт в аккумулятор (E→A)
RAR
;циклический сдвиг вправо через ТС
MOV
E
,
A
;возврат в Е старшего байта
MOV
A
,
D
;пересылаем младший байт в аккумулятор (D→A)
RAR
;циклический сдвиг вправо через ТС
MOV
D
,
A
;возврат в D младшего байта
ORA
A
;обнуление флага переполнения (ТС:=0)
DCR
B
;уменьшение счётчика кол-ва сдвигов на 1 (B:=B-1)
JNZ
DIV
;если сдвиг не последний – продолжить
RET
;выход из подпрограммы DIV
REZ
1:
MOV
Н,
D
;пересылаем ACP
в регистр Н
MVI
E
, 00 ;
обнуление регистра Е
MOV
D
,
C
;
пересылка АMIN
в регистр D
MVI
B
, 02
;задание кол-ва сдвигов (B:=02H – 2 сдвигa равносильно
делению на 4)
CALL DIV
;вызов подпрограммы DIV (деление на 4)
MOV
C
,
D
;обратная пересылка в регистр С значения АMIN
/4
MOV
A
,
H
;
отправляем ACP
в аккумулятор
MVI
E
, 00 ;
обнуление регистра E
MVI
B
, 03 ;
записываем в регистр В количество циклов суммирования
(03 = 4 - 1)
X
4:
ADD
H
;
к аккумулятору прибавляем по одному значению ACP
JNC
X
5 ;
если нет переполнения – перейти на Х5
INR
E
;
если произошло переполнение – увеличить старший байт на 1
X
5:
DCR
B
;
уменьшить кол-во циклов суммирования на 1
JNZ
X
4 ;
если цикл не последний – повторить суммирование
SUB
C
;
вычитание: 4АСР
– AMIN
/4
JP
X
6 ;
если результат вычитания положителен – перейти на Х6
DCR
E
;
если результат вычитания отрицателен – вычесть 1 из
старшего байта
X
6:
MOV
D
,
A
;
переслать младший байт результата (4АСР
– AMIN
/4) в регистр
D (весь результат находится в паре DE)
RET
;выход из подпрограммы REZ1
MAX
: LXI H, 8100
;задание адреса первого элемента (HL:=8100H)
MVI
B
, 40
;задание кол-ва элементов (B:=64D=40H)
MOV
A
,
M
;
будем считать первый элемент максимальным (A:=M(HL))
X7:
CMP
M
;сравниваем максимальный элемент с текущим (A-M(HL))
JP
X
8
;при TS=0 (A-M(HL)≥0 → A≥M(HL)) переход на Х8
MOV
A
,
M
;если же TS=1 (A-M(HL)<0 → A<M(HL)), сделать текущий
элемент максимальным
X8: INX H
;присвоить HL адрес следующей ячейки (HL:=HL+1)
DCR
B
;уменьшение счётчика кол-ва элементов на 1 (B:=B-1)
JNZ X7
;если элемент не последний - продолжить суммирование
RAR
;деление AMAX
на 2
ORA
A
;обнуление флага переполнения (ТС:=0)
MOV
C
,
A
;пересылка значения AMAX
/2 в регистр C
RET
;выход из подпрограммы MAX
MULT
:
LXI
H
, 0000 ;
обнуление регистров H и L
MOV
B
,
C
;загрузить множитель (AMAX
/2) в регистр В
DCR
B
;уменьшение на 1 множителя
MOV
A
,
D
;пересылка младшего байта множимого в аккумулятор
X
9:
ADD
D
;суммируем по одному значению
JNC
X
10
;если нет переполнения – перейти на Х10
INR
H
;если было переполнение – увеличить счётчик переполнения
младшего байта на 1
X
10:
DCR
B
;уменьшить кол-во циклов суммирования на 1
JNZ
X
9
;если цикл не последний – повторить суммирование
STA
80
FD
;отправить первый (самый младший) байт результата (Y) в
ячейку ОЗУ 80FDH
MOV
B
,
C
;загрузить множитель (AMAX
/2) в регистр В
DCR
B
;уменьшение на 1 множителя
MOV
A
,
E
;пересылка старшего байта множимого в аккумулятор
X
11:
ADD
E
;суммируем по одному значению
JNC
X
12
;если нет переполнения – перейти на Х12
INR
L
;если было переполнение – увеличить счётчик переполнения
старшего байта на 1
X
12:
DCR
B
;уменьшить кол-во циклов суммирования на 1
JNZ
X
11
;если цикл не последний – повторить суммирование
ADD
H
;суммирование старшего байта множимого с счётчиком
переполнения младшего байта множимого
JNC
X
13
;если нет переполнения – перейти на Х13
INR
L
;если было переполнение – увеличить счётчик переполнения
старшего байта на 1
X
13:
STA
80
FE
;отправить второй байт результата (Y) в ячейку ОЗУ 80FDH
MOV
A
,
L
;переслать третий байт результата (Y) в аккумулятор
STA
80
FF
;отправить третий байт (самый старший) результата (Y) в
ячейку ОЗУ 80FFH
RET
;выход из подпрограммы MULT
Задача
#5
Разработать драйвер вывода информации (разрядностью 12 бит) на внешнее устройство с помощью параллельного интерфейса ППИ (К580ВВ55).
Поскольку разрядность данных составляет 12 бит, для их вывода понадобится порт А и порт В. Отправлять сигнал «Запись» и принимать сигнал «Готов» будем портом С. Следовательно, управляющее слово будет таким: 100010002
= 8816
.
1 | 00 | 0 | 1 | 0 | 0 | 0 |
Режим работы группы А - 0 | Направление порта А - вывод | Направление порта С(7-4) - ввод | Группа В | Направление порта В - вывод | Направление порта С(3-0) - вывод |
Схема обмена данными ППИ с периферийным устройством:
Алгоритм работы драйвера:
DRV
:
PUSH
B
;сохранение с стеке пары ВС
PUSH
D
;сохранение с стеке пары DE
PUSH
H
;сохранение с стеке пары HL
PUSH
PSW
;сохранение с стеке аккумулятора и флагов
MVI
A
, 10001000
OUT
<
П
ер.
У
стр.>
;вывод управляющего слова на периферийное устройство
LXI
H
, 8070
;загрузка в пару HLадреса младшего байта
(1-8й бит) данных
MOV
A
,
M
OUT
PORTA
;вывод младшего байта в порт А
INX
H
;перейти на адрес старшего байта (9-12й бит) данных
MOV
A
,
M
OUT
PORTB
;вывод старшего байта в порт В
MVI A, 00000001
OUT
PORTC
;вывод сигнала «Запись» на порт С(0)
MVI A, 00000000
OUT
PORTC
;обнуление значения порта С
X
1:
IN
PORTC
;приём сигнала портом С
RAL
;перемещение старшего бита пришедшего сигнала
с порта С(7) в ТС
JNC
X
1
;если ТС=0 (сигнал не пришёл) - продолжить ожидание
POP
PSW
;восстановление аккумулятора и флагов
POP
H
;восстановление пары HL
POP
D
;восстановление пары DE
POP
B
;восстановление пары BC
RET
;выход из драйвера