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
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
|