ПРИМЕРЫ ПРОГРАММ
Пример 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 «Т»
4.6. НЕКОТОРЫЕ СПРАВОЧНЫЕ ДАННЫЕ ПО Е-97
А. Система команд процессора
МОД |
коп |
ОП1 |
ОП 2 |
Пояснения |
х |
0 |
X |
X |
Нет операции |
х |
1 |
X |
X |
оп l => oп 2 |
х |
2 |
X |
X |
oп 2 + oп 1 => oп 2 |
х |
3 |
X |
X |
oп 2 – oп l =>oп 2 |
х |
4 |
X |
X |
oп 2 + oп 1 (сравнить) |
х |
5 |
X |
X |
oп 2 * oп l => oп 2 |
х |
6 |
X |
X |
oп 2/oп l => oп 2 |
X |
7 |
х |
х |
оп 2 AND oп 1 => oп 2 |
X |
8 |
х |
х |
oп 2 OR oп l => оп 2 |
X |
9 |
х |
х |
oп 2 XOR oп l => oп 2 |
X |
А |
х |
х |
порт! => oп 2 |
X |
В |
х |
х |
oп 1 => порт 2 |
X |
С |
х |
х |
Переход по адресу |
X |
D |
X |
х |
Переход по смещению |
X |
Е |
* |
х |
(Одноадресные операции) |
X |
F |
X |
х |
Останов |
МОД |
коп |
ОП1 |
Пояснения |
х |
Е1 |
х |
NOT oп l |
х |
Е2 |
х |
оп 1 => стек |
х |
ЕЗ |
х |
стек => oп l |
х |
Е4 |
х |
SP + oп l => SP |
х |
Е5 |
х |
SP – oп 1 => SP |
х |
Е6 |
х |
Oп 1 => SP |
х |
Е7 |
х |
SP => oп l |
х |
Е8 |
0 |
PS => стек |
х |
Е9 |
0 |
стек => РS |
х |
ЕА |
X |
Сдвиг влево oп l |
х |
ЕВ |
X |
Сдвиг вправо oп l |
х |
ЕС |
X |
Арифметический сдвиг вправо oп l |
Б. Двоичные коды модификатора МОД для переходов
0000 - возврат из подпрограммы
0001 - безусловный переход
0010 - N=0 (>=0)
0011 - N=l (<0)
0100 - Z=0 (<>0)
0101 - Z=l (=0)
0110 - N=1 or Z=l (<=0)
0111 - N=0 and Z=0 (>0)
1001 - вызов подпрограммы.
В. Важные кочанды с «короткой константой»
XX 10 0001 0000 ХХХХ - очистить oп l
ХХ 10 0010 0001 ХХХХ - +1 в оп 1
XX 11 0010 0001 ХХХХ - ****
или
ХХ 10 0011 0001 ХХХХ - -1 из oп l
XX 10 0100 0000 ХХХХ - сравнить 0 с oп 1
XX 11 0101 0001 ХХХХ - *(-1) оп1
ХХ 10 0111 0001 ХХХХ - oп l MOD 2 = => oп l
Г. Кодирование операндов
0 |
0000 |
R0 |
1000 |
резерв |
|
1 |
01 |
R1 |
01 |
резерв |
|
2 |
10 |
R2 |
10 |
резерв |
|
3 |
11 |
R3 |
11 |
резерв |
|
4 |
0100 |
(R0) |
1100 |
резерв |
|
5 |
01 |
(R1) |
01 |
константа |
|
6 |
10 |
(R2) |
10 |
адрес ОЗУ |
|
7 |
11 |
(R3) |
11 |
резерв |