Ремонт принтеров, сканнеров, факсов и остальной офисной техники


назад Оглавление вперед




[148]

(controller test-b

(test (op =) (reg b) (const 0))

(branch (label gcd-done))

(assign t (reg a)) rem-loop

(test (op <) (reg t) (reg b))

(branch (label rem-done))

(assign t (op -) (reg t) (reg b))

(goto (label rem-loop)) rem-done

(assign a (reg b))

(assign b (reg t)) (goto (label test-b)) gcd-done)

Рис. 5.6: Последовательность команд контроллера машины НОД с рисунка 5.5.

Было бы лучше заменить эти две последовательности переходами к единой последовательности - подпрограмме (subroutine), - в конце которой мы возвращаемся обратно к нужному месту в основной последовательности команд. Этого можно добиться так: прежде, чем перейти к gcd, мы помещаем определенное значение (0 или 1) в особый регистр, continue. В конце подпрограммы gcd мы переходим либо к after-gcd-1, либо к after-gcd-2, в зависимости от значения из регистра continue. На рисунке 5.9 показан соответствующий сегмент получающейся последовательности команд контроллера, который содержит только одну копию команд gcd.

Для маленьких задач это разумный подход, однако если бы в последовательности команд контроллера имелось много вызовов вычисления НОД, он стал бы неудобен. Чтобы решить, где продолжать вычисление после подпрограммы gcd, нам пришлось бы иметь в контроллере тесты и переходы для всех мест, где используется gcd. Более мощный метод реализации подпрограмм состоит в том, чтобы запоминать в регистре continue метку точки входа в последовательности контроллера, с которой выполнение должно продолжиться, когда подпрограмма закончится. Реализация этой стратегии требует нового вида связи между путями данных и контроллером регистровой машины: должно быть возможно присвоить регистру метку в последовательности команд контроллера таким образом, чтобы это значение можно было из регистра извлечь и с его помощью продолжить выполнение с указанной точки входа.

Чтобы отразить эту возможность, мы расширим команду assign языка регистровых машин и позволим присваивать регистру в качестве значения метку из последовательности команд контроллера (как особого рода константу). Кроме того, мы расширим команду goto и позволим вычислению продолжаться с точки входа, которая описывается содержимым регистра, а не только с точки входа, описываемой меткой-константой. С помощью этих двух команд мы можем завершить подпрограмму gcd переходом в место, хранимое в регистре continue. Это ведет к последовательности команд, показанной на рисунке 5.10.

Машина, в которой имеется более одной подпрограммы, могла бы исполь-


a <-b

b

ю

rem

t <-r

b <-t

Н8ъ

c <-d

i

rem

s <-r

d <-t

gcd-1

(test (op =) (reg b) (const 0)) (branch (label after-gcd-1)) (assign t (op rem) (reg a) (reg b)) (assign a (reg b)) (assign b (reg t)) (goto (label gcd-1)) after gcd-2

gcd-2

(test (op =) (reg d) (const 0)) (branch (label after-gcd-2)) (assign s (op rem) (reg c) (reg d)) (assign c (reg d)) (assign d (reg s))

(goto (label gcd-2))

after-gcd-2

d

c

a

0

0

t

s

Рис. 5.7: Части путей данных и последовательностей команд контроллера для машины с двумя вычислениями НОД.


gcd-1

(test (op *) (reg b) (const 0)) (branch (label after-gcd-1)) (assign t (op rem) (reg a) (reg b)) (assign a (reg b)) (assign b (reg t)) after-gcd-2

gcd-1

(test (op =) (reg b) (const 0)) (branch (label after-gcd-2)) (assign t (op rem) (reg a) (reg b)) (assign a (reg b)) (assign b (reg t))

(goto (label gcd-2))

after-gcd-2

Рис. 5.8: Сегменты последовательности команд контроллера для машины, которая использует одни и те же компоненты путей данных для двух различных вычислений НОД.

