灯下 登录
计算机科学 / SICP / subsection 中英对照

5.2.1 The Machine Model

The machine model generated by make-machine is represented as a

procedure with local state using the message-passing techniques developed in

Chapter 3. To build this model, make-machine begins by calling

the procedure make-new-machine to construct the parts of the machine

model that are common to all register machines. This basic machine model

constructed by make-new-machine is essentially a container for some

registers and a stack, together with an execution mechanism that processes the

controller instructions one by one.

由 make-machine 生成的机器模型被表示为一个具有局部状态的过程,采用第 3 章中发展起来的消息传递技术。为了构造这个模型,make-machine 首先调用过程 make-new-machine,构造出所有寄存器机器共有的那些机器模型部件。make-new-machine 构造的这个基本机器模型本质上是若干寄存器和一个栈的容器,同时附有一个逐条处理控制器指令的执行机制。

Make-machine then extends this basic model (by sending it messages) to

include the registers, operations, and controller of the particular machine

being defined. First it allocates a register in the new machine for each of

the supplied register names and installs the designated operations in the

machine. Then it uses an

assembler (described below in

5.2.2) to transform the controller list into instructions for the new

machine and installs these as the machine’s instruction sequence.

Make-machine returns as its value the modified machine model.

make-machine 随后通过向该基本模型发送消息来扩展它,加入待定义机器所特有的寄存器、操作和控制器。它首先为每个提供的寄存器名称在新机器中分配一个寄存器,并将指定的操作安装到机器中;然后使用一个汇编器(在 5.2.2 节中描述)将控制器表转换为新机器的指令,并将这些指令作为机器的指令序列安装进去。make-machine 将修改后的机器模型作为其返回值。

Subheading: Registers

子标题:寄存器

We will represent a register as a procedure with local state, as in

Chapter 3. The procedure make-register creates a register that

holds a value that can be accessed or changed:

我们将把寄存器表示为一个具有局部状态的过程,如同第 3 章中所做的那样。过程 make-register 创建一个寄存器,该寄存器持有一个可被访问或修改的值:

The following procedures are used to access registers:

以下过程用于访问寄存器:

Subheading: The stack

子标题:栈

We can also represent a stack as a procedure with local state. The procedure

make-stack creates a stack whose local state consists of a list of the

items on the stack. A stack accepts requests to push an item onto the

stack, to pop the top item off the stack and return it, and to

initialize the stack to empty.

我们也可以将栈表示为一个具有局部状态的过程。过程 make-stack 创建一个栈,其局部状态由栈中各元素组成的表构成。栈接受三种请求:将一个元素压入栈顶、将栈顶元素弹出并返回,以及将栈初始化为空。

The following procedures are used to access stacks:

以下过程用于访问栈:

Subheading: The basic machine

子标题:基本机器

The make-new-machine procedure, shown in Figure 5.13,

constructs

an object whose local state consists of a stack, an initially empty instruction

sequence, a list of operations that initially contains an operation to

initialize the stack, and a

register table that initially contains

two registers, named flag and pc (for “program counter”). The

internal procedure allocate-register adds new entries to the register

table, and the internal procedure lookup-register looks up registers in

the table.

make-new-machine 过程如图 5.13 所示,它构造一个对象,其局部状态由以下部分组成:一个栈、一个初始为空的指令序列、一个初始包含栈初始化操作的操作列表,以及一个初始包含 flag 和 pc(“程序计数器”)两个寄存器的寄存器表。内部过程 allocate-register 向寄存器表中添加新条目,内部过程 lookup-register 在表中查找寄存器。

Figure 5.13: ↓ The make-new-machine

procedure, which implements the basic machine model.

图 5.13:↓ make-new-machine 过程,实现基本机器模型。

The flag register is used to control branching in the simulated machine.

Test instructions set the contents of flag to the result of the

test (true or false). Branch instructions decide whether or not to

branch by examining the contents of flag.

flag 寄存器用于控制被模拟机器中的分支。test 指令将 flag 的内容设置为测试的结果(真或假)。branch 指令通过检查 flag 的内容来决定是否跳转。

The pc register determines the sequencing of instructions as the machine

runs. This sequencing is implemented by the internal procedure execute.

In the simulation model, each machine instruction is a data structure that

includes a procedure of no arguments, called the

instruction execution procedure,

such that calling this procedure simulates executing the

instruction. As the simulation runs, pc points to the place in the

instruction sequence beginning with the next instruction to be executed.

Execute gets that instruction, executes it by calling the instruction

execution procedure, and repeats this cycle until there are no more

instructions to execute (i.e., until pc points to the end of the

instruction sequence).

pc 寄存器决定机器运行时的指令执行顺序。这种顺序控制由内部过程 execute 来实现。在模拟模型中,每条机器指令都是一个数据结构,其中包含一个无参数的过程,称为指令执行过程 (instruction execution procedure),调用该过程即模拟执行对应指令。模拟运行时,pc 指向指令序列中从下一条待执行指令开始的位置。execute 取出该指令,通过调用指令执行过程来执行它,然后重复此循环,直到没有更多指令可执行为止(即 pc 指向指令序列末尾)。

