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