haxor 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (49) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +11 -0
  3. data/.travis.yml +4 -0
  4. data/Gemfile +4 -0
  5. data/LICENSE.txt +27 -0
  6. data/README.md +414 -0
  7. data/Rakefile +1 -0
  8. data/bin/hcc +21 -0
  9. data/bin/hld +38 -0
  10. data/bin/hvm +17 -0
  11. data/examples/build.sh +10 -0
  12. data/examples/guess-the-number.hax +100 -0
  13. data/haxor.gemspec +24 -0
  14. data/lib/haxor.rb +44 -0
  15. data/lib/haxor/compiler/component/arithmetic.rb +55 -0
  16. data/lib/haxor/compiler/component/base.rb +37 -0
  17. data/lib/haxor/compiler/component/data.rb +32 -0
  18. data/lib/haxor/compiler/component/jumps.rb +95 -0
  19. data/lib/haxor/compiler/component/logical.rb +43 -0
  20. data/lib/haxor/compiler/component/other.rb +21 -0
  21. data/lib/haxor/compiler/component/transfer.rb +29 -0
  22. data/lib/haxor/compiler/component/various.rb +33 -0
  23. data/lib/haxor/compiler/core.rb +134 -0
  24. data/lib/haxor/compiler/section.rb +6 -0
  25. data/lib/haxor/compiler/unit.rb +39 -0
  26. data/lib/haxor/consts.rb +28 -0
  27. data/lib/haxor/header.rb +40 -0
  28. data/lib/haxor/linker.rb +89 -0
  29. data/lib/haxor/token/base.rb +7 -0
  30. data/lib/haxor/token/cmd.rb +9 -0
  31. data/lib/haxor/token/data.rb +17 -0
  32. data/lib/haxor/token/int64.rb +17 -0
  33. data/lib/haxor/token/label.rb +23 -0
  34. data/lib/haxor/token/pointer.rb +13 -0
  35. data/lib/haxor/vm/core.rb +53 -0
  36. data/lib/haxor/vm/cpu/core.rb +129 -0
  37. data/lib/haxor/vm/cpu/unit/arithmetic.rb +92 -0
  38. data/lib/haxor/vm/cpu/unit/base.rb +46 -0
  39. data/lib/haxor/vm/cpu/unit/jumps.rb +123 -0
  40. data/lib/haxor/vm/cpu/unit/logical.rb +59 -0
  41. data/lib/haxor/vm/cpu/unit/transfer.rb +37 -0
  42. data/lib/haxor/vm/cpu/unit/various.rb +47 -0
  43. data/lib/haxor/vm/mem.rb +101 -0
  44. data/lib/haxor/vm/os.rb +115 -0
  45. data/lib/haxor/vm/stack.rb +31 -0
  46. data/lib/haxor/vm/subsystem.rb +16 -0
  47. data/media/memory.png +0 -0
  48. data/media/vm.png +0 -0
  49. metadata +122 -0
