Работа с внешними устройствами

Как уже говорилось ранее, модель «Е97» отражает наиболее простые методы обмена с внешними устройствами из тех, что свойственны современным компьютерам.

Как и в реальных микропроцессорах, «общение» с периферийными устройствами осуществляется через порты ввода-вывода. Для учебной ЭВМ принята наиболее простая модель, когда каждому из имеющихся внешних устройств соответству ет два порта -порт данных и порт состояния. Можно считать, что каждый порт представляет собой 16-разрядный регистр, находящийся в контроллере. Через порт данных происходит обмен информацией. Порты состояния позволяют управлять процессом обмена данными, так как предоставляют процессору сведения о текущем состоянии внешнего устройства. Реальная синхронизация ввода-вывода является достаточно сложной проблемой и существенно зависит от типа периферийного устройства. Поэтому в «Е97» регистр состояния устроен максимально просто: в нем имеется единственный используемый бит - бит готовности. В обсуждаемом учебном компьютере бит готовности помещается в седьмом разряде регистра состояния.

Все порты являются 16-разрядными, но реальная информация всегда располагается в их младшем байте. Содержимое битов с 8-го по 15-й в выходные порты формально заносится, но никакого влияния на устройство вывода не оказывает.

Каждому порту соответствует свой номер (адрес). В «Е97»из шестнадцати возможных используются следующие порты:

0 - порт состояния клавиатуры (только чтение);

1 - порт данных клавиатуры (только чтение);

2 - порт состояния дисплея (только чтение);

3 - порт данных дисплея (только запись).

Стандартный алгоритм обмена с использованием портов ввода-вывода выглядит следующим образом. Считывается порт состояния и проверяется значение знакового бита его младшего банта. Эта операция повторяется до тех пор, пока бит готовности не будет установлен внешним устройством в единицу, что является сигналом процессору к началу обмена. Только после него процессор может записать информацию в порт данных, если речь идет об устройстве вывода, или считать их из порта, если это порт ввода.

Вот как может выглядеть правильная программа вывода одиночного символа из R0 на дисплей (именно так она реализована в ПЗУ «Е97»):

0А21 порт2=>R1

Е401 сравнить с 0 R1b

2DFA если ≥ 0, PC - 6 (к повторению проверки)

0В03 R0 => порт 3

Первые три команды считывают и проверяют бит готовности в порту 2, а последняя команда обеспечивает собственно вывод требуемого символа на дисплей.

Обратите внимание на команду с «короткой константой» 0,которая обязательно должна проверять знаковый разряд младшего байта, а не всего слова в целом.

Мы подробно рассмотрели программирование процедуры вывода символа; ввод осуществляется совершенно аналогично.

ПРИМЕРЫ ПРОГРАММ

Пример 1. Вычислить полную поверхность параллелепипеда со сторонами А, В и С. Считать, что исходные значения находятся в ячейках ОЗУ. Результат также поместить в ячейку памяти.

Решение. Полная поверхность параллелепипеда вычисляется по формуле

S=2*(A*B+A*C+B*C)

Для упрощения программы выражение удобно представить в виде S = 2 * [А * (В + С) + В * С]

Программа 134

0000 01ЕО (22) => R0 В => R0

0002 0022

0004 0101 R0 => Rl В => Rl

0006 02Е0 R0 + (24) => R0 В + С

0008 0024

000А 05Е0 R0 * (20) => R0 A * (В + С)

000С 0020

000Е 05Е1 Rl * (24) => Rl В * С

0010 0024

0012 0210 R0 + Rl => R0 A * (В + С) + В * С

0014 0200 R0 + R0 => R0 2 * [A * (В + С) + В * С]

0016 010Е R0 => (26) результат => S

0018 0026

001A 0F00 останов

……….

0020 0002 А

0022 0003 В

0024 0004 С

0026 0034 S

Примечание. Не забывайте, что ответ 34 в памятиЭВМ представленв шестнадцатеричной системе. В десятичной, как и положено, получится 52.

Пример 2. Организовать ввод латинских букв таким образом: программа принимает латинскую букву и обрабатывает ее так, чтобы она всегда была заглавной.

Решение. Главная «хитрость» решения состоит в том, чтобы понять, чем отличаются заглавные буквы от строчных. Для этого из таблицы ASCII, приведенной в главе 1, выберем наугад одну из букв и выпишем в двоичном виде коды заглавного и строчного символов. Например, для буквы R получим

R 0101 0010

r 0111 0010

Повторив аналогичные действия еще для нескольких букв, сделаем вывод, что коды заглавных ч строчных букв отличаются единственным битом - пятым, если считать младший бит за нулевой. Запомним этот факт,поскольку он справедлив для любого современного компьютера.

Итак, для нашей задачи требуется сохранить все биты, кроме пятого, значит потребуется выполнить логическую операцию И с константой

1101 1111 =DF,

после чего любой код «потеряет» ненужный нам бит, сохраняя все остальные.

Еще одной особенностью решения является активное использование подпрограммиз ПЗУ. Поскольку при вызове подпрограмм обязательно используется стековая память, то должен быть корректно определен указатель стека SP; программа начинает работу с установки указателя стека.

