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

5.2.3 Generating Execution Procedures for Instructions

The assembler calls make-execution-procedure to generate the execution

procedure for an instruction. Like the analyze procedure in the

evaluator of 4.1.7, this dispatches on the type of instruction to

generate the appropriate execution procedure.

汇编器调用 `make-execution-procedure` 为每条指令生成执行过程。与 4.1.7 节求值器中的 `analyze` 过程类似,它按指令类型进行分派,生成相应的执行过程。

For each type of instruction in the register-machine language, there is a

generator that builds an appropriate execution procedure. The details of these

procedures determine both the syntax and meaning of the individual instructions

in the register-machine language. We use data abstraction to isolate the

detailed syntax of register-machine expressions from the general execution

mechanism, as we did for evaluators in 4.1.2, by using syntax

procedures to extract and classify the parts of an instruction.

Subheading: Assign instructions

The make-assign procedure handles assign instructions:

对于寄存器机器语言中的每种指令类型,都有一个生成器负责构建适当的执行过程。这些过程的细节同时决定了寄存器机器语言中各条指令的语法与语义。我们采用数据抽象将寄存器机器表达式的具体语法与通用执行机制相隔离,正如在 4.1.2 节中对求值器所做的那样——通过语法过程来提取并归类指令的各个部分。

子标题:`assign` 指令

过程 `make-assign` 处理 `assign` 指令:

Make-assign extracts the target register name (the second element of the

instruction) and the value expression (the rest of the list that forms the

instruction) from the assign instruction using the selectors

`make-assign` 使用选择函数从 `assign` 指令中提取目标寄存器名(指令的第二个元素)和值表达式(构成指令的表中的其余部分):

The register name is looked up with get-register to produce the target

register object. The value expression is passed to make-operation-exp

if the value is the result of an operation, and to make-primitive-exp

otherwise. These procedures (shown below) parse the value expression and

produce an execution procedure for the value. This is a procedure of no

arguments, called value-proc, which will be evaluated during the

simulation to produce the actual value to be assigned to the register. Notice

that the work of looking up the register name and parsing the value expression

is performed just once, at assembly time, not every time the instruction is

simulated. This saving of work is the reason we use execution procedures, and

corresponds directly to the saving in work we obtained by separating program

analysis from execution in the evaluator of 4.1.7.

寄存器名通过 `get-register` 查找,得到目标寄存器对象。若值是某个操作的结果,值表达式被传给 `make-operation-exp`;否则传给 `make-primitive-exp`。这两个过程(如下所示)解析值表达式并产生相应的值执行过程。该执行过程是一个无参过程,称为 `value-proc`,在模拟期间被求值以产生实际的赋值。注意,查找寄存器名和解析值表达式的工作仅在汇编时执行一次,而不是每次模拟指令时都执行。节省这部分工作正是我们使用执行过程的原因,这与 4.1.7 节中通过将程序分析与执行分离所获得的节省直接对应。

The result returned by make-assign is the execution procedure for the

assign instruction. When this procedure is called (by the machine

model’s execute procedure), it sets the contents of the target register

to the result obtained by executing value-proc. Then it advances the

pc to the next instruction by running the procedure

`make-assign` 返回的结果是 `assign` 指令的执行过程。当该过程被调用时(由机器模型的 `execute` 过程调用),它将目标寄存器的内容设置为执行 `value-proc` 所得的结果,然后通过运行以下过程将 `pc` 推进到下一条指令:

Advance-pc is the normal termination for all instructions except

branch and goto.

Subheading: Test, branch, and goto instructions

`advance-pc` 是除 `branch` 和 `goto` 以外所有指令的正常终止方式。

子标题:`test`、`branch` 与 `goto` 指令

Make-test handles test instructions in a similar way. It

extracts the expression that specifies the condition to be tested and generates

an execution procedure for it. At simulation time, the procedure for the

condition is called, the result is assigned to the flag register, and

the pc is advanced:

`make-test` 以类似方式处理 `test` 指令。它提取指定被测条件的表达式,并为其生成执行过程。在模拟时,条件过程被调用,结果赋给 `flag` 寄存器,然后推进 `pc`:

The execution procedure for a branch instruction checks the contents of

the flag register and either sets the contents of the pc to the

branch destination (if the branch is taken) or else just advances the pc

(if the branch is not taken). Notice that the indicated destination in a

branch instruction must be a label, and the make-branch procedure

enforces this. Notice also that the label is looked up at assembly time, not

each time the branch instruction is simulated.

