We will often define a machine to include “primitive” operations that are
actually very complex. For example, in 5.4 and 5.5 we
will treat Scheme’s environment manipulations as primitive. Such abstraction
is valuable because it allows us to ignore the details of parts of a machine so
that we can concentrate on other aspects of the design. The fact that we have
swept a lot of complexity under the rug, however, does not mean that a machine
design is unrealistic. We can always replace the complex “primitives” by
simpler primitive operations.
我们经常会将机器定义为包含一些"基本"操作,而这些操作实际上相当复杂。例如,在 5.4 节和 5.5 节中,我们将把 Scheme 的环境操作视为基本操作。这种抽象很有价值,因为它允许我们忽略机器某些部分的细节,从而将注意力集中到设计的其他方面。然而,将大量复杂性隐藏起来,并不意味着机器设计是不切实际的。我们始终可以用更简单的基本操作来替换那些复杂的"基本元素"。
Consider the GCD machine. The machine has an instruction that
computes the remainder of the contents of registers a and b and
assigns the result to register t. If we want to construct the
GCD machine without using a primitive remainder operation, we must
specify how to compute remainders in terms of simpler operations, such as
subtraction. Indeed, we can write a Scheme procedure that finds remainders in
this way:
考虑 GCD 机器。该机器有一条指令,用于计算寄存器 a 和 b 的内容的余数,并将结果赋给寄存器 t。如果我们希望在不使用基本余数操作的情况下构造 GCD 机器,就必须用更简单的操作(如减法)来说明如何计算余数。实际上,我们可以写出一个按此方法求余数的 Scheme 过程:
We can thus replace the remainder operation in the GCD machine’s data
paths with a subtraction operation and a comparison test. Figure 5.5
shows the data paths and controller for the elaborated machine. The
instruction
这样,我们便可以用一个减法操作和一个比较检测来替换 GCD 机器数据通路中的余数操作。图 5.5 展示了这台经过细化的机器的数据通路和控制器。其中的指令
in the GCD controller definition is replaced by a sequence of
instructions that contains a loop, as shown in Figure 5.6.
Figure 5.5: Data paths and controller for the elaborated GCD machine.
在 GCD 控制器定义中,被替换为一段包含循环的指令序列,如图 5.6 所示。图 5.5:细化后的 GCD 机器的数据通路和控制器。
Figure 5.6: ↓ Controller instruction sequence for the
GCD machine in Figure 5.5.
图 5.6:↓ 图 5.5 中 GCD 机器的控制器指令序列。
(define (remainder n d)
(if ( n d) n (remainder (- n d) d))) (assign t (op rem) (reg a) (reg b)) (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)