Программа 135

0000 0E6D 26 => SP установка указателя стека

0002 0026

0004 9C0D вызов п/п 40FE ввод символа (без эхо-печати!)

0006 40FE

0008 0101 R0 => Rl сохранить введенный символ

000A 07D0 DF and R0 => R0 сделать букву заглавной

000C 00DF

000E 9C0D вызов п/п 4088 вывести результат

0010 4088

0012 0F00 останов

Пример 3. Найти максимум из трех чисел, находящихся в регистрах Rl, R2 и R3. Переписать наибольшее из них в R0.

Решение. Сначала максимальное из чисел в Rl и R2 занесем в R0. После этого, если R3 окажется больше R0, «исправим положение», переписав в качестве ответа R3.

Программа 136

0000 0412 сравнить R2 с Rl

0002 3D04 если < 0, то РС=РС+4 к записи Rl (к 0008)

0004 0120 R2 => R0 запомнить R2

0006 1D02 РС=РС+2 обход второй ветви (к 000A)

0008 0110 Rl => R0 запомнить Rl

000A 0403 сравнить R3 с R0

000C 3D02 если < 0, то РC=РС+2 к выходу (к 0010)

000E 0130 R3 => R0 запомнить R3

0010 0F00 останов

Пример 4. Найти сумму первых 100 натуральных чисел.

Говорят, такую задачу некогда решил в уме юный Гаусс, когда учился в школе. Мы будем решать задачу «в лоб», т.е. честно суммировть с помощью компьютера. Решение. Поместим в R3 обрабатываемое в данный момент число N (меняется от 1 до 100), а в R0 - результирующую сумму S. Зададим им начальные значения и будем циклически добавлять к S текущее значение N. Признаком окончания цикла будет ситуация, когда N >100.

Программа 137

0000 2113 1 => R3 1 => N

0002 2100 0 => R0 0 => S

0С04 0230 R0 + R3 => R0 S = S + N

0006 2213 R3 + 1 => R3 N=N+1

0008 04D3 сравнить R3 с 100 сравнить N и 100

000A 0064

000C 6DF6 если ≤0, то PC=PC+F6 если N≤100,

к повторению (000E + FFF6 = 0004)

000E 0F00 останов

Пример 5. Вывести на экран весь латинский алфавит от А до Z. Решение. Разместим в RO выводимый латинский символ, первоначальное значение которого будет «А» (код 65 = 41h). Вывод будем осуществлять обращением к соответствующей подпрограмме ПЗУ. Для перехода к следующему символу алфавита достаточно прибавить 1 к коду текущего символа (очень похоже на переход к следующему числу в предыдущем примере). Остается только проверить, не выходит ли вновь полученный символ за латинский алфавит, т.е. не превышает ли его код 5Ah («Z»), и, если ответ будет «да» (превышает), то закончить процедуру.

Программа 138

0000 0E6D 26 => SP установка указателя стека

0002 0026

0004 01D0 41 => R0 код первого символа

0006 0041 («А»)

0008 9C0D вызов п/п 4088 вывод символа

000А 4088

000С 2210 R0 + 1 => R0 следующий символ

000Е 04D0 сравнитьR0 с 5А его код ≤ «Z»?

0010 005А («Z»)

0012 6DF4 если ≤0, то PC=PC+F4 к повторению (0008)

0014 0F00 останов

Пример 6. В памяти, начиная с адреса 001А, хранится некоторый текст, длина которого равна 15 (Fh) байтам Определить номер первого, совпадающего с образцом, символа в тексте. При отсутствии требуемого символа результат равен 0 (это практически полный аналог функции POS в Паскале).

Решение Поместим в R1 счетчик символов, в R2 - адрес текущего символа. Затем будем сравнивать каждый символ текста с образцом в R0 и в случае совпадения прервем выполнение цикла. При несовпадении будем продолжать цикл до теx пор, пока счетчик не превысит Fh, т.е. не станет равным 10h Если цикл завершится по выполнении этого условия, то символ-образец найти не удалось и в качестве ответа в R1 следует занести 0.

Программа 139

0000 2111 1 => R1 номер символа

0002 01D2 1А => R2 адрес начала текста

0004 001А

0006 С460 сравнить R0b с (R2)b сравнить символ с образцом

0008 5D0C если = 0, то РC=РС+2 выход при совпадении (к 0016)

000А 2211 R1 + 1 => R1 увеличить номер символа

000С 2212 R2 + 1 => R2 вычислить следующий адрес

000Е 04D1 сравнить R1 с 10 текст не закончился?

0010 0010

0012 4DF2 если ≠ 0, то PC=PC+F4 нет - к повторению (к 0006)

0014 2101 0 => R1 при отсутствии символа - 0

0016 0F00 останов

0018 0000

001А 4854 «ТН» текст

001С 5349 «IS» «THIS IS MY TEXT»

001E 4920 «I»

0020 2053 «S »

0022 594D «MY»

0024 5420 «Т»

0026 5845 «EX»

0028 0054 «Т»

Наши рекомендации