`branch` 指令的执行过程检查 `flag` 寄存器的内容,若分支成立则将 `pc` 的内容设为分支目标,否则只是推进 `pc`。注意,`branch` 指令中指定的目标必须是一个标号,`make-branch` 过程强制执行这一约束。还应注意,标号的查找在汇编时完成,而不是每次模拟 `branch` 指令时才查找。

A goto instruction is similar to a branch, except that the destination

may be specified either as a label or as a register, and there is no condition

to check—the pc is always set to the new destination.

`goto` 指令与 `branch` 类似,不同之处在于目标既可以是标号也可以是寄存器,且无需检查任何条件——`pc` 总是被设置为新的目标。

Subheading: Other instructions

子标题:其他指令

The stack instructions save and restore simply use the stack with

the designated register and advance the pc:

栈指令 `save` 和 `restore` 只是对指定寄存器使用栈,并推进 `pc`:

The final instruction type, handled by make-perform, generates an

execution procedure for the action to be performed. At simulation time, the

action procedure is executed and the pc advanced.

最后一种指令类型由 `make-perform` 处理,它为待执行的动作生成执行过程。在模拟时,动作过程被执行,然后推进 `pc`。

Subheading: Execution procedures for subexpressions

子标题:子表达式的执行过程

The value of a reg, label, or const expression may be

needed for assignment to a register (make-assign) or for input to an

operation (make-operation-exp, below). The following procedure

generates execution procedures to produce values for these expressions during

the simulation:

`reg`、`label` 或 `const` 表达式的值可能用于赋值给寄存器(`make-assign`)或作为操作的输入(`make-operation-exp`,见下文)。以下过程生成执行过程,在模拟期间产生这些表达式的值:

The syntax of reg, label, and const expressions is

determined by

`reg`、`label` 和 `const` 表达式的语法由以下过程确定:

Assign, perform, and test instructions may include the

application of a machine operation (specified by an op expression) to

some operands (specified by reg and const expressions). The

following procedure produces an execution procedure for an “operation

expression”—a list containing the operation and operand expressions from the

instruction:

`assign`、`perform` 和 `test` 指令中可以包含将某个机器操作(由 `op` 表达式指定)应用于若干运算对象(由 `reg` 和 `const` 表达式指定)的调用。以下过程为"操作表达式 (operation expression)"——一个包含操作及指令中运算对象表达式的表——产生执行过程:

The syntax of operation expressions is determined by

操作表达式的语法由以下过程确定:

Observe that the treatment of operation expressions is very much like the

treatment of procedure applications by the analyze-application procedure

in the evaluator of 4.1.7 in that we generate an execution

procedure for each operand. At simulation time, we call the operand procedures

and apply the Scheme procedure that simulates the operation to the resulting

values. The simulation procedure is found by looking up the operation name in

the operation table for the machine:

请注意,对操作表达式的处理与 4.1.7 节求值器中 `analyze-application` 过程处理过程应用的方式非常相似——我们同样为每个运算对象生成执行过程。在模拟时,我们调用各运算对象过程,并将模拟该操作的 Scheme 过程应用于所得的各个值。模拟过程通过在机器的操作表中查找操作名称来找到:

