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.
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 @@
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
@@ -0,0 +1,10 @@
1
+ #! /bin/sh
2
+
3
+ # Fail on first error
4
+ set -e
5
+
6
+ for program in *.hax ; do
7
+ echo "Compiling example $program ..."
8
+ ../bin/hcc $program
9
+ ../bin/hld -o $program.e $program.u
10
+ done
@@ -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
@@ -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
@@ -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