@@ -0,0 +1,7 @@
1
+ module Haxor
2
+ module Token
3
+ class Base
4
+ attr_accessor :absolute_addr
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,9 @@
1
+ module Haxor
2
+ module Token
3
+ class Cmd < Int64
4
+ def to_s
5
+ "Cmd -> 0x#{@data.to_s(16)}"
6
+ end
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,17 @@
1
+ module Haxor
2
+ module Token
3
+ class Data < Base
4
+ def initialize(data)
5
+ @data = data
6
+ end
7
+
8
+ def size
9
+ @data.size
10
+ end
11
+
12
+ def to_s
13
+ @data.to_s
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,17 @@
1
+ module Haxor
2
+ module Token
3
+ class Int64 < Data
4
+ def to_bytecode
5
+ [@data].pack('q<')
6
+ end
7
+
8
+ def size
9
+ 8
10
+ end
11
+
12
+ def to_s
13
+ "int64 -> #{@data}"
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,23 @@
1
+ module Haxor
2
+ module Token
3
+ class Label < Base
4
+ attr_reader :label
5
+
6
+ def initialize(label)
7
+ @label = label
8
+ end
9
+
10
+ def to_bytecode
11
+ ''
12
+ end
13
+
14
+ def to_s
15
+ "Label -> #{@label}"
16
+ end
17
+
18
+ def size
19
+ 0
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,13 @@
1
+ module Haxor
2
+ module Token
3
+ class Pointer < Int64
4
+ attr_accessor :data
5
+ attr_reader :label
6
+
7
+ def initialize(label)
8
+ super(-1) # invalid pointer
9
+ @label = label
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,53 @@
1
+ module Haxor
2
+ module Vm
3
+ class Core
4
+ attr_reader :mem
5
+
6
+ def initialize
7
+ @subsystems = {}
8
+ register_subsystem :cpu, Cpu::Core.new
9
+ register_subsystem :mem, Mem.new(Consts::RESERVED_MEM)
10
+ register_subsystem :stack, Stack.new
11
+ register_subsystem :os, Os.new
12
+
13
+ subsystem(:cpu).labels.each do |_, label|
14
+ subsystem(:mem).add_label label.label, label.absolute_addr
15
+ end
16
+
17
+ @units = []
18
+ @opcodes = {}
19
+ end
20
+
21
+ def register_subsystem(id, object)
22
+ @subsystems[id] = object
23
+ object.vm = self
24
+ end
25
+
26
+ def subsystem(id)
27
+ @subsystems[id]
28
+ end
29
+
30
+ def execute
31
+ loop do
32
+ subsystem(:cpu).iterate
33
+ end
34
+ end
35
+
36
+ def load_program(filename)
37
+ exe = File.read(filename, encoding: 'ASCII-8BIT')
38
+
39
+ @hdr = Header.new
40
+ @hdr.parse! exe
41
+
42
+ fail if @hdr.version != Consts::VERSION
43
+
44
+ exe = exe[@hdr.size..-1] # cut off header
45
+ subsystem(:mem).replace_region Consts::RESERVED_MEM, exe
46
+ subsystem(:mem).write 'ip', @hdr.entry_point # instruction pointer
47
+ subsystem(:mem).enlarge @hdr.bss_size
48
+ subsystem(:mem).enlarge @hdr.stack_size
49
+ subsystem(:mem).write 'sp', subsystem(:mem).size
50
+ end
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,129 @@
1
+ module Haxor
2
+ module Vm
3
+ module Cpu
4
+ class Core < Subsystem
5
+ attr_reader :struct
6
+ attr_reader :labels
7
+
8
+ def initialize
9
+ @units = []
10
+ @opcodes = {}
11
+
12
+ register_unit Unit::Arithmetic.new
13
+ register_unit Unit::Jumps.new
14
+ register_unit Unit::Logical.new
15
+ register_unit Unit::Transfer.new
16
+ register_unit Unit::Various.new
17
+
18
+ build_struct
19
+ end
20
+
21
+ def bind_opcode(opcode, object, method)
22
+ fail "OpCode already defined - #{opcode}." if @opcodes.key? opcode
23
+ @opcodes[opcode] = {
24
+ object: object,
25
+ method: method
26
+ }
27
+ end
28
+
29
+ def iterate
30
+ opcode = subsystem(:mem).next_cell
31
+ cmd = opcode & Consts::OPCODE_CMD_MASK
32
+ subsystem(:mem).write 'op', opcode
33
+
34
+ fail "Call to not existing opcode #{cmd}." unless @opcodes.key? cmd
35
+ # puts 'cmd = ' + cmd.to_s(16)
36
+ # puts flg.to_s(16)
37
+ @opcodes[cmd][:object].send(@opcodes[cmd][:method])
38
+ end
39
+
40
+ def reserved_mem
41
+ 1024
42
+ end
43
+
44
+ def register_unit(unit)
45
+ @units << unit
46
+ unit.vm = self
47
+ unit.register
48
+ end
49
+
50
+ def operand
51
+ flg = (subsystem(:mem).read 'op') & Consts::OPCODE_FLG_MASK
52
+ a = subsystem(:mem).next_cell
53
+ a = subsystem(:mem).read a if (flg & Consts::OPCODE_FLG_DA != 0)
54
+ a
55
+ end
56
+
57
+ def operands
58
+ flg = (subsystem(:mem).read 'op') & Consts::OPCODE_FLG_MASK
59
+
60
+ a = subsystem(:mem).next_cell
61
+ a = subsystem(:mem).read a if (flg & Consts::OPCODE_FLG_DA != 0)
62
+
63
+ b = subsystem(:mem).next_cell
64
+ b = subsystem(:mem).read b if (flg & Consts::OPCODE_FLG_DB != 0)
65
+
66
+ [a, b]
67
+ end
68
+
69
+ private
70
+
71
+ def build_struct
72
+ @struct = []
73
+
74
+ @struct << Token::Label.new('null')
75
+ @struct << Token::Int64.new(0)
76
+
77
+ @struct << Token::Label.new('registers')
78
+
79
+ # instruction pointer
80
+ @struct << Token::Label.new('ip')
81
+ @struct << Token::Int64.new(0)
82
+
83
+ # stack pointer
84
+ @struct << Token::Label.new('sp')
85
+ @struct << Token::Int64.new(0)
86
+
87
+ # base pointer
88
+ @struct << Token::Label.new('bp')
89
+ @struct << Token::Int64.new(0)
90
+
91
+ # arithmetic registry I
92
+ @struct << Token::Label.new('ar')
93
+ @struct << Token::Int64.new(0)
94
+
95
+ # arithmetic registry II
96
+ @struct << Token::Label.new('dr')
97
+ @struct << Token::Int64.new(0)
98
+
99
+ # flags registry
100
+ @struct << Token::Label.new('fr')
101
+ @struct << Token::Int64.new(0)
102
+
103
+ # currently processed opcode (with opcode flags)
104
+ @struct << Token::Label.new('op')
105
+ @struct << Token::Int64.new(0)
106
+
107
+ # system call
108
+ @struct << Token::Label.new('sc')
109
+ @struct << Token::Int64.new(0)
110
+
111
+ # general usage registers
112
+ (1..10).each do |i|
113
+ @struct << Token::Label.new(format('r%02d', i))
114
+ @struct << Token::Int64.new(0)
115
+ end
116
+
117
+ addr = 0
118
+ @labels = {}
119
+ @struct.each do |token|
120
+ token.absolute_addr = addr
121
+ addr += token.size
122
+
123
+ @labels[token.label] = token if token.is_a? Token::Label
124
+ end
125
+ end
126
+ end
127
+ end
128
+ end
129
+ end
@@ -0,0 +1,92 @@
1
+ module Haxor
2
+ module Vm
3
+ module Cpu
4
+ module Unit
5
+ class Arithmetic < Base
6
+ # 0x00 (not used)
7
+ OP_ADD = 0x01 # add a, b
8
+ OP_SUB = 0x02 # sub a, b
9
+ OP_DIV = 0x03 # div a
10
+ OP_MUL = 0x04 # mul a
11
+ OP_INC = 0x05 # inc a
12
+ OP_DEC = 0x06 # dec a
13
+ OP_CMP = 0x07 # cmp a, b
14
+ # 0x1f
15
+
16
+ def register
17
+ bind_opcode OP_ADD, :op_add
18
+ bind_opcode OP_SUB, :op_sub
19
+ bind_opcode OP_DIV, :op_div
20
+ bind_opcode OP_MUL, :op_mul
21
+ bind_opcode OP_INC, :op_inc
22
+ bind_opcode OP_DEC, :op_dec
23
+ bind_opcode OP_CMP, :op_cmp
24
+ end
25
+
26
+ def op_add
27
+ a, b = operands
28
+ c = @vm.subsystem(:mem).read(a) + @vm.subsystem(:mem).read(b)
29
+ @vm.subsystem(:mem).write a, c
30
+ end
31
+
32
+ def op_sub
33
+ a, b = operands
34
+ c = @vm.subsystem(:mem).read(a) - @vm.subsystem(:mem).read(b)
35
+ @vm.subsystem(:mem).write a, c
36
+ end
37
+
38
+ def op_div
39
+ a = operand
40
+ av = @vm.subsystem(:mem).read a
41
+ arv = @vm.subsystem(:mem).read 'ar'
42
+ @vm.subsystem(:mem).write 'ar', (arv / av)
43
+ @vm.subsystem(:mem).write 'dr', (arv % av)
44
+ end
45
+
46
+ def op_mul
47
+ a = operand
48
+ av = @vm.subsystem(:mem).read a
49
+ arv = @vm.subsystem(:mem).read 'ar'
50
+ @vm.subsystem(:mem).write 'ar', (arv * av)
51
+ end
52
+
53
+ def op_inc
54
+ a = operand
55
+ av = @vm.subsystem(:mem).read a
56
+ @vm.subsystem(:mem).write a, (av + 1)
57
+ end
58
+
59
+ def op_dec
60
+ a = operand
61
+ av = @vm.subsystem(:mem).read a
62
+ @vm.subsystem(:mem).write a, (av - 1)
63
+ end
64
+
65
+ def op_cmp
66
+ a, b = operands
67
+ av = @vm.subsystem(:mem).read a
68
+ bv = @vm.subsystem(:mem).read b
69
+ v = av - bv
70
+ fr_set Consts::FR_ZERO, (v == 0)
71
+ fr_set Consts::FR_SIGN, v < 0
72
+ end
73
+
74
+ def fr_set(b, enable)
75
+ flags = fetch_cell 'fr'
76
+ if enable
77
+ flags |= b
78
+ else
79
+ flags &= ~b
80
+ end
81
+ replace_cell 'fr', flags
82
+ end
83
+
84
+ def fr_if(b)
85
+ flags = fetch_cell 'fr'
86
+ (flags & b) > 0
87
+ end
88
+ end
89
+ end
90
+ end
91
+ end
92
+ end
@@ -0,0 +1,46 @@
1
+ module Haxor
2
+ module Vm
3
+ module Cpu
4
+ module Unit
5
+ class Base
6
+ attr_accessor :vm
7
+
8
+ def register
9
+ fail 'this method must be implemented.'
10
+ end
11
+
12
+ def bind_opcode(opcode, method)
13
+ @vm.bind_opcode opcode, self, method
14
+ end
15
+
16
+ # TODO: BC
17
+ def next_cell
18
+ @vm.subsystem(:mem).next_word
19
+ end
20
+
21
+ # TODO: BC
22
+ def fetch_cell(addr)
23
+ @vm.subsystem(:mem).read addr
24
+ end
25
+
26
+ def dereference(addr)
27
+ @vm.subsystem(:mem).read addr
28
+ end
29
+
30
+ # TODO: BC
31
+ def replace_cell(addr, value)
32
+ @vm.subsystem(:mem).write addr, value
33
+ end
34
+
35
+ def operand
36
+ @vm.operand
37
+ end
38
+
39
+ def operands
40
+ @vm.operands
41
+ end
42
+ end
43
+ end
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,123 @@
1
+ module Haxor
2
+ module Vm
3
+ module Cpu
4
+ module Unit
5
+ class Jumps < Base
6
+ # 0x20
7
+ OP_CALL = 0x20 # call a
8
+ OP_JMP = 0x21 # jmp a
9
+ OP_JE = 0x22 # je a
10
+ OP_JG = 0x23 # jg a
11
+ OP_JGE = 0x24 # jge a
12
+ OP_JL = 0x25 # jl a
13
+ OP_JLE = 0x26 # jle a
14
+ OP_JNE = 0x27 # jne a
15
+ OP_JNG = 0x28 # jng a
16
+ OP_JNGE = 0x29 # jnge a
17
+ OP_JNL = 0x2a # jnl a
18
+ OP_JNLE = 0x2b # jnle a
19
+ OP_RET = 0x2c # ret
20
+ OP_IRET = 0x2d # iret
21
+ # 0x3f
22
+
23
+ def register
24
+ bind_opcode OP_CALL, :op_call
25
+ bind_opcode OP_JMP, :op_jmp
26
+ bind_opcode OP_JE, :op_je
27
+ bind_opcode OP_JG, :op_jg
28
+ bind_opcode OP_JGE, :op_jge
29
+ bind_opcode OP_JL, :op_jl
30
+ bind_opcode OP_JLE, :op_jle
31
+ bind_opcode OP_JNE, :op_jne
32
+ bind_opcode OP_JNG, :op_jng
33
+ bind_opcode OP_JNGE, :op_jnge
34
+ bind_opcode OP_JNL, :op_jnl
35
+ bind_opcode OP_JNLE, :op_jnle
36
+ bind_opcode OP_RET, :op_ret
37
+ bind_opcode OP_IRET, :op_iret
38
+ end
39
+
40
+ def fr_if(b)
41
+ flags = fetch_cell 'fr'
42
+ (flags & b) > 0
43
+ end
44
+
45
+ def op_call
46
+ a = operand
47
+ @vm.subsystem(:stack).push 'ip'
48
+ jmp a
49
+ end
50
+
51
+ def op_jmp
52
+ a = operand
53
+ jmp a
54
+ end
55
+
56
+ def op_je
57
+ a = operand
58
+ jmp a if fr_if Consts::FR_ZERO
59
+ end
60
+
61
+ def op_jg
62
+ a = operand
63
+ jmp a if !fr_if(Consts::FR_ZERO) && !fr_if(Consts::FR_SIGN)
64
+ end
65
+
66
+ def op_jge
67
+ a = operand
68
+ jmp a if !fr_if(Consts::FR_SIGN) || fr_if(Consts::FR_ZERO)
69
+ end
70
+
71
+ def op_jl
72
+ a = operand
73
+ jmp a if !fr_if(Consts::FR_ZERO) && fr_if(Consts::FR_SIGN)
74
+ end
75
+
76
+ def op_jle
77
+ a = operand
78
+ jmp a if fr_if(Consts::FR_SIGN) || fr_if(Consts::FR_ZERO)
79
+ end
80
+
81
+ def op_jne
82
+ a = operand
83
+ jmp a unless fr_if Consts::FR_ZERO
84
+ end
85
+
86
+ def op_jng
87
+ a = operand
88
+ jmp a unless !fr_if(Consts::FR_ZERO) && !fr_if(Consts::FR_SIGN)
89
+ end
90
+
91
+ def op_jnge
92
+ a = operand
93
+ jmp a unless !fr_if(Consts::FR_SIGN) || fr_if(Consts::FR_ZERO)
94
+ end
95
+
96
+ def op_jnl
97
+ a = operand
98
+ jmp a unless !fr_if(Consts::FR_ZERO) && fr_if(Consts::FR_SIGN)
99
+ end
100
+
101
+ def op_jnle
102
+ a = operand
103
+ jmp a unless fr_if(Consts::FR_SIGN) || fr_if(Consts::FR_ZERO)
104
+ end
105
+
106
+ def op_ret
107
+ @vm.subsystem(:stack).pop 'ip'
108
+ end
109
+
110
+ def op_iret
111
+ @vm.subsystem(:stack).pop 'ip'
112
+ end
113
+
114
+ private
115
+
116
+ def jmp(addr)
117
+ @vm.subsystem(:mem).write 'ip', addr
118
+ end
119
+ end
120
+ end
121
+ end
122
+ end
123
+ end