Racket #lang sicp
(define (make-execution-procedure
 inst labels machine pc flag stack ops)
 (cond ((eq? (car inst) 'assign)
 (make-assign
 inst machine labels ops pc))
 ((eq? (car inst) 'test)
 (make-test
 inst machine labels ops flag pc))
 ((eq? (car inst) 'branch)
 (make-branch
 inst machine labels flag pc))
 ((eq? (car inst) 'goto)
 (make-goto inst machine labels pc))
 ((eq? (car inst) 'save)
 (make-save inst machine stack pc))
 ((eq? (car inst) 'restore)
 (make-restore inst machine stack pc))
 ((eq? (car inst) 'perform)
 (make-perform
 inst machine labels ops pc))
 (else (error "Unknown instruction
 type: ASSEMBLE"
 inst))))
Racket #lang sicp
(define (make-assign
 inst machine labels operations pc)
 (let ((target
 (get-register
 machine
 (assign-reg-name inst)))
 (value-exp (assign-value-exp inst)))
 (let ((value-proc
 (if (operation-exp? value-exp)
 (make-operation-exp
 value-exp
 machine
 labels
 operations)
 (make-primitive-exp
 (car value-exp)
 machine
 labels))))
 (lambda () ; execution procedure
 ; for assign
 (set-contents! target (value-proc))
 (advance-pc pc)))))
Racket #lang sicp
(define (assign-reg-name assign-instruction)
 (cadr assign-instruction))
(define (assign-value-exp assign-instruction)
 (cddr assign-instruction))
Racket #lang sicp
(define (advance-pc pc)
 (set-contents! pc (cdr (get-contents pc))))
Racket #lang sicp
(define
 (make-test
 inst machine labels operations flag pc)
 (let ((condition (test-condition inst)))
 (if (operation-exp? condition)
 (let ((condition-proc
 (make-operation-exp
 condition
 machine
 labels
 operations)))
 (lambda ()
 (set-contents!
 flag (condition-proc))
 (advance-pc pc)))
 (error "Bad TEST instruction:
 ASSEMBLE" inst))))

(define (test-condition test-instruction)
 (cdr test-instruction))
Racket #lang sicp
(define
 (make-branch
 inst machine labels flag pc)
 (let ((dest (branch-dest inst)))
 (if (label-exp? dest)
 (let ((insts
 (lookup-label
 labels
 (label-exp-label dest))))
 (lambda ()
 (if (get-contents flag)
 (set-contents! pc insts)
 (advance-pc pc))))
 (error "Bad BRANCH instruction:
 ASSEMBLE"
 inst))))

(define (branch-dest branch-instruction)
 (cadr branch-instruction))
Racket #lang sicp
(define (make-goto inst machine labels pc)
 (let ((dest (goto-dest inst)))
 (cond ((label-exp? dest)
 (let ((insts
 (lookup-label
 labels
 (label-exp-label dest))))
 (lambda ()
 (set-contents! pc insts))))
 ((register-exp? dest)
 (let ((reg
 (get-register
 machine
 (register-exp-reg dest))))
 (lambda ()
 (set-contents!
 pc
 (get-contents reg)))))
 (else (error "Bad GOTO instruction:
 ASSEMBLE"
 inst)))))

(define (goto-dest goto-instruction)
 (cadr goto-instruction))
Racket #lang sicp
(define (make-save inst machine stack pc)
 (let ((reg (get-register
 machine
 (stack-inst-reg-name inst))))
 (lambda ()
 (push stack (get-contents reg))
 (advance-pc pc))))

(define (make-restore inst machine stack pc)
 (let ((reg (get-register
 machine
 (stack-inst-reg-name inst))))
 (lambda ()
 (set-contents! reg (pop stack))
 (advance-pc pc))))

(define (stack-inst-reg-name
 stack-instruction)
 (cadr stack-instruction))
Racket #lang sicp
(define (make-perform
 inst machine labels operations pc)
 (let ((action (perform-action inst)))
 (if (operation-exp? action)
 (let ((action-proc
 (make-operation-exp
 action
 machine
 labels
 operations)))
 (lambda ()
 (action-proc)
 (advance-pc pc)))
 (error "Bad PERFORM instruction:
 ASSEMBLE"
 inst))))

(define (perform-action inst) (cdr inst))
Racket #lang sicp
(define (make-primitive-exp exp machine labels)
 (cond ((constant-exp? exp)
 (let ((c (constant-exp-value exp)))
 (lambda () c)))
 ((label-exp? exp)
 (let ((insts
 (lookup-label
 labels
 (label-exp-label exp))))
 (lambda () insts)))
 ((register-exp? exp)
 (let ((r (get-register
 machine
 (register-exp-reg exp))))
 (lambda () (get-contents r))))
 (else (error "Unknown expression type:
 ASSEMBLE"
 exp))))
Racket #lang sicp
(define (register-exp? exp)
 (tagged-list? exp 'reg))
(define (register-exp-reg exp)
 (cadr exp))
(define (constant-exp? exp)
 (tagged-list? exp 'const))
(define (constant-exp-value exp)
 (cadr exp))
(define (label-exp? exp)
 (tagged-list? exp 'label))
(define (label-exp-label exp)
 (cadr exp))
Racket #lang sicp
(define (make-operation-exp
 exp machine labels operations)
 (let ((op (lookup-prim
 (operation-exp-op exp)
 operations))
 (aprocs
 (map (lambda (e)
 (make-primitive-exp
 e machine labels))
 (operation-exp-operands exp))))
 (lambda () (apply op (map (lambda (p) (p))
 aprocs)))))
Racket #lang sicp
(define (operation-exp? exp)
 (and (pair? exp)
 (tagged-list? (car exp) 'op)))
(define (operation-exp-op operation-exp)
 (cadr (car operation-exp)))
(define (operation-exp-operands operation-exp)
 (cdr operation-exp))
Racket #lang sicp
(define (lookup-prim symbol operations)
 (let ((val (assoc symbol operations)))
 (if val
 (cadr val)
 (error "Unknown operation: ASSEMBLE"
 symbol))))