As part of its operation, each instruction execution procedure modifies

pc to indicate the next instruction to be executed. Branch and

goto instructions change pc to point to the new destination. All

other instructions simply advance pc, making it point to the next

instruction in the sequence. Observe that each call to execute calls

execute again, but this does not produce an infinite loop because

running the instruction execution procedure changes the contents of pc.

每个指令执行过程在运行过程中都会修改 pc,以指示下一条待执行的指令。branch 和 goto 指令将 pc 改为指向新的目标位置;所有其他指令则简单地将 pc 向前推进,使其指向序列中的下一条指令。注意,每次调用 execute 都会再次调用 execute,但这并不会产生无限循环,因为执行指令执行过程会改变 pc 的内容。

Make-new-machine returns a dispatch procedure that implements

message-passing access to the internal state. Notice that starting the machine

is accomplished by setting pc to the beginning of the instruction

sequence and calling execute.

make-new-machine 返回一个实现消息传递访问内部状态的分派过程。注意,启动机器是通过将 pc 设置为指令序列的起始位置并调用 execute 来完成的。

For convenience, we provide an alternate procedural interface to a machine’s

start operation, as well as procedures to set and examine register

contents, as specified at the beginning of 5.2:

为方便起见,我们提供了一个过程式的替代接口,用于机器的 start 操作,以及用于设置和查看寄存器内容的过程,如 5.2 节开头所说明的那样:

These procedures (and many procedures in 5.2.2 and 5.2.3)

use the following to look up the register with a given name in a given machine:

这些过程(以及 5.2.2 和 5.2.3 中的许多过程)使用下面这个过程,在给定机器中按名称查找寄存器:

Racket #lang sicp
(define (make-machine register-names
 ops
 controller-text)
 (let ((machine (make-new-machine)))
 (for-each (lambda (register-name)
 ((machine 'allocate-register)
 register-name))
 register-names)
 ((machine 'install-operations) ops)
 ((machine 'install-instruction-sequence)
 (assemble controller-text machine))
 machine))
Racket #lang sicp
(define (make-register name)
 (let ((contents '*unassigned*))
 (define (dispatch message)
 (cond ((eq? message 'get) contents)
 ((eq? message 'set)
 (lambda (value)
 (set! contents value)))
 (else
 (error "Unknown request:
 REGISTER"
 message))))
 dispatch))
Racket #lang sicp
(define (get-contents register)
 (register 'get))

(define (set-contents! register value)
 ((register 'set) value))
Racket #lang sicp
(define (make-stack)
 (let ((s '()))
 (define (push x)
 (set! s (cons x s)))
 (define (pop)
 (if (null? s)
 (error "Empty stack: POP")
 (let ((top (car s)))
 (set! s (cdr s))
 top)))
 (define (initialize)
 (set! s '())
 'done)
 (define (dispatch message)
 (cond ((eq? message 'push) push)
 ((eq? message 'pop) (pop))
 ((eq? message 'initialize)
 (initialize))
 (else
 (error "Unknown request: STACK"
 message))))
 dispatch))
Racket #lang sicp
(define (pop stack) (stack 'pop))
(define (push stack value)
 ((stack 'push) value))
Racket #lang sicp
(define (make-new-machine)
 (let ((pc (make-register 'pc))
 (flag (make-register 'flag))
 (stack (make-stack))
 (the-instruction-sequence '()))
 (let ((the-ops
 (list
 (list 'initialize-stack
 (lambda ()
 (stack 'initialize)))))
 (register-table
 (list (list 'pc pc)
 (list 'flag flag))))
 (define (allocate-register name)
 (if (assoc name register-table)
 (error
 "Multiply defined register: "
 name)
 (set! register-table
 (cons
 (list name
 (make-register name))
 register-table)))
 'register-allocated)
 (define (lookup-register name)
 (let ((val
 (assoc name register-table)))
 (if val
 (cadr val)
 (error "Unknown register:"
 name))))
 (define (execute)
 (let ((insts (get-contents pc)))
 (if (null? insts)
 'done
 (begin
 ((instruction-execution-proc
 (car insts)))
 (execute)))))
 (define (dispatch message)
 (cond ((eq? message 'start)
 (set-contents!
 pc
 the-instruction-sequence)
 (execute))
 ((eq?
 message
 'install-instruction-sequence)
 (lambda (seq)
 (set!
 the-instruction-sequence
 seq)))
 ((eq? message
 'allocate-register)
 allocate-register)
 ((eq? message 'get-register)
 lookup-register)
 ((eq? message
 'install-operations)
 (lambda (ops)
 (set! the-ops
 (append the-ops ops))))
 ((eq? message 'stack) stack)
 ((eq? message 'operations)
 the-ops)
 (else (error "Unknown request:
 MACHINE"
 message))))
 dispatch)))
Racket #lang sicp
(define (start machine)
 (machine 'start))

(define (get-register-contents
 machine register-name)
 (get-contents
 (get-register machine register-name)))

(define (set-register-contents!
 machine register-name value)
 (set-contents!
 (get-register machine register-name)
 value)
 'done)
Racket #lang sicp
(define (get-register machine reg-name)
 ((machine 'get-register) reg-name))