П.2. Учебная двухадресная машина УМ-2.
Анализ большого числа программ показывает, что только 25% команд содержат три различных адреса. В остальных командах либо два, либо все три адреса совпадают. Этот факт наталкивает на идею отказаться от одного из адресов — сделать команды двухадресными. Тогда можно использовать освободившиеся разряды для задания более длинных адресов — появляется возможность адресовать бóльший объем памяти. Либо можно сократить размер ячейки, сделав более дешевой оперативную память.
Как избавиться от третьего адреса? В УМ-3 существенно трехадресными были арифметические команды и команды условного перехода.
а) Арифметические команды. Договоримся, что результат записывается на место первого операнда (по адресу А1).
б) Команды условного перехода. Можно разбить команду на две, выделив в отдельную команду действие сравнения.
1. Описание УМ-2.
Структура процессора та же, что и в УМ-3; разрядность регистров соответствует разрядности ячейки и объему ОП.
Ячейка ОП — 10 шестнадцатиричных разрядов.
Объем ОП — 164 ячеек.
Представление чисел. Число занимает одну ячейку. Отрицательные числа записываются в дополнительном коде.
Формат команд. Команда занимает одну ячейку:
-
КОП А1 А2
Система команд. Коды операций те же, что в УМ-3. Отличия заключаются в следующем.
Команды
|
Действие
|
Пересылка 00 А1 А2
|
[А1] := [А2]
|
Арифметические команды
|
[А1] := [А1] [А2], где {+, -, *}
|
Деление
|
вычисляет частное и остаток от деления [А1] на [А2]; частное записывается в [А1], остаток в [А1+1]
|
Сравнение 05 А1 А2
|
вычисляется [А1] - [А2], устанавливаются арифметические флаги; результат вычитания не сохраняется
|
Условные переходы
КОП А1 А2
|
переход по А2, если условие выполняется; А1 не используется
|
Остальные команды те же, что в УМ-3.
2. Рассмотрим два примера программ для УМ-2.
Пример 1. Вычислить значение x= ( a mod 50 - b )2 по заданным a и b.
Распределение памяти:
0000 a
0001 x
0002 3216 (=5010)
0003 b
Программа:
-
0100
|
04 0000 0002
|
x := a mod 50
|
0101
|
02 0001 0003
|
x := x - b
|
0102
|
03 0001 0001
|
x := x * x
|
0103
|
99 0000 0000
|
стоп
|
Пример 2. Вычислить p = n!.
Алгоритм:
begin p:=1; k:=2;
while k n do
begin p := p * k;
k := k + 1
end
end.
Распределение памяти:
0000 1
0001 2
0002 n
0003 p
0004 k.
Программа:
-
0100
|
00 0003 0000
|
p := 1
|
0101
|
00 0004 0001
|
k := 2
|
0102
|
05 0004 0002
|
k n ?
|
0103
|
95 0000 0107
|
k > n, go to 0107
|
0104
|
13 0003 0004
|
p := p * k
|
0105
|
01 0004 0000
|
k := k + 1
|
0106
|
80 0000 0102
|
go to 0102
|
0107
|
99 0000 0000
|
стоп
|
П.3. Учебная машина с регистрами УМ-Р.
Вспомним, как выполняется арифметическая команда. Процессор обращается к ОП для получения операндов и для записи результата. Поскольку ОП внешнее по отношению к ЦП устройство, на это взаимодействие затрачивается бóльшая часть времени выполнения команды. Кроме того, часто оказывается, что результат, полученный ЦП в предыдущей команде, требуется в качестве операнда для выполнения следующей команды. Принимая во внимание эти обстоятельства, имеет смысл включить в ЦП несколько ячеек памяти. Так как этих ячеек будет немного, можно сделать их более быстродействующими (и, видимо, более дорогими), чем ячейки ОП. Такие ячейки, расположенные в ЦП, называются регистрами. Программист может использовать эти регистры по своему желанию для хранения информации, в отличие от других регистров процессора. Поскольку регистров немного, для указания их в команде требуется меньше разрядов, чем для задания адресов ОП. Использование регистров позволяет сократить размер программ.
1. Описание УМ-Р.
Кроме обычных регистров, ЦП содержит 16 регистров общего назначения. Регистры нумеруются от 0 до F16. Размер регистров совпадает с разрядностью чисел.
Ячейка ОП состоит из четырех шестнадцатиричных разрядов.
Объем ОП — 165 ячеек.
Число занимает две соседние ячейки, отрицательные числа записываются в дополнительном коде.
Команды бывают двух типов.
а) Регистр-регистр. Занимает одну ячейку. Формат команды
-
КОП R1 R2,
где R1 — первый операнд, R2 — второй операнд.
б) Регистр-память. Занимает две ячейки. Формат команды
-
КОП R1 А2,
где R1 — первый операнд, A2 — адрес второго операнда.
Система команд следующая:
Название
|
КОП
|
Регистр-память
|
КОП
|
Регистр-регистр
|
останов
|
|
|
99
|
стоп
|
пересылки
|
00
|
R1:=(A2,A2+1)
|
20
|
R1:=R2
|
|
10
|
R1(A2,A2+1)
|
|
|
|
|
арифметические
|
|
|
сложение
|
01
|
R1:=R1+(А2,A2+1)
|
21
|
R1:=R1+R2
|
вычитание
|
02
|
R1:=R1-(А2,A2+1)
|
22
|
R1:=R1-R2
|
умножение
|
|
|
|
|
со знаком
|
03
|
R1:=R1*(А2,A2+1)
|
23
|
R1:=R1*R2
|
без знака
|
13
|
|
33
|
|
деление
|
|
|
|
|
со знаком
|
04
|
R1:=R1 div (А2,A2+1), (R1+1):=R1 mod (А2,A2+1)
|
24
|
R1:=R1 div R2,
(R1+1):=R1 mod R2
|
без знака
|
14
|
|
34
|
|
сравнение
|
05
|
R1-(А2,A2+1)
|
25
|
R1-R2
|
переходы по А2 (типа регистр-память)(R1- любой)
|
безусловный
|
80
|
|
|
|
по =
|
81
|
|
|
|
по
|
82
|
|
|
|
по
|
с/зн - 83
|
б/зн - 93
|
|
по
|
с/зн - 84
|
б/зн - 94
|
|
по
|
с/зн - 85
|
б/зн - 95
|
|
по
|
с/зн - 86
|
б/зн - 96
|
|
2. Примеры.
Для удобства чтения программы будем записывать, располагая по одной команде на строке. Тот факт, что команды имеют разную длину, будем учитывать при подсчете адресов команд.
Пример 1. Вычислить значение x= ( a mod 50 - b )2 по заданным a и b.
Распределение памяти:
00000 a
00002 b
00004 3216 (=5010)
00006 x
Программа:
-
00100
|
00 0 00000
|
R0 := a
|
|
00102
|
04 0 00004
|
R1 := a mod 50
|
00104
|
02 1 00002
|
R1 := R1 - b
|
|
00106
|
23 1 1
|
R1 := R1 *R1
|
|
00107
|
10 1 00006
|
x := R1
|
|
00109
|
99 0 0
|
стоп
|
|
Пример 2. Вычислить
S1 = max(a,b) * 20,
S2 = min(a,b) div 3.
Алгоритм:
begin S1 := a; S2 := b;
if a > b then begin S1 := b; S2 := a end;
S1 := S1 * 20;
S2 := S2 div 3
end.
Данные:
00000 a
00002 b
00004 1416 (=2010)
00006 3
00008 S1
0000A S2
Значение S1 будем вычислять в регистре R1, значение S2 — в регистре R0 .
Программа:
-
00100
|
00 0 00000
|
R0 := a
|
00102
|
00 1 00002
|
R1 := b
|
00104
|
25 0 1
|
R0 > R1?
|
00105
|
96 0 0010A
|
R0 R1 go to 10A
|
00107
|
20 2 0
|
|
00108
|
20 0 1
|
|
00109
|
20 1 2
|
R0 R1
|
0010A
|
13 1 00004
|
R1 := R1 * 20
|
0010С
|
10 1 00008
|
S1 := R1
|
0010E
|
14 0 00006
|
R0 := R0 div 3
|
00110
|
10 0 0000A
|
S2 := R0
|
00112
|
99 0 0
|
стоп
|
Пример 3. Вычислить p = n!.
Напомним алгоритм:
begin p:=1; k:=2;
while k n do
begin p := p * k;
k := k + 1
end
end.
Распределение памяти:
00000 1
00002 2
00004 n
00006 p
Для ускорения работы цикла будем использовать регистры R1 1, R2 n, R3 k, R4 p.
Программа:
-
00100
|
00 1 00000
|
R1 := 1
|
00102
|
00 2 00004
|
R2 := n
|
00104
|
20 4 1
|
p := 1
|
00105
|
00 3 00002
|
k := 2
|
00107
|
25 3 2
|
k n?
|
00108
|
95 0 0010E
|
k > n, go to 0010E
|
0010A
|
33 4 3
|
p := p * k
|
0010B
|
21 3 1
|
k := k + 1
|
0010C
|
80 0 00107
|
go to 0107
|
0010E
|
10 4 00006
|
сохранили p
|
00110
|
99 0 0
|
стоп
|
По сравнению с программой для УМ-2, потребовалась подготовительная работа по записи начальных значений в регистры (загрузка регистров). Однако основной цикл выглядит очень коротким, да и весь текст программы сократился (если считать длину в шестнадцатиричных разрядах, а не в ячейках).
Пример 4. Вычислить сумму элементов массива x1, ..., x20..
S = x1 + x2 +...+ x20
Алгоритм:
begin S := 0; i := 1;
repeat S := S + x[i];
i := i + 1
until i = 21
end.
Распределение памяти:
|
Используемые регистры:
|
00000 x1
|
R0 0
|
00002 x2
|
R1 1
|
* * *
|
R2 2
|
00026 x20
|
R3 21
|
00028 S
|
R4 i
|
0002A 0
|
R5 S
|
0002C 1
|
R6 , R7 вспомогательные
|
0002E 1516 (=2110)
|
|
00030 2
|
|
Программа:
-
00100
|
00 0 0002A
|
R0 := 0
|
загрузка
|
00102
|
00 1 0002C
|
R1 := 1
|
константных
|
00104
|
00 2 00030
|
R2 := 2
|
регистров
|
00106
|
00 3 0002E
|
R3 := 21
|
|
00108
|
00 6 0010D
|
R6 := [0010D]
|
|
0010A
|
20 7 6
|
R7 := R6
|
|
0010B
|
20 5 0
|
S := 0
|
|
0010C
|
20 4 1
|
i := 1
|
|
0010D
|
01 5 00000
|
S := S + x [1]
|
|
0010F
|
21 6 2
|
подготовка программы к обработке
|
|
00110
|
10 6 0010D
|
следующего элемента массива
|
|
00112
|
21 4 1
|
i := i + 1
|
|
00113
|
25 4 3
|
i = 21?
|
|
00114
|
82 0 0010D
|
i 21, go to 0010D
|
|
00116
|
10 5 00028
|
сохранили S
|
|
00118
|
10 7 0010D
|
восстановили первоначальный вариант команды 0010D
|
|
0011A
|
99 0 0
|
стоп
|
|
При решении данной задачи возникла проблема: как добиться того, чтобы в разные моменты работы программы к S прибавлялись различные элементы массива? По сути, требуется, чтобы во время работы программы менялся адрес второго операнда в команде 0010D: 01 5 00000 (S := S + x[1]). Мы сделали это так. Регистр R6 содержит копию команды 0010D. Когда команда 0010D выполнится, прибавим к R6 число 2 (адреса соседних элементов массива отличаются на 2) и запишем новую команду из R6 в программу по адресу 0010D. Таким образом, на следующем шаге цикла будет выполнена другая команда 0010D: 01 5 00002 (S := S + x[2]). это изменение текста программы производится командами 0010F, 00110. Команда 00118 восстанавливает первоначальный вариант команды 0010D. Если этого не сделать, после окончания работы программы команда 0010D будет содержать адрес ячейки, следующей за последним элементом массива x. При этом повторный запуск программы приведет к неверным результатам.
Мы встретились в этом примере с программой, которая изменяет свой текст во время работы. Такие программы называются самомодифицирующимися. Их применение довольно опасно из-за непредсказуемых последствий возможных ошибок в изменении команд.
Достарыңызбен бөлісу: |