So after the let-down of having to complete another test after the last one, I found myself with the following javascript file:
//--------------------------------------------------------------------------------------------------
//
// stage 2 of 3
//
// challenge:
//   reveal the solution within VM.mem
//
// disclaimer:
//   tested in ie 9, firefox 6, chrome 14 and v8 shell (http://code.google.com/apis/v8/build.html),
//   other javascript implementations may or may not work.
//
//--------------------------------------------------------------------------------------------------
var VM = {
  
    cpu: {
        ip: 0x00,
    
        r0: 0x00,
        r1: 0x00,
        r2: 0x00,
        r3: 0x00,
    
        cs: 0x00,
        ds: 0x10,
    
        fl: 0x00,
    
        firmware: [0xd2ab1f05, 0xda13f110]
    },
  
    mem: [
        0x31, 0x04, 0x33, 0xaa, 0x40, 0x02, 0x80, 0x03, 0x52, 0x00, 0x72, 0x01, 0x73, 0x01, 0xb2, 0x50,
        0x30, 0x14, 0xc0, 0x01, 0x80, 0x00, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        
        0x98, 0xab, 0xd9, 0xa1, 0x9f, 0xa7, 0x83, 0x83, 0xf2, 0xb1, 0x34, 0xb6, 0xe4, 0xb7, 0xca, 0xb8,
        0xc9, 0xb8, 0x0e, 0xbd, 0x7d, 0x0f, 0xc0, 0xf1, 0xd9, 0x03, 0xc5, 0x3a, 0xc6, 0xc7, 0xc8, 0xc9,
        0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9,
        0xda, 0xdb, 0xa9, 0xcd, 0xdf, 0xdf, 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9,
        0x26, 0xeb, 0xec, 0xed, 0xee, 0xef, 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9,
        0x7d, 0x1f, 0x15, 0x60, 0x4d, 0x4d, 0x52, 0x7d, 0x0e, 0x27, 0x6d, 0x10, 0x6d, 0x5a, 0x06, 0x56,
        0x47, 0x14, 0x42, 0x0e, 0xb6, 0xb2, 0xb2, 0xe6, 0xeb, 0xb4, 0x83, 0x8e, 0xd7, 0xe5, 0xd4, 0xd9,
        0xc3, 0xf0, 0x80, 0x95, 0xf1, 0x82, 0x82, 0x9a, 0xbd, 0x95, 0xa4, 0x8d, 0x9a, 0x2b, 0x30, 0x69,
        0x4a, 0x69, 0x65, 0x55, 0x1c, 0x7b, 0x69, 0x1c, 0x6e, 0x04, 0x74, 0x35, 0x21, 0x26, 0x2f, 0x60,
        0x03, 0x4e, 0x37, 0x1e, 0x33, 0x54, 0x39, 0xe6, 0xba, 0xb4, 0xa2, 0xad, 0xa4, 0xc5, 0x95, 0xc8,
        0xc1, 0xe4, 0x8a, 0xec, 0xe7, 0x92, 0x8b, 0xe8, 0x81, 0xf0, 0xad, 0x98, 0xa4, 0xd0, 0xc0, 0x8d,
        0xac, 0x22, 0x52, 0x65, 0x7e, 0x27, 0x2b, 0x5a, 0x12, 0x61, 0x0a, 0x01, 0x7a, 0x6b, 0x1d, 0x67,
        0x75, 0x70, 0x6c, 0x1b, 0x11, 0x25, 0x25, 0x70, 0x7f, 0x7e, 0x67, 0x63, 0x30, 0x3c, 0x6d, 0x6a,
        0x01, 0x51, 0x59, 0x5f, 0x56, 0x13, 0x10, 0x43, 0x19, 0x18, 0xe5, 0xe0, 0xbe, 0xbf, 0xbd, 0xe9,
        0xf0, 0xf1, 0xf9, 0xfa, 0xab, 0x8f, 0xc1, 0xdf, 0xcf, 0x8d, 0xf8, 0xe7, 0xe2, 0xe9, 0x93, 0x8e,
        0xec, 0xf5, 0xc8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    
        0x37, 0x7a, 0x07, 0x11, 0x1f, 0x1d, 0x68, 0x25, 0x32, 0x77, 0x1e, 0x62, 0x23, 0x5b, 0x47, 0x55,
        0x53, 0x30, 0x11, 0x42, 0xf6, 0xf1, 0xb1, 0xe6, 0xc3, 0xcc, 0xf8, 0xc5, 0xe4, 0xcc, 0xc0, 0xd3,
        0x85, 0xfd, 0x9a, 0xe3, 0xe6, 0x81, 0xb5, 0xbb, 0xd7, 0xcd, 0x87, 0xa3, 0xd3, 0x6b, 0x36, 0x6f,
        0x6f, 0x66, 0x55, 0x30, 0x16, 0x45, 0x5e, 0x09, 0x74, 0x5c, 0x3f, 0x29, 0x2b, 0x66, 0x3d, 0x0d,
        0x02, 0x30, 0x28, 0x35, 0x15, 0x09, 0x15, 0xdd, 0xec, 0xb8, 0xe2, 0xfb, 0xd8, 0xcb, 0xd8, 0xd1,
        0x8b, 0xd5, 0x82, 0xd9, 0x9a, 0xf1, 0x92, 0xab, 0xe8, 0xa6, 0xd6, 0xd0, 0x8c, 0xaa, 0xd2, 0x94,
        0xcf, 0x45, 0x46, 0x67, 0x20, 0x7d, 0x44, 0x14, 0x6b, 0x45, 0x6d, 0x54, 0x03, 0x17, 0x60, 0x62,
        0x55, 0x5a, 0x4a, 0x66, 0x61, 0x11, 0x57, 0x68, 0x75, 0x05, 0x62, 0x36, 0x7d, 0x02, 0x10, 0x4b,
        0x08, 0x22, 0x42, 0x32, 0xba, 0xe2, 0xb9, 0xe2, 0xd6, 0xb9, 0xff, 0xc3, 0xe9, 0x8a, 0x8f, 0xc1,
        0x8f, 0xe1, 0xb8, 0xa4, 0x96, 0xf1, 0x8f, 0x81, 0xb1, 0x8d, 0x89, 0xcc, 0xd4, 0x78, 0x76, 0x61,
        0x72, 0x3e, 0x37, 0x23, 0x56, 0x73, 0x71, 0x79, 0x63, 0x7c, 0x08, 0x11, 0x20, 0x69, 0x7a, 0x14,
        0x68, 0x05, 0x21, 0x1e, 0x32, 0x27, 0x59, 0xb7, 0xcf, 0xab, 0xdd, 0xd5, 0xcc, 0x97, 0x93, 0xf2,
        0xe7, 0xc0, 0xeb, 0xff, 0xe9, 0xa3, 0xbf, 0xa1, 0xab, 0x8b, 0xbb, 0x9e, 0x9e, 0x8c, 0xa0, 0xc1,
        0x9b, 0x5a, 0x2f, 0x2f, 0x4e, 0x4e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
    ],
  
    exec: function()
    {
    // virtual machine architecture
    // ++++++++++++++++++++++++++++
    //
    // segmented memory model with 16-byte segment size (notation seg:offset)
    //
    // 4 general-purpose registers (r0-r3)
    // 2 segment registers (cs, ds equiv. to r4, r5)
    // 1 flags register (fl)
    //
    // instruction encoding
    // ++++++++++++++++++++
    //
    //           byte 1               byte 2 (optional)
    // bits      [ 7 6 5 4 3 2 1 0 ]  [ 7 6 5 4 3 2 1 0 ]
    // opcode      - - -             
    // mod               -           
    // operand1            - - - -
    // operand2                         - - - - - - - -
    //
    // operand1 is always a register index
    // operand2 is optional, depending upon the instruction set specified below
    // the value of mod alters the meaning of any operand2
    //   0: operand2 = reg ix
    //   1: operand2 = fixed immediate value or target segment (depending on instruction)
    //
    // instruction set
    // +++++++++++++++
    // 
    // Notes:
    //   * r1, r2 => operand 1 is register 1, operand 2 is register 2
    //   * movr r1, r2 => move contents of register r2 into register r1
    // 
    // opcode | instruction | operands (mod 0) | operands (mod 1)
    // -------+-------------+------------------+-----------------
    // 0x00   | jmp         | r1               | r2:r1
    // 0x01   | movr        | r1, r2           | rx,   imm 
    // 0x02   | movm        | r1, [ds:r2]      | [ds:r1], r2
    // 0x03   | add         | r1, r2           | r1,   imm
    // 0x04   | xor         | r1, r2           | r1,   imm 
    // 0x05   | cmp         | r1, r2           | r1,   imm 
    // 0x06   | jmpe        | r1               | r2:r1
    // 0x07   | hlt         | N/A              | N/A
    //
    // flags
    // +++++
    // 
    // cmp r1, r2 instruction results in:
    //   r1 == r2 => fl = 0
    //   r1 < r2  => fl = 0xff
    //   r1 > r2  => fl = 1
    // 
    // jmpe r1
    //   => if (fl == 0) jmp r1
    //      else nop
    
        throw "VM.exec not yet implemented";
    }
  
};
//--------------------------------------------------------------------------------------------------
try
{
    VM.exec();
}
catch(e)
{
    alert('\nError: ' + e + '\n');
}
//--------------------------------------------------------------------------------------------------
 
