Article 17SQ6 Reservoir south

Reservoir south

by
ericlippert
from Fabulous adventures in coding on (#17SQ6)

You are south of a large lake, far too deep and wide to be crossed. Paths lead east, south and southwest.

> go north

You would drown.

> swim in the lake

Swimming isn't allowed in the lake.

> go east

Fine, be that way.

Code for this and the next several episodes is at https://github.com/ericlippert/flathead/tree/blog9

Two instructions are followed by a zstring-encoded string.

let has_text opcode = match opcode with | OP0_178 | OP0_179 -> true | _ -> false

We already have the method we need to read it; we can just call it:

 let decode_text text_address opcode = if has_text opcode then Some (read_zstring text_address) else None

We'll need to know how long, in bytes, the zstring encoded text was, so that we know where this instruction ends and the next one begins. I've implemented a little helper method, not shown, to do that.

 let get_text_length text_address opcode = if has_text opcode then zstring_length text_address else 0

And now we can combine the efforts of the last half dozen episodes to decode a single instruction. I am going to represent the instruction using a record type:

type t ={ opcode : bytecode; address : instruction_address; length : int; operands : operand list; store : variable_location option; branch : (bool * branch_address) option; text : string option;}

Recall that in OCaml the generic types are constructed backwards, so string option and operand list are "optional string" and "list of operands" respectively.

Let's put it all together. I have the byte address of the first byte in the instruction stored in addr:

 let form = decode_form addr in let op_count = decode_op_count addr form in let opcode = decode_opcode addr form op_count in let opcode_length = get_opcode_length form in let operand_types = decode_operand_types addr form op_count opcode in let type_length = get_type_length form opcode in let operand_address = inc_byte_addr_by addr (opcode_length + type_length) in let operands = decode_operands operand_address operand_types in let operand_length = get_operand_length operand_types in let store_address = inc_byte_addr_by operand_address operand_length in let store = decode_store store_address opcode ver in let store_length = get_store_length opcode ver in let branch_code_address = inc_byte_addr_by store_address store_length in let branch = decode_branch branch_code_address opcode ver in let branch_length = get_branch_length branch_code_address opcode ver in let (Byte_address ba) = branch_code_address in let text_address = Zstring (ba + branch_length) in let text = decode_text text_address opcode in let text_length = get_text_length text_address opcode in let length = opcode_length + type_length + operand_length + store_length + branch_length + text_length in let address = Instruction address in { opcode; address; length; operands; store; branch; text }

We have finally done it; we can completely disassemble any instruction, given a pointer to the instruction.

Next time on FAIC: now that we've disassembled it, let's display it as text. This will be shorter, I promise!


4108 b.gif?host=ericlippert.com&blog=67759120
External Content
Source RSS or Atom Feed
Feed Location http://ericlippert.com/feed
Feed Title Fabulous adventures in coding
Feed Link https://ericlippert.com/
Reply 0 comments