haxor 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gitignore +11 -0
- data/.travis.yml +4 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +27 -0
- data/README.md +414 -0
- data/Rakefile +1 -0
- data/bin/hcc +21 -0
- data/bin/hld +38 -0
- data/bin/hvm +17 -0
- data/examples/build.sh +10 -0
- data/examples/guess-the-number.hax +100 -0
- data/haxor.gemspec +24 -0
- data/lib/haxor.rb +44 -0
- data/lib/haxor/compiler/component/arithmetic.rb +55 -0
- data/lib/haxor/compiler/component/base.rb +37 -0
- data/lib/haxor/compiler/component/data.rb +32 -0
- data/lib/haxor/compiler/component/jumps.rb +95 -0
- data/lib/haxor/compiler/component/logical.rb +43 -0
- data/lib/haxor/compiler/component/other.rb +21 -0
- data/lib/haxor/compiler/component/transfer.rb +29 -0
- data/lib/haxor/compiler/component/various.rb +33 -0
- data/lib/haxor/compiler/core.rb +134 -0
- data/lib/haxor/compiler/section.rb +6 -0
- data/lib/haxor/compiler/unit.rb +39 -0
- data/lib/haxor/consts.rb +28 -0
- data/lib/haxor/header.rb +40 -0
- data/lib/haxor/linker.rb +89 -0
- data/lib/haxor/token/base.rb +7 -0
- data/lib/haxor/token/cmd.rb +9 -0
- data/lib/haxor/token/data.rb +17 -0
- data/lib/haxor/token/int64.rb +17 -0
- data/lib/haxor/token/label.rb +23 -0
- data/lib/haxor/token/pointer.rb +13 -0
- data/lib/haxor/vm/core.rb +53 -0
- data/lib/haxor/vm/cpu/core.rb +129 -0
- data/lib/haxor/vm/cpu/unit/arithmetic.rb +92 -0
- data/lib/haxor/vm/cpu/unit/base.rb +46 -0
- data/lib/haxor/vm/cpu/unit/jumps.rb +123 -0
- data/lib/haxor/vm/cpu/unit/logical.rb +59 -0
- data/lib/haxor/vm/cpu/unit/transfer.rb +37 -0
- data/lib/haxor/vm/cpu/unit/various.rb +47 -0
- data/lib/haxor/vm/mem.rb +101 -0
- data/lib/haxor/vm/os.rb +115 -0
- data/lib/haxor/vm/stack.rb +31 -0
- data/lib/haxor/vm/subsystem.rb +16 -0
- data/media/memory.png +0 -0
- data/media/vm.png +0 -0
- metadata +122 -0
@@ -0,0 +1,59 @@
|
|
1
|
+
module Haxor
|
2
|
+
module Vm
|
3
|
+
module Cpu
|
4
|
+
module Unit
|
5
|
+
class Logical < Base
|
6
|
+
# 0x40
|
7
|
+
OP_AND = 0x40 # and a, b
|
8
|
+
OP_NEG = 0x41 # neg a
|
9
|
+
OP_NOT = 0x42 # not a
|
10
|
+
OP_OR = 0x43 # or a, b
|
11
|
+
OP_XOR = 0x44 # xor a, b
|
12
|
+
# 0x5f
|
13
|
+
|
14
|
+
def register
|
15
|
+
bind_opcode OP_AND, :op_and
|
16
|
+
bind_opcode OP_NEG, :op_neg
|
17
|
+
bind_opcode OP_NOT, :op_not
|
18
|
+
bind_opcode OP_OR, :op_or
|
19
|
+
bind_opcode OP_XOR, :op_xor
|
20
|
+
end
|
21
|
+
|
22
|
+
def op_and
|
23
|
+
a, b = operands
|
24
|
+
av = @vm.subsystem(:mem).read a
|
25
|
+
bv = @vm.subsystem(:mem).read b
|
26
|
+
v = av & bv
|
27
|
+
@vm.subsystem(:mem).write a, v
|
28
|
+
end
|
29
|
+
|
30
|
+
def op_neg
|
31
|
+
a = operand
|
32
|
+
av = @vm.subsystem(:mem).read a
|
33
|
+
@vm.subsystem(:mem).write a, -av
|
34
|
+
end
|
35
|
+
|
36
|
+
def op_not
|
37
|
+
a = operand
|
38
|
+
av = @vm.subsystem(:mem).read a
|
39
|
+
@vm.subsystem(:mem).write a, ~av
|
40
|
+
end
|
41
|
+
|
42
|
+
def op_or
|
43
|
+
a, b = operands
|
44
|
+
av = @vm.subsystem(:mem).read a
|
45
|
+
bv = @vm.subsystem(:mem).read b
|
46
|
+
@vm.subsystem(:mem).write a, (av | bv)
|
47
|
+
end
|
48
|
+
|
49
|
+
def op_xor
|
50
|
+
a, b = operands
|
51
|
+
av = @vm.subsystem(:mem).read a
|
52
|
+
bv = @vm.subsystem(:mem).read b
|
53
|
+
@vm.subsystem(:mem).write a, (av ^ bv)
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
module Haxor
|
2
|
+
module Vm
|
3
|
+
module Cpu
|
4
|
+
module Unit
|
5
|
+
class Transfer < Base
|
6
|
+
# 0x60
|
7
|
+
OP_MOV = 0x60 # mov a, b
|
8
|
+
OP_PUSH = 0x61 # push a
|
9
|
+
OP_POP = 0x62 # pop a
|
10
|
+
# 0x7f
|
11
|
+
|
12
|
+
def register
|
13
|
+
bind_opcode OP_MOV, :op_mov
|
14
|
+
bind_opcode OP_PUSH, :op_push
|
15
|
+
bind_opcode OP_POP, :op_pop
|
16
|
+
end
|
17
|
+
|
18
|
+
def op_mov
|
19
|
+
a, b = operands
|
20
|
+
v = @vm.subsystem(:mem).read b
|
21
|
+
@vm.subsystem(:mem).write a, v
|
22
|
+
end
|
23
|
+
|
24
|
+
def op_push
|
25
|
+
a = operand
|
26
|
+
@vm.subsystem(:stack).push a
|
27
|
+
end
|
28
|
+
|
29
|
+
def op_pop
|
30
|
+
a = operand
|
31
|
+
@vm.subsystem(:stack).pop a
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
module Haxor
|
2
|
+
module Vm
|
3
|
+
module Cpu
|
4
|
+
module Unit
|
5
|
+
class Various < Base
|
6
|
+
# = 0x80
|
7
|
+
OP_LEA = 0x80 # lea a
|
8
|
+
OP_NOP = 0x81 # nop
|
9
|
+
OP_INT = 0x85 # int a
|
10
|
+
OP_SYSCALL = 0x86 # syscall
|
11
|
+
# 0x9f
|
12
|
+
|
13
|
+
def register
|
14
|
+
bind_opcode OP_LEA, :op_lea
|
15
|
+
bind_opcode OP_NOP, :op_nop
|
16
|
+
bind_opcode OP_INT, :op_int
|
17
|
+
bind_opcode OP_SYSCALL, :op_syscall
|
18
|
+
end
|
19
|
+
|
20
|
+
def op_lea
|
21
|
+
a, b = operands
|
22
|
+
@vm.subsystem(:mem).write a, b
|
23
|
+
end
|
24
|
+
|
25
|
+
def op_nop
|
26
|
+
# intentionally nothing here
|
27
|
+
end
|
28
|
+
|
29
|
+
def op_int
|
30
|
+
a = operand
|
31
|
+
|
32
|
+
@vm.subsystem(:stack).push 'ip'
|
33
|
+
|
34
|
+
av = @vm.subsystem(:mem).read a
|
35
|
+
ivt = Consts::IVT_ADDR + (av * 8)
|
36
|
+
handler = @vm.subsystem(:mem).read ivt
|
37
|
+
@vm.subsystem(:mem).write 'ip', handler
|
38
|
+
end
|
39
|
+
|
40
|
+
def op_syscall
|
41
|
+
@vm.subsystem(:os).syscall
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
data/lib/haxor/vm/mem.rb
ADDED
@@ -0,0 +1,101 @@
|
|
1
|
+
module Haxor
|
2
|
+
module Vm
|
3
|
+
class Mem < Subsystem
|
4
|
+
attr_accessor :memory
|
5
|
+
|
6
|
+
def initialize(bytes)
|
7
|
+
@memory = Array.new(bytes, 0).pack('C*')
|
8
|
+
@labels = {}
|
9
|
+
end
|
10
|
+
|
11
|
+
def size
|
12
|
+
@memory.size
|
13
|
+
end
|
14
|
+
|
15
|
+
def enlarge(bytes)
|
16
|
+
replace_region size, Array.new(bytes, 0).pack('C*')
|
17
|
+
end
|
18
|
+
|
19
|
+
# Adds label
|
20
|
+
#
|
21
|
+
# @param name [String] Name of label
|
22
|
+
# @param addr [Integer] Address in memory to point to
|
23
|
+
def add_label(name, addr)
|
24
|
+
fail if @labels.key? name
|
25
|
+
@labels[name] = addr
|
26
|
+
end
|
27
|
+
|
28
|
+
# Reads word from memory
|
29
|
+
#
|
30
|
+
# @param addr [String|Integer] Label or address in memory
|
31
|
+
# @return [Integer] Data stored under specified address
|
32
|
+
def read(addr)
|
33
|
+
@memory[resolve addr].unpack(Consts::WORD_UNPACK)[0]
|
34
|
+
end
|
35
|
+
|
36
|
+
# Writes word to memory
|
37
|
+
#
|
38
|
+
# @param addr [String|Integer] Label or address in memory
|
39
|
+
# @param value [Integer] Data to store under specified address
|
40
|
+
def write(addr, value)
|
41
|
+
@memory[resolve addr] = [value].pack(Consts::WORD_UNPACK)
|
42
|
+
end
|
43
|
+
|
44
|
+
def write_string(addr, value)
|
45
|
+
i = 0
|
46
|
+
value.each_char do |x|
|
47
|
+
write addr + i, x.ord
|
48
|
+
i += Consts::WORD_SIZE
|
49
|
+
end
|
50
|
+
|
51
|
+
write addr + i, 0
|
52
|
+
end
|
53
|
+
|
54
|
+
def replace_region(addr, data)
|
55
|
+
x = addr + data.size
|
56
|
+
@memory[addr...x] = data
|
57
|
+
end
|
58
|
+
|
59
|
+
# (see #read)
|
60
|
+
def dereference(addr)
|
61
|
+
read addr
|
62
|
+
end
|
63
|
+
|
64
|
+
# Reads data pointed by IP register and moves IP forward
|
65
|
+
#
|
66
|
+
# @return [Integer] Data stored under address pointed by IP
|
67
|
+
def next_word
|
68
|
+
data = read ip
|
69
|
+
move_ip Consts::WORD_SIZE
|
70
|
+
data
|
71
|
+
end
|
72
|
+
|
73
|
+
# TODO: BC
|
74
|
+
def next_cell
|
75
|
+
next_word
|
76
|
+
end
|
77
|
+
|
78
|
+
def ip
|
79
|
+
read 'ip'
|
80
|
+
end
|
81
|
+
|
82
|
+
def move_ip(step)
|
83
|
+
write 'ip', ip + step
|
84
|
+
end
|
85
|
+
|
86
|
+
def label(name)
|
87
|
+
@labels[addr]
|
88
|
+
end
|
89
|
+
|
90
|
+
private
|
91
|
+
|
92
|
+
def resolve(addr)
|
93
|
+
if addr.is_a? String
|
94
|
+
fail "Unknown label #{addr}." unless @labels.key? addr
|
95
|
+
addr = @labels[addr]
|
96
|
+
end
|
97
|
+
Range.new(addr, addr + Consts::WORD_SIZE, true)
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
data/lib/haxor/vm/os.rb
ADDED
@@ -0,0 +1,115 @@
|
|
1
|
+
module Haxor
|
2
|
+
module Vm
|
3
|
+
class Os < Subsystem
|
4
|
+
TABLE = {
|
5
|
+
0x01 => :sys_exit,
|
6
|
+
0x02 => :sys_printf,
|
7
|
+
0x03 => :sys_scanf,
|
8
|
+
0x04 => :sys_rand
|
9
|
+
}
|
10
|
+
|
11
|
+
def syscall
|
12
|
+
func = subsystem(:mem).read 'sc'
|
13
|
+
send(TABLE[func])
|
14
|
+
end
|
15
|
+
|
16
|
+
def collect_string(addr)
|
17
|
+
i = 0
|
18
|
+
string = ''
|
19
|
+
loop do
|
20
|
+
char = @vm.subsystem(:mem).read(addr + i)
|
21
|
+
break if char == 0
|
22
|
+
string << char.ord
|
23
|
+
|
24
|
+
i += Consts::WORD_SIZE
|
25
|
+
end
|
26
|
+
|
27
|
+
string
|
28
|
+
end
|
29
|
+
|
30
|
+
def parse_format(fmt)
|
31
|
+
fmt = fmt.tr '^A-Za-z%', ''
|
32
|
+
fmt = fmt.gsub '%%', ''
|
33
|
+
|
34
|
+
types = []
|
35
|
+
last_char = nil
|
36
|
+
fmt.each_char do |char|
|
37
|
+
if last_char == '%'
|
38
|
+
if %w(b B d i o u x X).include? char
|
39
|
+
types << :integer
|
40
|
+
elsif %w(c s).include? char
|
41
|
+
types << :string
|
42
|
+
else
|
43
|
+
fail
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
last_char = char
|
48
|
+
end
|
49
|
+
|
50
|
+
types
|
51
|
+
end
|
52
|
+
|
53
|
+
def sys_exit
|
54
|
+
code = subsystem(:stack).pop_value
|
55
|
+
exit code
|
56
|
+
end
|
57
|
+
|
58
|
+
def sys_printf
|
59
|
+
fd = subsystem(:stack).pop_value
|
60
|
+
|
61
|
+
x = subsystem(:stack).pop_value
|
62
|
+
fmt = collect_string x
|
63
|
+
args = []
|
64
|
+
parse_format(fmt).each do |type|
|
65
|
+
case type
|
66
|
+
when :string
|
67
|
+
args << collect_string(subsystem(:stack).pop_value)
|
68
|
+
when :integer
|
69
|
+
args << subsystem(:stack).pop_value
|
70
|
+
else
|
71
|
+
fail
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
file = IO.new(fd, 'a')
|
76
|
+
file.write sprintf(fmt, *args)
|
77
|
+
end
|
78
|
+
|
79
|
+
def sys_scanf
|
80
|
+
fd = subsystem(:stack).pop_value
|
81
|
+
fmt = collect_string subsystem(:stack).pop_value
|
82
|
+
types = parse_format fmt
|
83
|
+
|
84
|
+
file = IO.new(fd, 'r')
|
85
|
+
result = file.scanf fmt
|
86
|
+
|
87
|
+
if result.size != types.size
|
88
|
+
subsystem(:mem).write 'sc', -1
|
89
|
+
return
|
90
|
+
end
|
91
|
+
|
92
|
+
types.each do |type|
|
93
|
+
value = result.shift
|
94
|
+
|
95
|
+
case type
|
96
|
+
when :string
|
97
|
+
subsystem(:mem).write_string subsystem(:stack).pop_value, value
|
98
|
+
when :integer
|
99
|
+
subsystem(:mem).write subsystem(:stack).pop_value, value
|
100
|
+
else
|
101
|
+
fail
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
def sys_rand
|
107
|
+
min = subsystem(:stack).pop_value
|
108
|
+
max = subsystem(:stack).pop_value
|
109
|
+
|
110
|
+
prng = Random.new
|
111
|
+
subsystem(:stack).push_value prng.rand(min..max)
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
module Haxor
|
2
|
+
module Vm
|
3
|
+
class Stack < Subsystem
|
4
|
+
def push(addr)
|
5
|
+
value = @vm.subsystem(:mem).read addr
|
6
|
+
push_value value
|
7
|
+
end
|
8
|
+
|
9
|
+
def push_value(value)
|
10
|
+
sp = @vm.subsystem(:mem).read 'sp'
|
11
|
+
sp -= Consts::WORD_SIZE
|
12
|
+
@vm.subsystem(:mem).write 'sp', sp
|
13
|
+
@vm.subsystem(:mem).write sp, value
|
14
|
+
end
|
15
|
+
|
16
|
+
def pop(addr)
|
17
|
+
value = pop_value
|
18
|
+
@vm.subsystem(:mem).write addr, value
|
19
|
+
end
|
20
|
+
|
21
|
+
def pop_value
|
22
|
+
sp = @vm.subsystem(:mem).read 'sp'
|
23
|
+
value = @vm.subsystem(:mem).read sp
|
24
|
+
sp += Consts::WORD_SIZE
|
25
|
+
@vm.subsystem(:mem).write 'sp', sp
|
26
|
+
|
27
|
+
value
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
data/media/memory.png
ADDED
Binary file
|
data/media/vm.png
ADDED
Binary file
|
metadata
ADDED
@@ -0,0 +1,122 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: haxor
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Krzysztof Magosa
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2015-12-29 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: bundler
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.10'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.10'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rake
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '10.0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '10.0'
|
41
|
+
description: Please follow to GitHub repository for more information.
|
42
|
+
email:
|
43
|
+
- krzysztof@magosa.pl
|
44
|
+
executables:
|
45
|
+
- hcc
|
46
|
+
- hld
|
47
|
+
- hvm
|
48
|
+
extensions: []
|
49
|
+
extra_rdoc_files: []
|
50
|
+
files:
|
51
|
+
- ".gitignore"
|
52
|
+
- ".travis.yml"
|
53
|
+
- Gemfile
|
54
|
+
- LICENSE.txt
|
55
|
+
- README.md
|
56
|
+
- Rakefile
|
57
|
+
- bin/hcc
|
58
|
+
- bin/hld
|
59
|
+
- bin/hvm
|
60
|
+
- examples/build.sh
|
61
|
+
- examples/guess-the-number.hax
|
62
|
+
- haxor.gemspec
|
63
|
+
- lib/haxor.rb
|
64
|
+
- lib/haxor/compiler/component/arithmetic.rb
|
65
|
+
- lib/haxor/compiler/component/base.rb
|
66
|
+
- lib/haxor/compiler/component/data.rb
|
67
|
+
- lib/haxor/compiler/component/jumps.rb
|
68
|
+
- lib/haxor/compiler/component/logical.rb
|
69
|
+
- lib/haxor/compiler/component/other.rb
|
70
|
+
- lib/haxor/compiler/component/transfer.rb
|
71
|
+
- lib/haxor/compiler/component/various.rb
|
72
|
+
- lib/haxor/compiler/core.rb
|
73
|
+
- lib/haxor/compiler/section.rb
|
74
|
+
- lib/haxor/compiler/unit.rb
|
75
|
+
- lib/haxor/consts.rb
|
76
|
+
- lib/haxor/header.rb
|
77
|
+
- lib/haxor/linker.rb
|
78
|
+
- lib/haxor/token/base.rb
|
79
|
+
- lib/haxor/token/cmd.rb
|
80
|
+
- lib/haxor/token/data.rb
|
81
|
+
- lib/haxor/token/int64.rb
|
82
|
+
- lib/haxor/token/label.rb
|
83
|
+
- lib/haxor/token/pointer.rb
|
84
|
+
- lib/haxor/vm/core.rb
|
85
|
+
- lib/haxor/vm/cpu/core.rb
|
86
|
+
- lib/haxor/vm/cpu/unit/arithmetic.rb
|
87
|
+
- lib/haxor/vm/cpu/unit/base.rb
|
88
|
+
- lib/haxor/vm/cpu/unit/jumps.rb
|
89
|
+
- lib/haxor/vm/cpu/unit/logical.rb
|
90
|
+
- lib/haxor/vm/cpu/unit/transfer.rb
|
91
|
+
- lib/haxor/vm/cpu/unit/various.rb
|
92
|
+
- lib/haxor/vm/mem.rb
|
93
|
+
- lib/haxor/vm/os.rb
|
94
|
+
- lib/haxor/vm/stack.rb
|
95
|
+
- lib/haxor/vm/subsystem.rb
|
96
|
+
- media/memory.png
|
97
|
+
- media/vm.png
|
98
|
+
homepage: https://github.com/krzysztof-magosa/haxor
|
99
|
+
licenses:
|
100
|
+
- BSD-3
|
101
|
+
metadata: {}
|
102
|
+
post_install_message:
|
103
|
+
rdoc_options: []
|
104
|
+
require_paths:
|
105
|
+
- lib
|
106
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - ">="
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '0'
|
111
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
112
|
+
requirements:
|
113
|
+
- - ">="
|
114
|
+
- !ruby/object:Gem::Version
|
115
|
+
version: '0'
|
116
|
+
requirements: []
|
117
|
+
rubyforge_project:
|
118
|
+
rubygems_version: 2.4.5.1
|
119
|
+
signing_key:
|
120
|
+
specification_version: 4
|
121
|
+
summary: Educational Assembly Language running on custom VM
|
122
|
+
test_files: []
|