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

5.2.2 The Assembler

The assembler transforms the sequence of controller expressions for a machine

into a corresponding list of machine instructions, each with its execution

procedure. Overall, the assembler is much like the evaluators we studied in

Chapter 4—there is an input language (in this case, the

register-machine language) and we must perform an appropriate action for each

type of expression in the language.

汇编器将机器的控制器表达式序列转换为对应的机器指令表,其中每条指令都附有相应的执行过程。总体而言,汇编器与我们在第 4 章研究过的求值器十分相似——都有一种输入语言(这里是寄存器机器语言),并且必须对语言中的每种表达式类型执行恰当的动作。

The technique of producing an execution procedure for each instruction is just

what we used in 4.1.7 to speed up the evaluator by separating

analysis from runtime execution. As we saw in Chapter 4, much useful

analysis of Scheme expressions could be performed without knowing the actual

values of variables. Here, analogously, much useful analysis of

register-machine-language expressions can be performed without knowing the

actual contents of machine registers. For example, we can replace references

to registers by pointers to the register objects, and we can replace references

to labels by pointers to the place in the instruction sequence that the label

designates.

为每条指令生成执行过程的技术,正是我们在 4.1.7 节中为加速求值器而采用的技术——通过将分析与运行时执行分离来实现。如同我们在第 4 章所见,对 Scheme 表达式的许多有用分析都可以在不知道变量实际值的情况下完成。与此类似,对寄存器机器语言表达式的许多有用分析也可以在不知道机器寄存器实际内容的情况下完成。例如,我们可以将对寄存器的引用替换为指向寄存器对象的指针,将对标号 (labels) 的引用替换为指向该标号所指定的指令序列位置的指针。

Before it can generate the instruction execution procedures, the assembler must

know what all the labels refer to, so it begins by scanning the controller text

to separate the labels from the instructions. As it scans the text, it

constructs both a list of instructions and a table that associates each label

with a pointer into that list. Then the assembler augments the instruction

list by inserting the execution procedure for each instruction.

在生成指令执行过程之前,汇编器必须知道所有标号所引用的位置,因此它首先扫描控制器文本,将标号与指令分离。在扫描文本的过程中,它同时构造一个指令表和一个将每个标号与该表中某一指针相关联的表格。之后,汇编器通过为每条指令插入执行过程来扩充这个指令表。

The assemble procedure is the main entry to the assembler. It takes the

controller text and the machine model as arguments and returns the instruction

sequence to be stored in the model. Assemble calls

extract-labels to build the initial instruction list and label table

from the supplied controller text. The second argument to

extract-labels is a procedure to be called to process these results:

This procedure uses update-insts! to generate the instruction execution

procedures and insert them into the instruction list, and returns the modified

list.

过程 `assemble` 是汇编器的主入口。它以控制器文本和机器模型为参数,返回将存入模型的指令序列。`assemble` 调用 `extract-labels`,根据所提供的控制器文本构建初始指令表和标号表。`extract-labels` 的第二个参数是一个用于处理这些结果的过程:该过程调用 `update-insts!` 生成指令执行过程并将其插入指令表,然后返回修改后的指令表。

Extract-labels takes as arguments a list text (the sequence of

controller instruction expressions) and a receive procedure.

Receive will be called with two values: (1) a list insts of

instruction data structures, each containing an instruction from text;

and (2) a table called labels, which associates each label from

text with the position in the list insts that the label

designates.

`extract-labels` 以一个表 `text`(控制器指令表达式的序列)和一个接收过程 `receive` 作为参数。`receive` 将被以两个值调用:(1)由指令数据结构组成的表 `insts`,其中每个元素包含来自 `text` 的一条指令;(2)一个称为 `labels` 的表格,它将 `text` 中的每个标号与其在 `insts` 表中所指定位置相关联。

Extract-labels works by sequentially scanning the elements of the

text and accumulating the insts and the labels. If an

element is a symbol (and thus a label) an appropriate entry is added to the

labels table. Otherwise the element is accumulated onto the

insts list.

`extract-labels` 通过顺序扫描 `text` 的各个元素来工作,逐步积累 `insts` 和 `labels`。若某个元素是符号(因而是标号),则向 `labels` 表中添加一个相应的条目;否则,该元素被积累到 `insts` 表中。

Update-insts! modifies the instruction list, which initially contains

only the text of the instructions, to include the corresponding execution

procedures:

`update-insts!` 修改指令表——该表最初只包含指令文本——以插入对应的执行过程:

The machine instruction data structure simply pairs the instruction text with

the corresponding execution procedure. The execution procedure is not yet

available when extract-labels constructs the instruction, and is

inserted later by update-insts!.

机器指令数据结构将指令文本与相应的执行过程简单地配对在一起。执行过程在 `extract-labels` 构造指令时尚不可用,由 `update-insts!` 在之后插入。

The instruction text is not used by our simulator, but it is handy to keep

around for debugging (see Exercise 5.16).

Elements of the label table are pairs:

指令文本在我们的模拟器中并不使用,但保留它便于调试(见练习 5.16)。标号表的元素是序对:

Entries will be looked up in the table with

表中的条目将通过以下方式查找:

Racket #lang sicp
(define (assemble controller-text machine)
 (extract-labels controller-text
 (lambda (insts labels)
 (update-insts! insts labels machine)
 insts)))
Racket #lang sicp
(define (extract-labels text receive)
 (if (null? text)
 (receive '() '())
 (extract-labels
 (cdr text)
 (lambda (insts labels)
 (let ((next-inst (car text)))
 (if (symbol? next-inst)
 (receive
 insts
 (cons
 (make-label-entry
 next-inst
 insts)
 labels))
 (receive
 (cons (make-instruction
 next-inst)
 insts)
 labels)))))))
Racket #lang sicp
(define (update-insts! insts labels machine)
 (let ((pc (get-register machine 'pc))
 (flag (get-register machine 'flag))
 (stack (machine 'stack))
 (ops (machine 'operations)))
 (for-each
 (lambda (inst)
 (set-instruction-execution-proc!
 inst
 (make-execution-procedure
 (instruction-text inst)
 labels
 machine
 pc
 flag
 stack
 ops)))
 insts)))
Racket #lang sicp
(define (make-instruction text)
 (cons text '()))
(define (instruction-text inst) (car inst))
(define (instruction-execution-proc inst)
 (cdr inst))
(define (set-instruction-execution-proc!
 inst
 proc)
 (set-cdr! inst proc))
Racket #lang sicp
(define (make-label-entry label-name insts)
 (cons label-name insts))
Racket #lang sicp
(define (lookup-label labels label-name)
 (let ((val (assoc label-name labels)))
 (if val
 (cdr val)
 (error "Undefined label: ASSEMBLE"
 label-name))))