Из сборника Введение в информатику. Лабораторные работы. Ч. II / Авт.-сост. А.П. Шестаков; Перм. ун-т. Пермь, 1999. 71 с.
Удобным способом выполнения действия с константой, значение которой не превышает по абсолютной величине 15(10) (F(16)), является операция с короткой константой. В этом случае место первого операнда (ОП1) в двухадресной команде занимает модуль константы. На знак константы указывает модификатор. Если его значение 2(16), то константа положительная; 3(16) отрицательная. Указанный способ оказывается экономичнее рассмотренного ранее способа адресации по PC, т.к. команда в этом случае занимает одно слово вместо двух.
Например, команда "переслать по адресу, записанному в регистре R0, число 3"
0020 01D4 0022 0003может быть заменена на такую 0020 2134, которая выполняет то же самое действие.
Решим задачу из данной лабораторной работы с использованием того же алгоритма и с тем же распределением памяти, только вместо адресации по PC, где возможно, будем использовать действие с короткой константой.
Пример. Поменять местами первый отрицательный элемент массива и его максимальный элемент.
Программа
Адрес Команда Действие Замечания 0000 2125 2 => (R1) i := 2 0002 0103 R0 => R3 адрес максимального элемента 0004 2221 R1 := R1 + 2 адрес otr 0006 2105 0 => (R1) otr := 0 0008 2404 сравнить a[1] с 0 (R0) - 0 000A 2D04 если a[1]>=0, переход на 4 байта 000C 0106 R0 => (R2) адрес 1-го отриц. элемента 000E 2115 1 => (R1) otr := 1 0010 2222 R2 := R2 + 2 адрес n 0012 2321 R1 := R1 - 2 адрес i 0014 2220 R0 := R0 + 2 адрес 2-го элемента массива 0016 0456 сравнить (R1) с (R2) (i с n) (R2) - (R1) 0018 3D20 если <0, переход на 20 байт переход на обмен значений 001A 2221 R1 := R1 + 2 адрес otr 001C 2404 сравнить (R0) c 0 (R0) - 0 001E 2D0C если >= 0, переход на C байт 0020 2405 сравнить (R1) c 0 (R1) - 0 0022 4D08 если <>0, переход на 8 байт 0024 2322 R2 := R2 - 2 адрес k 0026 0106 R0 => (R2) адрес 1-го отриц. элемента 0028 2115 1 => (R1) otr := 1 002A 2222 R2 := R2 + 2 адрес n 002C 0447 ср. (R0) с (R3) (a[i] c a[max]) (R3) - (R0) 002E 2D02 если >=0, переход на 2 байта если a[max]>=a[i] 0030 0103 R0 => R3 адрес максимального элемента 0032 2321 R1 := R1 - 2 адрес i 0034 2215 (R1) := (R1) + 1 i:= i + 1 0036 2220 R0 := R0 + 2 адрес i-го элемента 0038 1DDC переход на -24 байт на сравнение i с n 003A 2322 R2 := R2 - 2 адрес k 003C 0162 (R2) => R2 003E 0161 (R2) => R1 vsp := a[k] 0040 0176 (R3) => (R2) a[k] := a[max] 0042 0117 R1 => (R3) a[max] := a[k] 0044 0F00 стоп
Как видно, в этом случае программа значительно сократилась.
Автор E97 реализовал достаточно много полезных подпрограмм, которые размещаются в ПЗУ. Напомним, что ПЗУ начинается с адреса 4000(16). Среди этих программ особо стоит выделить те, которые позволяют работать с клавиатурой и дисплеем, т.е. организовывать ввод-вывод данных.
Перечислим их.
Рассмотрим пример, где организуется ввод данных с клавиатуры и результат выводится на экран.
Пример. Вычислить значение выражения u=x3y-y2z+12xyz, организовав ввод данных с клавиатуры и вывод результатов на экран.
При решении необходимо позаботиться о распределении памяти с оглядкой на то, что некоторые регистры, а также часть ОЗУ используется подпрограммами ввода-вывода.
План решения
1. Ввод x, y, z. 6. S := yz. 2. P := x2. 7. R := R - S. 3. R := 12z. 8. U := yR. 4. R := P + R. 9. Вывод U. 5. R := Rx. 10. Стоп.
Распределение памяти. Значения x, y, z после ввода разместим в памяти по последовательным адресам 80-84(16). Регистры R1, R2 будем использовать для хранения величин P, R, S. Значение U получим в R1. Кроме того, некоторые регистры будут использованы стандартными подпрограммами (см. выше). Указатель стека установим для удобства на последний адрес ОЗУ FE(16).
Тесты
Программа
Адрес Команда Действие Замечания 0000 0E6D FE => SP установка SP 0002 00FE 0004 01D0 80 => R0 адрес x 0006 0080 0008 9C0D вызов п/п 000A 40DC вывода текста 000C 7802 текст "x?" 2 - длина текста 000E 003F 0010 9C0D вызов п/п 0012 4108 ввода целого числа 0014 0114 R1 => (R0) сохраняем x 0016 2220 R0 := R0 + 2 адрес y 0018 9C0D вызов п/п 001A 40DC вывода текста 001C 7902 текст "y?" 2 - длина текста 001E 003F 0020 9C0D вызов п/п 0022 4108 ввода целого числа 0024 0114 R1 => (R0) сохраняем y 0026 2220 R0 := R0 + 2 адрес z 0028 9C0D вызов п/п 002A 40DC вывода текста 002C 7A02 текст "z?" 2 - длина текста 002E 003F 0030 9C0D вызов п/п 0032 4108 ввода целого числа 0034 0114 R1 => (R0) сохраняем z 0036 3240 R0 := R0 - 4 адрес x 0038 0142 (R0) => R2 x => R2 003A 0522 R2 := R2 * R2 P := x2 003C 2240 R0 := R0 + 4 адрес z 003E 0141 (R0) => R1 z => R1 0040 25C1 R1 := R1 * 12 R := 12z 0042 0221 R1 := R1 + R2 R := R + P 0044 3240 R0 := R0 + (-4) адрес x 0046 0541 R1 := R1 * (R0) R := Rx 0048 2220 R0 := R0 + 2 адрес y 004A 0142 (R0) => R2 004C 2220 R0 := R0 + 2 адрес z 004E 0542 R2 := R2 * (R0) S := yz 0050 0321 R1 := R1 - R2 R := R - S 0052 3220 R0 := R0 + (-2) адрес y 0054 0541 R1 := R1 * (R0) U := Ry 0056 9C0D вызов п/п 0058 40DC вывода текста 005A 7502 текст "u=" 2 - длина текста 005C 003D 005E 01D3 в R3 помещаем используется 0060 0090 адрес 90 в п/п 0062 9C0D п/п вывода 0064 4068 целого числа 0066 0F00 стоп
В E97 используются команды для работы не только с машинными словами, но и отдельными байтами. Рассмотрим некоторые из них на примере программы обработки текста.
Пример. Составить программу, которая определяет количество заглавных русских букв в заданном тексте и выводит результат на экран.
Пусть текст находится в ОЗУ. Будем считать, что текст закончился, если встретится код 00(16). Примем во внимание, что диапазон кодов заглавных русских букв 80(16)-9F(16).
План решения
1. S := 0. 2. Сравнить код символа с 00(16). 3. Если равен, переход к п. 7. 4. Если код символа больше 7F(16), но меньше A0(16), то S := S + 1. 5. Перейти к следующему символу. 6. Переход к п. 2. 7. Вывод S. 8. Стоп.
Распределение памяти
R0 | R1 | R2 | R3 |
адрес символа | S | | |
Тест. Текст: НА ШАХМАТНОЙ доске 64 КЛЕТКИ. S = 17.
Программа
Адрес Команда Действие Замечания 0000 2101 0 => R1 S := 0 0002 C44D сравнить (R0)b не встретили ли 0004 0000 с (0)b символ с кодом 0 0006 5D12 если =0, переход на 12(16) байт 0008 C44D сравнить (R0)b с (7F)b 7F - (R0) 000A 007F 000C 2D08 если >=0, переход на 8(16) байт 000E C44D сравнить (R0)b с (A0)b A0 - (R0) 0010 00A0 0012 6D02 если <=0, переход на 2(16) байта 0014 2211 R1 := R1 + 1 S := S + 1 0016 2210 R0 := R0 + 1 к следующему символу 0018 1DE8 переход к адресу 0002 001A 0111 001C 9C0D вызов п/п 001E 40DC вывода последующего текста 0020 AE06 текст из 6 символов 0022 A2E2 "ответ:" 0024 E2A5 0026 003A 0028 01D3 в R3 помещаем используется 002A 0090 адрес 90 в п/п 002C 9C0D п/п вывода 002E 4068 целого числа 0030 0F00 стоп
Следующий пример иллюстрирует работу с логическими выражениями, командами Е97, выполняющими логические операции.
Пример. Построить таблицу истинности для логического выражения (A or B) and C. Результаты вывести на экран.
Для решения задачи организуем цикл по каждой из переменных A, B, C. Результат обозначим D. Для дальнейших действие закодируем значение ИСТИНА (TRUE) с помощью числа -1 (FFFF), ЛОЖЬ (FALSE) с помощью числа 0 (0000) (такой способ кодирования применяется, например, в языке BASIC). Для простоты будем хранить логическое значение не с помощью одного байта, как это реализовано в тех или иных языках программирования, а займем под него машинное слово. Получив очередное значение D, будем печатать A, B, C, D.
План решения
1. A := -1. 11. D := K and C. 2. Сравнить A с 0. 12. Вывод A, B, C, D. 3. Если A > 0, переход к п. 19. 13. C := C + 1. 4. B := -1. 14. переход к п. 9. 5. Сравнить B с 0. 15. B := B + 1. 6. Если B > 0, переход к п. 17. 16. переход к п. 4. 7. K := A or B. 17. A := A + 1. 8. C := -1. 18. переход к п. 2. 9. Сравнить C с 0. 19. Стоп. 10. Если C > 0, переход к п. 15.
Распределение памяти. В регистр R0 поместим адрес переменных A, B, C (перед запуском программы зададим там адрес величины A). В регистре R1 величина D; R2 K. Кроме того, регистры используются стандартными подпрограммами; перед переходом на подпрограммы будем сохранять содержимое регистров в стеке, восстанавливая его в последствии.
Результатом работы программы будет следующая таблица
A B C D TRUE TRUE TRUE TRUE TRUE TRUE FALSE FALSE TRUE FALSE TRUE TRUE TRUE FALSE FALSE FALSE FALSE TRUE TRUE TRUE FALSE TRUE FALSE FALSE FALSE FALSE TRUE FALSE FALSE FALSE FALSE FALSE
Программа
Адрес Команда Действие Замечания 0000 0E6D FE => SP установка SP 0002 00FE 0004 01D4 -1 => (R0) A := -1 0006 FFFF 0008 2404 сравнить (R0) с 0 (A - 0) 000A 7D56 если >0, переход на стоп 000C 2220 R0 + 2 => R0 адрес B 000E 01D4 -1=> (R0) B := -1 0010 FFFF 0012 2404 сравнить (R0) с 0 (B - 0) 0014 7D46 если >0, переход на A:=A+1 0016 0142 (R0) => R2 B => R2 0018 3220 R0 -2=> R0 адрес A 001A 0842 (R0) or R2 => R2 K := A or B 001C 2240 R0 + 4 => R0 адрес C 001E 01D4 -1=> (R0) C := -1 0020 FFFF 0022 2404 сравнить (R0) с 0 (C - 0) 0024 7D30 если >0, переход на B:=B+1 0026 0141 (R0) => R1 C => R2 0028 0721 R2 and R1 => R1 D := K and C 002A 0E22 R2 => стек K => стек 002C 0E21 R1 => стек D => стек 002E 3240 R0 - 4 => R0 адрес A 0030 0141 (R0) => R1 A => R1 0032 9C0D п/п вывода значения 0034 0090 логической константы 0036 2220 R0 + 2 => R0 адрес B 0038 0141 (R0) => R1 B => R1 003A 9C0D п/п вывода значения 003C 0090 логической константы 003E 2220 R0 + 2 => R0 адрес C 0040 0141 (R0) => R1 C => R1 0042 9C0D п/п вывода значения 0044 0090 логической константы 0046 0E31 стек => R1 D => R1 0048 9C0D п/п вывода значения 004A 0090 логической константы 004C 9C0D п/п перевода строки 004E 40EC 0050 0E32 стек => R2 K => R2 0052 2214 (R0) + 1 => (R0) C := C + 1 0054 1DCC переход к сравнению C с 0 0056 3220 R0 -2=> R0 адрес B 0058 2214 (R0) + 1 => (R0) B := B + 1 005A 1DB6 переход к сравнению B с 0 005C 3220 R0 -2=> R0 адрес A 005E 2214 (R0) + 1 => (R0) A := A + 1 0060 1DA6 переход к сравнению A с 0 0062 0F00 стоп
С адреса 0090 разместим измененный вариант авторской подпрограммы вывода значения логической константы. Изменения связаны с тем, что, во-первых, рассмотренной программе логическая константа кодируется 2 байтами, во-вторых, для получения таблицы в подпрограмме выводятся в каждом случае 6 символов: TRUE дополняется двумя пробелами, FALSE одним.
Адрес Команда Действие Замечания 0090 2401 сравнить R1 c 0 R1 - 0 0092 5D0E если 0, переход к выводу FALSE 0094 9C0D п/п вывода 0096 40DC следующего далее текста 0098 5406 количество символов 6; 009A 5552 текст TRUE 009C 2045 009E 0020 00A0 1D0C переход к возврату из п/п 00A2 9C0D п/п вывода 00A4 40DC следующего далее текста 00A6 4606 количество символов 6; 00A8 4C41 текст FALSE 00AA 4553 00AC 0020 00AE 0D00 возврат из п/п
В нескольких предыдущих программах были использованы одноадресные команды. В этом случае код операции есть E, и поскольку операнд всего один, то место одного из операндов (в двухадресных командах это ОП1) занимает дополнительный код операции. За счет этого появляется 12 одноадресных команд. Например, были использованы команды E2 (пересылка операнда в стек), E3 (возвращение операнда из стека), E6 (помещение операнда в регистр SP установка указателя стека). Полный список команд представлен в руководстве от автора E97.
I. Ввести значения переменных с клавиатуры, вычислить значение выражения и результат вывести на экран:
II. Задания на обработку текста.
III. Составить программу, которая позволят построить таблицу истинности для заданного логического выражения и вывести ее на экран. Проверить результаты работы программы с помощью составления таблицы истинности. Примечание. Логическое значение ИСТИНА (TRUE) можно закодировать кодом FFFF, а ЛОЖЬ (FALSE) кодом 0000. Возможны и другие варианты кодировки.
1. (X and Y) or (Z and X) 9. (X or Y) and not Z 2. not(X or Y or Z) 10. not(X or Y) and Z 3. X and (not Y or Z) 11. X or not(Y and Z) 4. not(X and Y) or Z 12. not(X and Y or Z) 5. not(X and Y and Z) 13. not X and Y and Z 6. X and not Y and Z 14. X or not Y or Z 7. (X and Y) or not Z 15. (X and Z) or not Y 8. (X and Z) or (Y and Z) 16. (X and Y) xor (X and Z) 17. (X xor Y) or (X xor Z) 24. not X and (Y or Z) 18. not(X xor Y xor Z) 25. X xor Y and not Z 19. not X xor Y xor Z 26. X and not Y xor Z 20. (X or Y) xor not Z 27. X or not(Y xor Z) 21. X or Y or (X xor Z) 28. not X and (Y xor Z) 22. (X xor Y) or (Z and Z) 29. X xor (not Y or Z) 23. X and not(Y and Z) 30. X or not(Y xor Z)