Class: Haxor::Vm::Os

Inherits:
Subsystem show all
Defined in:
lib/haxor/vm/os.rb

Constant Summary collapse

TABLE =
{
  0x01 => :sys_exit,
  0x02 => :sys_printf,
  0x03 => :sys_scanf,
  0x04 => :sys_rand
}

Instance Attribute Summary

Attributes inherited from Subsystem

#vm

Instance Method Summary collapse

Methods inherited from Subsystem

#register, #subsystem

Instance Method Details

#collect_string(addr) ⇒ Object



16
17
18
19
20
21
22
23
24
25
26
27
28
# File 'lib/haxor/vm/os.rb', line 16

def collect_string(addr)
  i = 0
  string = ''
  loop do
    char = @vm.subsystem(:mem).read(addr + i)
    break if char == 0
    string << char.ord

    i += Consts::WORD_SIZE
  end

  string
end

#parse_format(fmt) ⇒ Object



30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
# File 'lib/haxor/vm/os.rb', line 30

def parse_format(fmt)
  fmt = fmt.tr '^A-Za-z%', ''
  fmt = fmt.gsub '%%', ''

  types = []
  last_char = nil
  fmt.each_char do |char|
    if last_char == '%'
      if %w(b B d i o u x X).include? char
        types << :integer
      elsif %w(c s).include? char
        types << :string
      else
        fail
      end
    end

    last_char = char
  end

  types
end

#sys_exit ⇒ Object



53
54
55
56
# File 'lib/haxor/vm/os.rb', line 53

def sys_exit
  code = subsystem(:stack).pop_value
  exit code
end

#sys_printf ⇒ Object



58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
# File 'lib/haxor/vm/os.rb', line 58

def sys_printf
  fd = subsystem(:stack).pop_value

  x = subsystem(:stack).pop_value
  fmt = collect_string x
  args = []
  parse_format(fmt).each do |type|
    case type
    when :string
      args << collect_string(subsystem(:stack).pop_value)
    when :integer
      args << subsystem(:stack).pop_value
    else
      fail
    end
  end

  file = IO.new(fd, 'a')
  file.write sprintf(fmt, *args)
end

#sys_rand ⇒ Object



106
107
108
109
110
111
112
# File 'lib/haxor/vm/os.rb', line 106

def sys_rand
  min = subsystem(:stack).pop_value
  max = subsystem(:stack).pop_value

  prng = Random.new
  subsystem(:stack).push_value prng.rand(min..max)
end

#sys_scanf ⇒ Object



79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
# File 'lib/haxor/vm/os.rb', line 79

def sys_scanf
  fd = subsystem(:stack).pop_value
  fmt = collect_string subsystem(:stack).pop_value
  types = parse_format fmt

  file = IO.new(fd, 'r')
  result = file.scanf fmt

  if result.size != types.size
    subsystem(:mem).write 'sc', -1
    return
  end

  types.each do |type|
    value = result.shift

    case type
    when :string
      subsystem(:mem).write_string subsystem(:stack).pop_value, value
    when :integer
      subsystem(:mem).write subsystem(:stack).pop_value, value
    else
      fail
    end
  end
end

#syscall ⇒ Object



11
12
13
14
# File 'lib/haxor/vm/os.rb', line 11

def syscall
  func = subsystem(:mem).read 'sc'
  send(TABLE[func])
end