The assembler transforms the sequence of controller
expressionsinstructions
for a machine into a corresponding list of machine instructions, each with its
execution
procedure.function.
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 component in the language.
The technique of producing an execution
procedurefunction
for each instruction is just what we used in
section 4.1.7 to speed
up the evaluator by separating analysis from runtime execution. As we
saw in chapter 4, much useful
analysis of
SchemeJavaScript
expressions could
be performed without knowing the actual values of
variables.names.
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.
Before it can generate the instruction execution
procedures,functions,
the assembler must know what all the labels refer to, so it begins by
scanning the controller textsequence to separate the labels from the
instructions. As it scans the textcontroller, 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
procedurefunction
for each instruction.
The assembleprocedurefunction
is the main entry to the assembler. It takes the controller
textsequence and the
machine model as arguments and returns the instruction sequence to be stored
in the model.
Assemble
The function
assemble
calls
extract-labelsextract_labels
to build the initial instruction list and label table from the supplied
controller text. The second argument
to
extract-labelsextract_labels
is a
procedurefunction
to be called to process these results: This
procedurefunction
uses
update-insts!update_insts
to generate the instruction execution
proceduresfunctions
and insert them into the instruction list, and returns the modified list.
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.
The function extract_labels takes
a list controller
and a function receive
as arguments. The function receive will
be called with two values: (1) a list insts
of instruction data structures, each containing an instruction from
controller; and (2) a table called
labels, which associates each label from
controller with the position in the list
insts that the label designates.
Extract-labelsThe function
extract_labels
works by sequentially scanning the elements of the
textcontroller
and accumulating the
insts and the
labels. If an element is a
symbolstring
(and thus a label) an appropriate entry is added to the
labels table. Otherwise the element is
accumulated onto the insts
list.[1]
Update-insts!
The function
update_insts
modifies the instruction list, which initially contains only
the text of the instructions,the controller instructions,
to include the corresponding execution
procedures:functions:
The machine instruction data structure simply pairs the
controller
instruction text with the corresponding execution
procedure.function.
The execution
procedurefunction
is not yet available when
extract-labelsextract_labels
constructs the instruction, and is inserted later by
update-insts!.update_insts.
With the simulator as written, what will the contents of register
a be when control reaches
there? Modify the
extract-labelsextract_labelsprocedurefunction
so that the assembler will signal an error if the same label
name is used to indicate two different locations.
There is currently no solution available for this exercise. This textbook adaptation is a community effort. Do consider contributing by providing a solution for this exercise, using a Pull Request in Github.
[1]
Using the
receiveprocedurefunction
here is a way to get
extract-labelsextract_labels
to effectively return two
values—labels and
insts—without explicitly making a
compound data structure to hold them. An alternative implementation, which
returns an explicit pair of values, is
You can consider our use of receive as
demonstrating an elegant way to
return multiple values, or simply an excuse
to show off a programming trick. An argument like
receive that is the next
procedurefunction
to be invoked is called a
continuation. Recall that we
also used continuations to implement the backtracking control
structure in the amb evaluator in
section 4.3.3.