Сияна обнови решението на 13.01.2014 20:25 (преди почти 11 години)
+module DefaultExecutableInstructions
+ def move(destination_register, source)
+ value = source.kind_of?(Symbol) ? @registers[source] : source
+ @registers[destination_register] = value
+ end
+
+ def increment (destination_register, value = 1)
+ value = value.kind_of?(Symbol) ? @registers[value] : value
+ @registers[destination_register] += value
+ end
+
+ def decrement (destination_register, value = 1)
+ value = value.kind_of?(Symbol) ? @registers[value] : value
+ @registers[destination_register] -= value
+ end
+
+ def compare (register, value)
+ value = value.kind_of?(Symbol) ? @registers[value] : value
+ @last_compare = @registers[register] - value
+ end
+
+ def add_label (label_name)
+ label_name
+ end
+end
+
+module DefaultInstructions
+ include DefaultExecutableInstructions
+ def mov (destination_register, source)
+ @instruction_number += 1
+ @instructions << [:move, [destination_register, source], @instruction_number]
+ end
+
+ def inc (destination_register, value = 1)
+ @instruction_number += 1
+ @instructions << [:increment, [destination_register, value], @instruction_number]
+ end
+
+ def dec (destination_register, value = 1)
+ @instruction_number += 1
+ @instructions << [:decrement, [destination_register, value], @instruction_number]
+ end
+
+ def cmp (register, value)
+ @instruction_number += 1
+ @instructions << [:compare, [register, value], @instruction_number]
+ end
+
+ def label (label_name)
+ @instructions << [:add_label, [label_name], label_name]
+ end
+end
+
+module ExecutableJumpInstructions
+ def jump (where)
+ where
+ end
+
+ def jump_equal (where)
+ @last_compare == 0 ? where : -1
+ end
+
+ def jump_not_equal (where)
+ @last_compare != 0 ? where : -1
+ end
+
+ def jump_less (where)
+ @last_compare < 0 ? where : -1
+ end
+
+ def jump_less_equal (where)
+ @last_compare <= 0 ? where : -1
+ end
+
+ def jump_greater (where)
+ @last_compare > 0 ? where : -1
+ end
+
+ def jump_greater_equal (where)
+ @last_compare >= 0 ? where : -1
+ end
+end
+
+module JumpInstructions
+ include ExecutableJumpInstructions
+ def jmp (where)
+ @instruction_number += 1
+ @instructions << [:jump, [where], @instruction_number, :jump]
+ end
+
+ def je (where)
+ @instruction_number += 1
+ @instructions << [:jump_equal, [where], @instruction_number, :jump]
+ end
+
+ def jne (where)
+ @instruction_number += 1
+ @instructions << [:jump_not_equal, [where], @instruction_number, :jump]
+ end
+
+ def jl (where)
+ @instruction_number += 1
+ @instructions << [:jump_less, [where], @instruction_number, :jump]
+ end
+
+ def jle (where)
+ @instruction_number += 1
+ @instructions << [:jump_less_equal, [where], @instruction_number, :jump]
+ end
+
+ def jg (where)
+ @instruction_number += 1
+ @instructions << [:jump_greater, [where], @instruction_number, :jump]
+ end
+
+ def jge (where)
+ @instruction_number += 1
+ @instructions << [:jump_greater_equal, [where], @instruction_number, :jump]
+ end
+
+end
+
+
+module Asm
+ class Execute
+ include DefaultInstructions
+ include JumpInstructions
+
+ def initialize
+ @registers = {ax: 0, bx: 0, cx: 0, dx: 0}
+ @instructions = []
+ @instruction_number = -1
+ @last_compare = 0
+ end
+
+ def execute
+ i = 0
+ while i < @instructions.length do
+ i = check_for_jumps(@instructions[i], i)
+ end
+ @registers.values.to_a
+ end
+
+ def check_for_jumps (current, i)
+ if current[3] == :jump
+ i = search_for_index(current, i)
+ else
+ i += 1
+ public_send current[0], *current[1]
+ end
+ i
+ end
+
+ def search_for_index (current, i)
+ previous_i = i
+ index_where = public_send current[0], *current[1]
+ if index_where != -1
+ @instructions.each_with_index do |instruction, index|
+ i = index if instruction[2] == index_where
+ end
+ end
+ i += 1 if previous_i == i
+ i
+ end
+
+ def method_missing (method_name, *args, &block)
+ method_name
+ end
+ end
+
+ def self.asm(&block)
+ executor = Execute.new
+ executor.instance_eval &block
+ executor.execute
+ end
+end
+
+Asm.asm do
+ mov ax, 40
+ mov bx, 32
+ label cycle
+ cmp ax, bx
+ je finish
+ jl asmaller
+ dec ax, bx
+ jmp cycle
+ label asmaller
+ dec bx, ax
+ jmp cycle
+ label finish
+end
+
+Asm.asm do
+ mov ax, 2
+ mov bx, 2
+ cmp ax, bx
+ je 5
+ mov cx, 3
+ mov dx, 3
+end