haxor 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
data/Rakefile
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
data/bin/hcc
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
#! /usr/bin/env ruby
|
2
|
+
|
3
|
+
require_relative '../lib/haxor'
|
4
|
+
|
5
|
+
if ARGV[0].nil?
|
6
|
+
puts "You must specify .hax file to be compiled."
|
7
|
+
exit 1
|
8
|
+
end
|
9
|
+
|
10
|
+
source = File.absolute_path ARGV[0]
|
11
|
+
|
12
|
+
compiler = Haxor::Compiler::Core.new
|
13
|
+
compiler.register_unit Haxor::Compiler::Component::Arithmetic.new
|
14
|
+
compiler.register_unit Haxor::Compiler::Component::Data.new
|
15
|
+
compiler.register_unit Haxor::Compiler::Component::Jumps.new
|
16
|
+
compiler.register_unit Haxor::Compiler::Component::Logical.new
|
17
|
+
compiler.register_unit Haxor::Compiler::Component::Other.new
|
18
|
+
compiler.register_unit Haxor::Compiler::Component::Transfer.new
|
19
|
+
compiler.register_unit Haxor::Compiler::Component::Various.new
|
20
|
+
|
21
|
+
compiler.compile source
|
data/bin/hld
ADDED
@@ -0,0 +1,38 @@
|
|
1
|
+
#! /usr/bin/env ruby
|
2
|
+
|
3
|
+
require_relative '../lib/haxor'
|
4
|
+
require 'optparse'
|
5
|
+
|
6
|
+
options = {}
|
7
|
+
parser = OptionParser.new do |opts|
|
8
|
+
opts.banner = 'Usage: hld [options] [file.hax.u] [...]'
|
9
|
+
|
10
|
+
opts.on('-o', '--output FILENAME', 'Write output to FILENAME') do |v|
|
11
|
+
options[:output] = v
|
12
|
+
end
|
13
|
+
|
14
|
+
opts.on('-s', '--stack SIZE', OptionParser::DecimalInteger, 'Stack size in bytes') do |v|
|
15
|
+
options[:stack] = v
|
16
|
+
end
|
17
|
+
|
18
|
+
opts.on_tail('-h', '--help', 'Show this message') do
|
19
|
+
puts opts
|
20
|
+
exit
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
parser.parse!
|
25
|
+
|
26
|
+
unless options.key?(:output) && !ARGV.empty?
|
27
|
+
puts 'You must specify output filename and at least one .hax.u file to be linked.'
|
28
|
+
puts parser
|
29
|
+
exit
|
30
|
+
end
|
31
|
+
|
32
|
+
linker = Haxor::Linker.new
|
33
|
+
ARGV.map do |x|
|
34
|
+
linker.load_unit File.absolute_path(x)
|
35
|
+
end
|
36
|
+
|
37
|
+
linker.stack = options[:stack] if options.key? :stack
|
38
|
+
linker.link options[:output]
|
data/bin/hvm
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
#! /usr/bin/env ruby
|
2
|
+
|
3
|
+
require_relative '../lib/haxor'
|
4
|
+
|
5
|
+
if ARGV[0].nil?
|
6
|
+
puts "You must specify .hax.e file to be run."
|
7
|
+
exit 1
|
8
|
+
end
|
9
|
+
|
10
|
+
vm = Haxor::Vm::Core.new
|
11
|
+
|
12
|
+
filename = ARGV[0]
|
13
|
+
# make life easier ;)
|
14
|
+
filename += '.e' if filename.end_with? '.hax'
|
15
|
+
|
16
|
+
vm.load_program filename
|
17
|
+
vm.execute
|
data/examples/build.sh
ADDED
@@ -0,0 +1,100 @@
|
|
1
|
+
section .data
|
2
|
+
dw welcome_msg, "Simple 'Guess the number' game. Powered by Haxor VM.", 10, 0
|
3
|
+
dw generate_msg, "I will pick a number between %d and %d, your job is to guess it in smallest number of tries.", 10, 0
|
4
|
+
dw question_msg, 10, "What is the number? ", 0
|
5
|
+
dw bigger_msg, "Sorry, but my number is bigger.", 10, 0
|
6
|
+
dw smaller_msg, "Sorry, but my number is smaller.", 10, 0
|
7
|
+
dw win_msg, "Yeah! You guessed my number after %d tries!", 10, 0
|
8
|
+
dw invalid_msg, "Man, do you need definition of a number?! Try wikipedia then ;)", 10, 0
|
9
|
+
dw answer_fmt, "%d", 0
|
10
|
+
dw min, 1
|
11
|
+
dw max, 1000
|
12
|
+
|
13
|
+
section .bss
|
14
|
+
dw number, 0
|
15
|
+
dw answer, 0
|
16
|
+
dw tries, 0
|
17
|
+
|
18
|
+
section .text
|
19
|
+
label bigger
|
20
|
+
mov sc, 02h
|
21
|
+
lea r01, bigger_msg
|
22
|
+
push r01
|
23
|
+
push 1
|
24
|
+
syscall
|
25
|
+
jmp question
|
26
|
+
|
27
|
+
label smaller
|
28
|
+
mov sc, 02h
|
29
|
+
lea r01, smaller_msg
|
30
|
+
push r01
|
31
|
+
push 1
|
32
|
+
syscall
|
33
|
+
jmp question
|
34
|
+
|
35
|
+
label win
|
36
|
+
mov sc, 02h
|
37
|
+
push tries
|
38
|
+
lea r01, win_msg
|
39
|
+
push r01
|
40
|
+
push 1
|
41
|
+
syscall
|
42
|
+
jmp exit
|
43
|
+
|
44
|
+
label invalid_number
|
45
|
+
mov sc, 02h
|
46
|
+
lea r01, invalid_msg
|
47
|
+
push r01
|
48
|
+
push 1
|
49
|
+
syscall
|
50
|
+
jmp question
|
51
|
+
|
52
|
+
label main
|
53
|
+
|
54
|
+
label welcome
|
55
|
+
mov sc, 02h
|
56
|
+
lea r01, welcome_msg
|
57
|
+
push r01
|
58
|
+
push 1
|
59
|
+
syscall
|
60
|
+
|
61
|
+
label generate
|
62
|
+
mov sc, 02h
|
63
|
+
push max
|
64
|
+
push min
|
65
|
+
lea r01, generate_msg
|
66
|
+
push r01
|
67
|
+
push 1
|
68
|
+
syscall
|
69
|
+
mov sc, 04h
|
70
|
+
push max
|
71
|
+
push min
|
72
|
+
syscall
|
73
|
+
pop number
|
74
|
+
|
75
|
+
label question
|
76
|
+
mov sc, 02h
|
77
|
+
lea r01, question_msg
|
78
|
+
push r01
|
79
|
+
push 1
|
80
|
+
syscall
|
81
|
+
mov sc, 03h
|
82
|
+
lea r01, answer
|
83
|
+
push r01
|
84
|
+
lea r01, answer_fmt
|
85
|
+
push r01
|
86
|
+
push 0
|
87
|
+
syscall
|
88
|
+
cmp sc, -1
|
89
|
+
je invalid_number
|
90
|
+
inc tries
|
91
|
+
|
92
|
+
cmp number, answer
|
93
|
+
je win
|
94
|
+
jg bigger
|
95
|
+
jl smaller
|
96
|
+
|
97
|
+
label exit
|
98
|
+
mov sc, 01h
|
99
|
+
push 0
|
100
|
+
syscall
|
data/haxor.gemspec
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'haxor/consts'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "haxor"
|
8
|
+
spec.version = Haxor::Consts::GEM_VERSION
|
9
|
+
spec.authors = ["Krzysztof Magosa"]
|
10
|
+
spec.email = ["krzysztof@magosa.pl"]
|
11
|
+
|
12
|
+
spec.summary = "Educational Assembly Language running on custom VM"
|
13
|
+
spec.description = "Please follow to GitHub repository for more information."
|
14
|
+
spec.homepage = "https://github.com/krzysztof-magosa/haxor"
|
15
|
+
spec.license = "BSD-3"
|
16
|
+
|
17
|
+
spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
18
|
+
spec.bindir = "bin"
|
19
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
20
|
+
spec.require_paths = ["lib"]
|
21
|
+
|
22
|
+
spec.add_development_dependency "bundler", "~> 1.10"
|
23
|
+
spec.add_development_dependency "rake", "~> 10.0"
|
24
|
+
end
|
data/lib/haxor.rb
ADDED
@@ -0,0 +1,44 @@
|
|
1
|
+
# 3rd party
|
2
|
+
require 'json'
|
3
|
+
require 'io/console'
|
4
|
+
require 'scanf'
|
5
|
+
|
6
|
+
require_relative 'haxor/consts'
|
7
|
+
require_relative 'haxor/header'
|
8
|
+
|
9
|
+
# vm
|
10
|
+
require_relative 'haxor/vm/core'
|
11
|
+
require_relative 'haxor/vm/subsystem'
|
12
|
+
require_relative 'haxor/vm/mem'
|
13
|
+
require_relative 'haxor/vm/stack'
|
14
|
+
require_relative 'haxor/vm/os'
|
15
|
+
require_relative 'haxor/vm/cpu/core'
|
16
|
+
require_relative 'haxor/vm/cpu/unit/base'
|
17
|
+
require_relative 'haxor/vm/cpu/unit/logical'
|
18
|
+
require_relative 'haxor/vm/cpu/unit/arithmetic'
|
19
|
+
require_relative 'haxor/vm/cpu/unit/jumps'
|
20
|
+
require_relative 'haxor/vm/cpu/unit/various'
|
21
|
+
require_relative 'haxor/vm/cpu/unit/transfer'
|
22
|
+
|
23
|
+
# compiler
|
24
|
+
require_relative 'haxor/compiler/unit'
|
25
|
+
require_relative 'haxor/compiler/core'
|
26
|
+
require_relative 'haxor/compiler/component/base'
|
27
|
+
require_relative 'haxor/compiler/component/logical'
|
28
|
+
require_relative 'haxor/compiler/component/arithmetic'
|
29
|
+
require_relative 'haxor/compiler/component/jumps'
|
30
|
+
require_relative 'haxor/compiler/component/various'
|
31
|
+
require_relative 'haxor/compiler/component/transfer'
|
32
|
+
require_relative 'haxor/compiler/component/data'
|
33
|
+
require_relative 'haxor/compiler/component/other'
|
34
|
+
|
35
|
+
# linker
|
36
|
+
require_relative 'haxor/linker'
|
37
|
+
|
38
|
+
# tokens
|
39
|
+
require_relative 'haxor/token/base'
|
40
|
+
require_relative 'haxor/token/data'
|
41
|
+
require_relative 'haxor/token/int64'
|
42
|
+
require_relative 'haxor/token/label'
|
43
|
+
require_relative 'haxor/token/pointer'
|
44
|
+
require_relative 'haxor/token/cmd'
|
@@ -0,0 +1,55 @@
|
|
1
|
+
module Haxor
|
2
|
+
module Compiler
|
3
|
+
module Component
|
4
|
+
class Arithmetic < Base
|
5
|
+
def register
|
6
|
+
bind_cmd 'inc', :cmd_inc
|
7
|
+
bind_cmd 'dec', :cmd_dec
|
8
|
+
bind_cmd 'add', :cmd_add
|
9
|
+
bind_cmd 'sub', :cmd_sub
|
10
|
+
bind_cmd 'div', :cmd_div
|
11
|
+
bind_cmd 'mul', :cmd_mul
|
12
|
+
bind_cmd 'cmp', :cmd_cmp
|
13
|
+
end
|
14
|
+
|
15
|
+
def cmd_add(a, b)
|
16
|
+
add Token::Cmd.new(Vm::Cpu::Unit::Arithmetic::OP_ADD | offset_flags(a, b))
|
17
|
+
parse_value a
|
18
|
+
parse_value b
|
19
|
+
end
|
20
|
+
|
21
|
+
def cmd_sub(a, b)
|
22
|
+
add Token::Cmd.new(Vm::Cpu::Unit::Arithmetic::OP_SUB | offset_flags(a, b))
|
23
|
+
parse_value a
|
24
|
+
parse_value b
|
25
|
+
end
|
26
|
+
|
27
|
+
def cmd_div(a)
|
28
|
+
add Token::Cmd.new(Vm::Cpu::Unit::Arithmetic::OP_DIV | offset_flags(a))
|
29
|
+
parse_value a
|
30
|
+
end
|
31
|
+
|
32
|
+
def cmd_mul(a)
|
33
|
+
add Token::Cmd.new(Vm::Cpu::Unit::Arithmetic::OP_MUL | offset_flags(a))
|
34
|
+
parse_value a
|
35
|
+
end
|
36
|
+
|
37
|
+
def cmd_cmp(a, b)
|
38
|
+
add Token::Cmd.new(Vm::Cpu::Unit::Arithmetic::OP_CMP | offset_flags(a, b))
|
39
|
+
parse_value a
|
40
|
+
parse_value b
|
41
|
+
end
|
42
|
+
|
43
|
+
def cmd_inc(a)
|
44
|
+
add Token::Cmd.new(Vm::Cpu::Unit::Arithmetic::OP_INC | offset_flags(a))
|
45
|
+
parse_value a
|
46
|
+
end
|
47
|
+
|
48
|
+
def cmd_dec(a)
|
49
|
+
add Token::Cmd.new(Vm::Cpu::Unit::Arithmetic::OP_DEC | offset_flags(a))
|
50
|
+
parse_value a
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
module Haxor
|
2
|
+
module Compiler
|
3
|
+
module Component
|
4
|
+
class Base
|
5
|
+
attr_accessor :compiler
|
6
|
+
|
7
|
+
def register
|
8
|
+
fail 'this method must be implemented.'
|
9
|
+
end
|
10
|
+
|
11
|
+
def bind_cmd(cmd, method)
|
12
|
+
compiler.bind_cmd cmd, self, method
|
13
|
+
end
|
14
|
+
|
15
|
+
def add(token)
|
16
|
+
compiler.add token
|
17
|
+
end
|
18
|
+
|
19
|
+
def parse_value(value)
|
20
|
+
compiler.parse_value value
|
21
|
+
end
|
22
|
+
|
23
|
+
def offset_flags(a, b = nil)
|
24
|
+
compiler.offset_flags(a, b)
|
25
|
+
end
|
26
|
+
|
27
|
+
def offset?(value)
|
28
|
+
compiler.offset? value
|
29
|
+
end
|
30
|
+
|
31
|
+
def strip_offset(value)
|
32
|
+
compiler.strip_offset value
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
module Haxor
|
2
|
+
module Compiler
|
3
|
+
module Component
|
4
|
+
class Data < Base
|
5
|
+
def register
|
6
|
+
bind_cmd 'dw', :cmd_dw
|
7
|
+
bind_cmd 'resw', :cmd_resw
|
8
|
+
end
|
9
|
+
|
10
|
+
def cmd_dw(*args)
|
11
|
+
add Token::Label.new(args[0])
|
12
|
+
|
13
|
+
(1...args.size).each do |i|
|
14
|
+
begin
|
15
|
+
add Token::Int64.new(Integer(args[i]))
|
16
|
+
rescue
|
17
|
+
args[i][1...-1].each_char do |c|
|
18
|
+
add Token::Int64.new(c.ord)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def cmd_resw(*args)
|
25
|
+
(1..args[0].to_i).each do
|
26
|
+
add Token::Int64.new(0)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,95 @@
|
|
1
|
+
module Haxor
|
2
|
+
module Compiler
|
3
|
+
module Component
|
4
|
+
class Jumps < Base
|
5
|
+
def register
|
6
|
+
bind_cmd 'call', :cmd_call
|
7
|
+
bind_cmd 'ret', :cmd_ret
|
8
|
+
bind_cmd 'iret', :cmd_iret
|
9
|
+
|
10
|
+
bind_cmd 'jmp', :cmd_jmp
|
11
|
+
|
12
|
+
bind_cmd 'je', :cmd_je
|
13
|
+
bind_cmd 'jg', :cmd_jg
|
14
|
+
bind_cmd 'jge', :cmd_jge
|
15
|
+
bind_cmd 'jl', :cmd_jl
|
16
|
+
bind_cmd 'jle', :cmd_jle
|
17
|
+
|
18
|
+
bind_cmd 'jne', :cmd_jne
|
19
|
+
bind_cmd 'jng', :cmd_jng
|
20
|
+
bind_cmd 'jnge', :cmd_jnge
|
21
|
+
bind_cmd 'jnl', :cmd_jnl
|
22
|
+
bind_cmd 'jnle', :cmd_jnle
|
23
|
+
end
|
24
|
+
|
25
|
+
def cmd_call(a)
|
26
|
+
add Token::Cmd.new(Vm::Cpu::Unit::Jumps::OP_CALL | offset_flags(a))
|
27
|
+
parse_value a
|
28
|
+
end
|
29
|
+
|
30
|
+
def cmd_ret(*_args)
|
31
|
+
add Token::Cmd.new(Vm::Cpu::Unit::Jumps::OP_RET)
|
32
|
+
end
|
33
|
+
|
34
|
+
def cmd_iret(*_args)
|
35
|
+
add Token::Cmd.new(Vm::Cpu::Unit::Jumps::OP_IRET)
|
36
|
+
end
|
37
|
+
|
38
|
+
def cmd_jmp(a)
|
39
|
+
add Token::Cmd.new(Vm::Cpu::Unit::Jumps::OP_JMP | offset_flags(a))
|
40
|
+
parse_value a
|
41
|
+
end
|
42
|
+
|
43
|
+
def cmd_je(a)
|
44
|
+
add Token::Cmd.new(Vm::Cpu::Unit::Jumps::OP_JE)
|
45
|
+
parse_value a
|
46
|
+
end
|
47
|
+
|
48
|
+
def cmd_jg(a)
|
49
|
+
add Token::Cmd.new(Vm::Cpu::Unit::Jumps::OP_JG)
|
50
|
+
parse_value a
|
51
|
+
end
|
52
|
+
|
53
|
+
def cmd_jge(a)
|
54
|
+
add Token::Cmd.new(Vm::Cpu::Unit::Jumps::OP_JGE)
|
55
|
+
parse_value a
|
56
|
+
end
|
57
|
+
|
58
|
+
def cmd_jl(a)
|
59
|
+
add Token::Cmd.new(Vm::Cpu::Unit::Jumps::OP_JL)
|
60
|
+
parse_value a
|
61
|
+
end
|
62
|
+
|
63
|
+
def cmd_jle(a)
|
64
|
+
add Token::Cmd.new(Vm::Cpu::Unit::Jumps::OP_JLE)
|
65
|
+
parse_value a
|
66
|
+
end
|
67
|
+
|
68
|
+
def cmd_jne(a)
|
69
|
+
add Token::Cmd.new(Vm::Cpu::Unit::Jumps::OP_JNE)
|
70
|
+
parse_value a
|
71
|
+
end
|
72
|
+
|
73
|
+
def cmd_jng(a)
|
74
|
+
add Token::Cmd.new(Vm::Cpu::Unit::Jumps::OP_JNG)
|
75
|
+
parse_value a
|
76
|
+
end
|
77
|
+
|
78
|
+
def cmd_jnge(a)
|
79
|
+
add Token::Cmd.new(Vm::Cpu::Unit::Jumps::OP_JNGE)
|
80
|
+
parse_value a
|
81
|
+
end
|
82
|
+
|
83
|
+
def cmd_jnl(a)
|
84
|
+
add Token::Cmd.new(Vm::Cpu::Unit::Jumps::OP_JNL)
|
85
|
+
parse_value a
|
86
|
+
end
|
87
|
+
|
88
|
+
def cmd_jnle(a)
|
89
|
+
add Token::Cmd.new(Vm::Cpu::Unit::Jumps::OP_JNLE)
|
90
|
+
parse_value a
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|