Assembler¶
Miki Tebeka’s Clever Idea http://pythonwise.blogspot.com/2012/06/python-based-assembler.html https://raw.githubusercontent.com/tebeka/pythonwise/master/assembler.pdf
-
class
oberon.assembler.
Assembler
[source]¶ -
-
dw
(data)[source]¶ Lay in a data word literal value. Adds the current address to the
data_addrs
set attribute.
-
-
class
oberon.assembler.
Context
(symbol_table)[source]¶ Execution namespace for asm code.
When identifiers are referenced and are not being assigned to the namespace Context __getitem__ method will be called with the name.
The Context searches itself (and __builtins__) for the name and returns the value if found, otherwise it creates a new named
LabelThunk
with that name, enters it in thesymbol_table
, and returns it.Later, when the named thunk is assigned a value, that value replaces the thunk in the
symbol_table
. This class will raise a RuntimeError if you attempt to assign a value to a label more than once.
-
class
oberon.assembler.
LabelThunk
(name)[source]¶ Stand for an address that will be determined later.
-
oberon.assembler.
assemble_file
(in_file, out_file, sym_file=None, print_program=False, additional_data=None, epilog=None)[source]¶ Accept up to three file objects. The first is a source file, the second is the binary output file, and the optional third is a file to which to write symbols and other information (currently the other information is just a set of addresses that contain data, rather than machine code.)
The symbol file is a pickle of a symbol table dictionary that maps label names to addresses, and the set of data addresses.
The resulting binary file is suitable for loading over the serial port, you can pass it to the
--serial-in
command line option.This is the Oberon bootloader function that will load the binary over the serial line:
PROCEDURE LoadFromLine; VAR len, adr, dat: INTEGER; BEGIN RecInt(len); WHILE len > 0 DO RecInt(adr); REPEAT RecInt(dat); SYSTEM.PUT(adr, dat); adr := adr + 4; len := len - 4 UNTIL len = 0; RecInt(len) END END LoadFromLine;
It reads a (4-byte) int length and drops into a while loop the loop reads a (4-byte) int address at which to store the following data.
Then a second loop (repeat) is started to read the data. It reads a 4-byte word, stores it to the RAM, then increments the address and decrements the length (each by four. So the length is counting bytes, not words! N.B.)
Once the repeat loop is done patching RAM it reads one more (4-byte) int length and the while loop restarts if the length is non-zero, otherwise we’re done and the machine boots from there.
-
oberon.assembler.
ops
= {'Add': 8, 'And': 4, 'Ann': 5, 'Asr': 2, 'Div': 11, 'Fad': 12, 'Fdv': 15, 'Fml': 14, 'Fsb': 13, 'Ior': 6, 'Lsl': 1, 'Mov': 0, 'Mul': 10, 'Ror': 3, 'Sub': 9, 'Xor': 7}¶ Operation names mapped to their values in instructions.
-
oberon.assembler.
thunkify_arithmetic_logic
(method)[source]¶ Wrap a method that uses
ASM
to make bits. If it’s called with aLabelThunk
it sets up a fixup function that resolves the actual instuction when the label is assigned to a concrete address.
-
oberon.assembler.
thunkify_branch
(method)[source]¶ Wrap a branch method. If it’s called with a
LabelThunk
it sets up a fixup function that resolves the actual instuction when the label is assigned to a concrete address.