зовать различные регистры продолжения (например, gcd-continue, factorial-continue), или же мы могли бы для всех подпрограмм использовать один регистр continue. Разделение регистра экономичнее, однако тогда требуется отслеживать случаи, когда из одной подпрограммы (sub1) зовется другая (sub2). Если sub1 не сохранит значение continue в каком-то другом регистре, прежде чем использовать continue при вызове sub2, то sub1 не будет знать, откуда продолжать выполнение после ее конца. Механизм, который разрабатывается в следующем разделе для работы с рекурсией, дает хорошее решение и для проблемы с вложенными вызовами подпрограмм.

5.1.4 Реализация рекурсии с помощью стека

При помощи описанных до сих пор механизмов мы можем реализовать любой итеративный процесс, задав регистровую машину, в которой имеется по регистру на каждую переменную состояния процесса. Машина выполняет цикл контроллера, изменяя при этом состояние регистров, до тех пор, пока не окажется выполнено некоторое условие окончания процесса. В каждой точке последовательности команд контроллера состояние машины (представляющее состояние итеративного процесса) полностью определяется состоянием регистров (значением переменных состояния).

Однако реализация рекурсивных процессов требует дополнительного механизма. Рассмотрим следующий рекурсивный метод вычисления факториала, описанный нами в разделе 1.2.1:

(define (factorial n)

(if (= n 1) 1



[стр.Начало] [стр.1] [стр.2] [стр.3] [стр.4] [стр.5] [стр.6] [стр.7] [стр.8] [стр.9] [стр.10] [стр.11] [стр.12] [стр.13] [стр.14] [стр.15] [стр.16] [стр.17] [стр.18] [стр.19] [стр.20] [стр.21] [стр.22] [стр.23] [стр.24] [стр.25] [стр.26] [стр.27] [стр.28] [стр.29] [стр.30] [стр.31] [стр.32] [стр.33] [стр.34] [стр.35] [стр.36] [стр.37] [стр.38] [стр.39] [стр.40] [стр.41] [стр.42] [стр.43] [стр.44] [стр.45] [стр.46] [стр.47] [стр.48] [стр.49] [стр.50] [стр.51] [стр.52] [стр.53] [стр.54] [стр.55] [стр.56] [стр.57] [стр.58] [стр.59] [стр.60] [стр.61] [стр.62] [стр.63] [стр.64] [стр.65] [стр.66] [стр.67] [стр.68] [стр.69] [стр.70] [стр.71] [стр.72] [стр.73] [стр.74] [стр.75] [стр.76] [стр.77] [стр.78] [стр.79] [стр.80] [стр.81] [стр.82] [стр.83] [стр.84] [стр.85] [стр.86] [стр.87] [стр.88] [стр.89] [стр.90] [стр.91] [стр.92] [стр.93] [стр.94] [стр.95] [стр.96] [стр.97] [стр.98] [стр.99] [стр.100] [стр.101] [стр.102] [стр.103] [стр.104] [стр.105] [стр.106] [стр.107] [стр.108] [стр.109] [стр.110] [стр.111] [стр.112] [стр.113] [стр.114] [стр.115] [стр.116] [стр.117] [стр.118] [стр.119] [стр.120] [стр.121] [стр.122] [стр.123] [стр.124] [стр.125] [стр.126] [стр.127] [стр.128] [стр.129] [стр.130] [стр.131] [стр.132] [стр.133] [стр.134] [стр.135] [стр.136] [стр.137] [стр.138] [стр.139] [стр.140] [стр.141] [стр.142] [стр.143] [стр.144] [стр.145] [стр.146] [стр.147] [стр.148] [стр.149] [стр.150] [стр.151] [стр.152] [стр.153] [стр.154] [стр.155] [стр.156] [стр.157] [стр.158] [стр.159] [стр.160] [стр.161] [стр.162] [стр.163] [стр.164] [стр.165] [стр.166] [стр.167] [стр.168] [стр.169] [стр.170] [стр.171] [стр.172] [стр.173] [стр.174] [стр.175] [стр.176] [стр.177] [стр.178] [стр.179] [стр.180] [стр.181] [стр.182] [стр.183] [стр.184] [стр.185] [стр.186] [стр.187] [стр.188] [стр.189] [стр.190] [стр.191] [стр.192] [стр.193] [стр.194] [стр.195] [стр.196]