So we have the details of an instruction set, three segments of memory and some variables that represent registers (oh...and some suspicious looking firmware values!).
The task here is to write a simple disassembler, be able to store a set of decoded instructions and to then execute them as part of a virtual machine. The tricky part is that the first section of code decodes the next one, so you must disassemble, build the instructions, run, disassemble, build more instructions then run again. After this you find the following in the second segment of memory:
'G' , 'E' , 'T' , ' ' , '/' , 'd' , 'a' , '7' , '5' , '3' , '7' , '0' , 'f' , 'e' , '1' , '5' , 
'c' , '4' , '1' , '4' , '8' , 'b' , 'd' , '4' , 'c' , 'e' , 'e' , 'c' , '8' , '6' , '1' , 'f' , 
'b' , 'd' , 'a' , 'a' , '5' , '.' , 'e' , 'x' , 'e' , ' ' , 'H' , 'T' , 'T' , 'P' , '/' , '1' ,
This is the address for the next stage of the challenge.
Interestingly, the third segment seems unchanged - very suspicious as there's not much spare information in any of these challenges.
My final code for this stage:
//--------------------------------------------------------------------------------------------------
//
// stage 2 of 3
//
// challenge:
//   reveal the solution within VM.mem
//
// disclaimer:
//   tested in ie 9, firefox 6, chrome 14 and v8 shell (http://code.google.com/apis/v8/build.html),
//   other javascript implementations may or may not work.
//
//--------------------------------------------------------------------------------------------------
var VM = {  
        cpu: {
        ip: 0x00,
        
        r0: 0x00,
        r1: 0x00,
        r2: 0x00,
        r3: 0x00,
        
        cs: 0x00,
        ds: 0x10, 
     
        fl: 0x00,
     
        firmware: [0xd2ab1f05, 0xda13f110]
    },
    
    mem: [
        0x31, 0x04, 0x33, 0xaa, 0x40, 0x02, 0x80, 0x03, 0x52, 0x00, 0x72, 0x01, 0x73, 0x01, 0xb2, 0x50,
        0x30, 0x14, 0xc0, 0x01, 0x80, 0x00, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        
        0x98, 0xab, 0xd9, 0xa1, 0x9f, 0xa7, 0x83, 0x83, 0xf2, 0xb1, 0x34, 0xb6, 0xe4, 0xb7, 0xca, 0xb8,
        0xc9, 0xb8, 0x0e, 0xbd, 0x7d, 0x0f, 0xc0, 0xf1, 0xd9, 0x03, 0xc5, 0x3a, 0xc6, 0xc7, 0xc8, 0xc9,
        0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9,
        0xda, 0xdb, 0xa9, 0xcd, 0xdf, 0xdf, 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9,
        0x26, 0xeb, 0xec, 0xed, 0xee, 0xef, 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9,
        0x7d, 0x1f, 0x15, 0x60, 0x4d, 0x4d, 0x52, 0x7d, 0x0e, 0x27, 0x6d, 0x10, 0x6d, 0x5a, 0x06, 0x56,
        0x47, 0x14, 0x42, 0x0e, 0xb6, 0xb2, 0xb2, 0xe6, 0xeb, 0xb4, 0x83, 0x8e, 0xd7, 0xe5, 0xd4, 0xd9,
        0xc3, 0xf0, 0x80, 0x95, 0xf1, 0x82, 0x82, 0x9a, 0xbd, 0x95, 0xa4, 0x8d, 0x9a, 0x2b, 0x30, 0x69,
        0x4a, 0x69, 0x65, 0x55, 0x1c, 0x7b, 0x69, 0x1c, 0x6e, 0x04, 0x74, 0x35, 0x21, 0x26, 0x2f, 0x60,
        0x03, 0x4e, 0x37, 0x1e, 0x33, 0x54, 0x39, 0xe6, 0xba, 0xb4, 0xa2, 0xad, 0xa4, 0xc5, 0x95, 0xc8,
        0xc1, 0xe4, 0x8a, 0xec, 0xe7, 0x92, 0x8b, 0xe8, 0x81, 0xf0, 0xad, 0x98, 0xa4, 0xd0, 0xc0, 0x8d,
        0xac, 0x22, 0x52, 0x65, 0x7e, 0x27, 0x2b, 0x5a, 0x12, 0x61, 0x0a, 0x01, 0x7a, 0x6b, 0x1d, 0x67,
        0x75, 0x70, 0x6c, 0x1b, 0x11, 0x25, 0x25, 0x70, 0x7f, 0x7e, 0x67, 0x63, 0x30, 0x3c, 0x6d, 0x6a,
        0x01, 0x51, 0x59, 0x5f, 0x56, 0x13, 0x10, 0x43, 0x19, 0x18, 0xe5, 0xe0, 0xbe, 0xbf, 0xbd, 0xe9,
        0xf0, 0xf1, 0xf9, 0xfa, 0xab, 0x8f, 0xc1, 0xdf, 0xcf, 0x8d, 0xf8, 0xe7, 0xe2, 0xe9, 0x93, 0x8e,
        0xec, 0xf5, 0xc8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        
        0x37, 0x7a, 0x07, 0x11, 0x1f, 0x1d, 0x68, 0x25, 0x32, 0x77, 0x1e, 0x62, 0x23, 0x5b, 0x47, 0x55,
        0x53, 0x30, 0x11, 0x42, 0xf6, 0xf1, 0xb1, 0xe6, 0xc3, 0xcc, 0xf8, 0xc5, 0xe4, 0xcc, 0xc0, 0xd3,
        0x85, 0xfd, 0x9a, 0xe3, 0xe6, 0x81, 0xb5, 0xbb, 0xd7, 0xcd, 0x87, 0xa3, 0xd3, 0x6b, 0x36, 0x6f,
        0x6f, 0x66, 0x55, 0x30, 0x16, 0x45, 0x5e, 0x09, 0x74, 0x5c, 0x3f, 0x29, 0x2b, 0x66, 0x3d, 0x0d,
        0x02, 0x30, 0x28, 0x35, 0x15, 0x09, 0x15, 0xdd, 0xec, 0xb8, 0xe2, 0xfb, 0xd8, 0xcb, 0xd8, 0xd1,
        0x8b, 0xd5, 0x82, 0xd9, 0x9a, 0xf1, 0x92, 0xab, 0xe8, 0xa6, 0xd6, 0xd0, 0x8c, 0xaa, 0xd2, 0x94,
        0xcf, 0x45, 0x46, 0x67, 0x20, 0x7d, 0x44, 0x14, 0x6b, 0x45, 0x6d, 0x54, 0x03, 0x17, 0x60, 0x62,
        0x55, 0x5a, 0x4a, 0x66, 0x61, 0x11, 0x57, 0x68, 0x75, 0x05, 0x62, 0x36, 0x7d, 0x02, 0x10, 0x4b,
        0x08, 0x22, 0x42, 0x32, 0xba, 0xe2, 0xb9, 0xe2, 0xd6, 0xb9, 0xff, 0xc3, 0xe9, 0x8a, 0x8f, 0xc1,
        0x8f, 0xe1, 0xb8, 0xa4, 0x96, 0xf1, 0x8f, 0x81, 0xb1, 0x8d, 0x89, 0xcc, 0xd4, 0x78, 0x76, 0x61,
        0x72, 0x3e, 0x37, 0x23, 0x56, 0x73, 0x71, 0x79, 0x63, 0x7c, 0x08, 0x11, 0x20, 0x69, 0x7a, 0x14,
        0x68, 0x05, 0x21, 0x1e, 0x32, 0x27, 0x59, 0xb7, 0xcf, 0xab, 0xdd, 0xd5, 0xcc, 0x97, 0x93, 0xf2,
        0xe7, 0xc0, 0xeb, 0xff, 0xe9, 0xa3, 0xbf, 0xa1, 0xab, 0x8b, 0xbb, 0x9e, 0x9e, 0x8c, 0xa0, 0xc1,
        0x9b, 0x5a, 0x2f, 0x2f, 0x4e, 0x4e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
    ],
    decoded_instructions: {},
    decode_mem: function()
    {
        var pos = this.decode_pos;
        var b1 = this.mem[(this.decode_offset * 16) + this.decode_pos];
        var b2 = this.mem[(this.decode_offset * 16) + this.decode_pos + 1]; 
        var operand2 = b2;
        var mod = ((0x10 & b1) >> 4);
        var operand1 = (0x07 & b1);
        var instruction = ((0xE0 & b1) >> 5);
        if(instruction == 0x07){ //hlt
            this.decoded_instructions[pos] = ["htl"];
            return false;
        }
        if(mod == 0){
            switch(instruction){
            case 0x00: //"jmp"
                this.decode_pos += 1;
                this.decoded_instructions[pos] = ["jmp", "r" + String(operand1)];
                return true;
            case 0x01: //"movr"
                this.decode_pos += 2;
                this.decoded_instructions[pos] = 
                    this.swap_out_segment_registers(["movr", "r" + String(operand1), "r" +
                                                     String(operand2)]);
                return true;
            case 0x02: //"movm"
                this.decode_pos += 2;  
                this.decoded_instructions[pos] = 
                    this.swap_out_segment_registers(["movm", "r" + String(operand1), "ds:r" +
                                                     String(operand2)]);
                return true;
            case 0x03: //"add"
                this.decode_pos += 2;
                this.decoded_instructions[pos] = 
                    this.swap_out_segment_registers(["add", "r" + String(operand1), "r" +
                                                     String(operand2)]);
                return true;
            case 0x04: //"xor"
                this.decode_pos += 2;
                this.decoded_instructions[pos] = 
                    this.swap_out_segment_registers(["xor", "r" + String(operand1), "r" +
                                                     String(operand2)]);
                return true;
            case 0x05: //"cmp"
                this.decode_pos += 2;
                this.decoded_instructions[pos] = 
                    this.swap_out_segment_registers(["cmp", "r" + String(operand1), "r" +
                                                     String(operand2)]);
                return true;
            case 0x06: //"jmpe"
                this.decode_pos += 1;
                this.decoded_instructions[pos] = ["jmpe", "r" + String(operand1)];
                return true;
            }
            } else { //mod == 1
            switch(instruction){
            case 0x00: //"jmp"
                this.decode_pos += 2;
                this.decode_offset = operand2 * 16;
                this.decoded_instructions[pos] = ["jmp", "s" + String(operand2) + ":r" +
                                                  String(operand1)];
                return false;
            case 0x01: //"movr"
                this.decode_pos += 2;
                this.decoded_instructions[pos] = 
                    this.swap_out_segment_registers(["movr", "r" + String(operand1), operand2]);
                return true;
            case 0x02: //"movm"
                this.decode_pos += 2;
                this.decoded_instructions[pos] = 
                    this.swap_out_segment_registers(["movm", "ds:r" + String(operand1), "r" +
                                                     String(operand2)]);
                return true;
            case 0x03: //"add"
                this.decode_pos += 2;
                this.decoded_instructions[pos] = 
                    this.swap_out_segment_registers(["add", "r" + String(operand1), operand2]);
                return true;
            case 0x04: //"xor"
                this.decode_pos += 2;
                this.decoded_instructions[pos] = 
                    this.swap_out_segment_registers(["xor", "r" + String(operand1), operand2]);
                return true;
            case 0x05: //"cmp"
                this.decode_pos += 2;
                this.decoded_instructions[pos] = 
                    this.swap_out_segment_registers(["cmp", "r" + String(operand1), operand2]);
                return true;
            case 0x06: //"jmpe"
                this.decode_pos += 2;
                this.decode_offset = operand2 * 16;
                this.decoded_instructions[pos] = ["jmpe", "s" + String(operand2) + ":r" +
                                                  String(operand1)];
                return false;
            }
        }
    },
    run_instructions: function(){
        document.write("<table border=\"1\">");
        var looping = true;
        while(looping && this.cpu.ip < 256){
            if(!(this.cpu.ip in this.decoded_instructions)){
                this.cpu.ip++;
                continue;
            }
            var instruction = this.decoded_instructions[this.cpu.ip];
            switch(instruction[0]){
            case "jmp":
                if(instruction[1][0] == "s"){
                    var re = /s(\d*):(r\d)/;
                    var vals = instruction[1].match(re);
                    this.cpu.cs = Number(vals[1]);
                    this.cpu.ip = eval("this.cpu." + vals[2]) - 1;
                    looping = false;
                } else {
                    this.cpu.ip = eval("this.cpu." + instruction[1]) - 1;
                }
                break;
            case "jmpe":
                if(this.cpu.fl != 0){
                    break;
                }
                if(instruction[1][0] == "s"){
                    var re = /s(\d*):(r\d)/;
                    var vals = instruction[1].match(re);
                    this.cpu.cs = Number(vals[1]);
                    this.cpu.ip = eval("this.cpu." + vals[2]) - 1;
                    looping = false;
                } else {
                    this.cpu.ip = eval("this.cpu." + instruction[1]) - 1;
                }
                break;
            case "movr":
                if(instruction[2][0] == "r" || instruction[2][0] == "c" ||
                        instruction[2][0] == "d"){
                    eval("this.cpu." + instruction[1] + " = this.cpu." + instruction[2])
                } else {
                    eval("this.cpu." + instruction[1] + " = " + instruction[2]);
                }
                break;
            case "movm":
                var re = /ds:(r\d*)/;
                if(instruction[1][0] == "d"){ //mod 1
                    var vals = instruction[1].match(re);
                    var r = eval("this.cpu." + vals[1]);
                    this.mem[r + (this.cpu.ds * 16)] = eval("this.cpu." + instruction[2]);
                } else {
                    var vals = instruction[2].match(re);
                    var r = eval("this.cpu." + vals[1]);
                    eval("this.cpu." + instruction[1] + " = this.mem[r + " +
                         (this.cpu.ds * 16) + "]");
                }
                break;
            case "add":
                if(instruction[2][0] == "r" || instruction[2][0] == "c" ||
                        instruction[2][0] == "d"){
                    eval("this.cpu." + instruction[1] + " += this.cpu." + instruction[2]);
                } else {
                    eval("this.cpu." + instruction[1] + " += " + instruction[2]);
                }  
                break;
            case "xor":
                if(instruction[2][0] == "r"){
                    eval("this.cpu." + instruction[1] + " ^= this.cpu." + instruction[2]);
                } else {
                    eval("this.cpu." + instruction[1] + " ^= " + instruction[2]);
                }  
                break;
            case "cmp":
                if(instruction[2][0] == "r"){
                    if(eval("this.cpu." + instruction[1]) == eval("this.cpu." + instruction[2])){
                 this.cpu.fl = 0;
                    } else if(eval("this.cpu." + instruction[1]) > eval("this.cpu." +
                                                                        instruction[2])){
                 this.cpu.fl = 1;
                    } else{
                 this.cpu.fl = 0xFF;
                    }
                } else {
                    if(eval("this.cpu." + instruction[1]) == instruction[2]){
                 this.cpu.fl = 0;
                    } else if(eval("this.cpu." + instruction[1]) > instruction[2]){
                 this.cpu.fl = 1;
                    } else{
                 this.cpu.fl = 0xFF;
                    }
                }
                break;
            case "hlt":
                looping = false;
                break;          
            }
            this.cpu.ip++;
            document.write("<tr>");
            document.write("<td>" + this.get_instruction_text(instruction));
            document.write("</td><td>" + this.get_state() + "</td></tr>");
        }
        document.write("</table></p>");
        this.decoded_instructions = {}
        this.decode_offset = this.cpu.cs;
        this.decode_pos = 0;
    },
    swap_out_segment_registers: function(instruction){
        for(var i = 0; i < instruction.length;i++){
            if(instruction[i] == "r4"){instruction[i] = "cs";}
            if(instruction[i] == "r5"){instruction[i] = "ds";}
        }
        return instruction;
   },
    print_mem: function(){
        document.write("Memory Dump<br />");
        for(var i = 0; i < this.mem.length; i++){
            if(this.mem[i] < 0x20 || this.mem[i] > 0x7E){
                var v = this.mem[i].toString(16);
                if(v.length == 1){
                    v = "0x0" + v;
                } else {
                    v = "0x" + v;
                }
                document.write(v + ", ");
            } else {
                document.write("'" + String.fromCharCode(this.mem[i]) + "' , ");
            }
            if(((i + 1) % 16) == 0){
                document.write("<br />"); 
            }
            if(((i + 1) % 256) == 0){
                document.write("<br />");
            }
        }
    },
    get_state: function(){
        var state = "ip = " + this.cpu.ip + ", ";
        state += "cs = " + this.cpu.cs + ", ";
        state += "ds = " + this.cpu.ds + ", ";
        state += "r0 = " + this.cpu.r0 + ", ";
        state += "r1 = " + this.cpu.r1 + ", ";
        state += "r2 = " + this.cpu.r2 + ", ";
        state += "r3 = " + this.cpu.r3 + ", ";
        state += "fl = " + this.cpu.fl + ".";
        return state;
    },
    get_instruction_text: function(instruction){
        var text = instruction[0];
        if(instruction.length == 2){
            text += " " + instruction[1];
        }
        if(instruction.length == 3){
            text += " " + instruction[1] + ", " + String(instruction[2]);
        }
        return text;
    },
    print_instructions: function(){
        document.write("<p>");
        document.write("Decoded instructions:<br />");
        document.write("<table border=\"1\">");
    
        for(var i = 0; i < 256 ; i++){
            if(!(i in this.decoded_instructions)){
                continue;
            }
            document.write("<tr>");
            var instruction = this.decoded_instructions[i];
            document.write("<td>At pos " + i + "</td>");
            document.write("<td>" + this.get_instruction_text(instruction));
            document.write("</td><td>");
        }
        document.write("</table></p>");
    },
    decode_pos : 0x00,
    decode_offset: 0x00,
    decode: function(){
        while(this.decode_mem()){ }
        this.print_instructions()
        this.run_instructions()
        this.print_mem()
        while(this.decode_mem()){ }
        this.print_instructions()
        this.run_instructions()
        this.print_mem()
/*
        this.decode_offset = 22;
        this.decode_pos = 0;
        while(this.decode_mem()){ }
        this.print_instructions()
        this.print_mem()
*/
    }, 
    instructions: ["jmp", "movr","movm", "add","xor","cmp","jmpe", "hlt"],
    exec: function()
    {
 // virtual machine architecture
 // ++++++++++++++++++++++++++++
 //
 // segmented memory model with 16-byte segment size (notation seg:offset)
 //
 // 4 general-purpose registers (r0-r3)
 // 2 segment registers (cs, ds equiv. to r4, r5)
 // 1 flags register (fl)
 //
 // instruction encoding
 // ++++++++++++++++++++
 //
 //           byte 1               byte 2 (optional)
 // bits      [ 7 6 5 4 3 2 1 0 ]  [ 7 6 5 4 3 2 1 0 ]
 // opcode      - - -             
 // mod               -           
 // operand1            - - - -
 // operand2                         - - - - - - - -
 //
 // operand1 is always a register index
 // operand2 is optional, depending upon the instruction set specified below
 // the value of mod alters the meaning of any operand2
 //   0: operand2 = reg ix
 //   1: operand2 = fixed immediate value or target segment (depending on instruction)
 //
 // instruction set
 // +++++++++++++++
 // 
 // Notes:
 //   * r1, r2 => operand 1 is register 1, operand 2 is register 2
 //   * movr r1, r2 => move contents of register r2 into register r1
 // 
 // opcode | instruction | operands (mod 0) | operands (mod 1)
 // -------+-------------+------------------+-----------------
 // 0x00   | jmp         | r1               | r2:r1
 // 0x01   | movr        | r1, r2           | rx,   imm 
 // 0x02   | movm        | r1, [ds:r2]      | [ds:r1], r2
 // 0x03   | add         | r1, r2           | r1,   imm
 // 0x04   | xor         | r1, r2           | r1,   imm 
 // 0x05   | cmp         | r1, r2           | r1,   imm 
 // 0x06   | jmpe        | r1               | r2:r1
 // 0x07   | hlt         | N/A              | N/A
 //
 // flags
 // +++++
 // 
 // cmp r1, r2 instruction results in:
 //   r1 == r2 => fl = 0
 //   r1 < r2  => fl = 0xff
 //   r1 > r2  => fl = 1
 // 
 // jmpe r1
 //   => if (fl == 0) jmp r1
 //      else nop 
 //    throw "VM.exec not yet implemented";
    }
  
};
//--------------------------------------------------------------------------------------------------
try
{
    VM.decode();
//    VM.exec();
}
catch(e)
{
    alert('\nError: ' + e + '\n');
}
//--------------------------------------------------------------------------------------------------
 
Use the following html file and load it in Chrome or Firefox to see it work:
Now onto stage 3...