gasm 0.1.0 → 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: bd06be7e5047c313deeb459a869c00cbf56ff8efd4d3d4190cd825ba09353eb3
4
- data.tar.gz: da6ddd558a76a47819abe388c3cd57564c89530ec762f6493c793d6a81225a2b
3
+ metadata.gz: ccae527d5bcdb0a59180066a9afc933419b48651c30db1d91f7e76f0ba94a2c0
4
+ data.tar.gz: 19b1662105f3125c1d53f98039191eb68664ad035033c354659c8283d5e5f8eb
5
5
  SHA512:
6
- metadata.gz: 68e594afb0d28eb6b22bf9e8fb126881157f2e447edbeac877cf86e0320665534b451ce96bb239cfa976389acebe669d0d05b1c3c440cb3c348e246749e9b26d
7
- data.tar.gz: 57f58715abe134ed443389ab2d432b454f4239b6dcf6ebd3703f80fed67da13533d9ad2fcad05930d8055a11be814b1d241c6ffa0e6659eb3b1f129954f44dd3
6
+ metadata.gz: c58736d7157d72eef6ae7566d41cc001f0be3bf177063647119f17c98133ef839ef3720ae38143d9629bf08e4bb1a724593958d3da22253cf6af390361c3665a
7
+ data.tar.gz: a649646e47bd77f3dce4ceafc0659825055ca0911ae4eca5bfacb658bdf2057a170615fb736f4b61709999933b0eac25ac07054c8eaf28c40f26bc3ed896adbf
@@ -10,7 +10,7 @@ asm do
10
10
  opcodes.each_with_index do |opcode, oi|
11
11
  addrmodes.each_with_index do |(pattern, zeropage, operands), ai|
12
12
  next if pattern.nil?
13
- next if pattern == '___'
13
+ next if opcode.start_with? '__'
14
14
 
15
15
  a = oi.to_s(2).rjust(3, '0')
16
16
  b = ai.to_s(2).rjust(3, '0')
@@ -3,7 +3,7 @@ asm do
3
3
  # Generate matchers for hex values for register
4
4
  def vp(pattern, bits)
5
5
  if pattern.include?('V<x>')
6
- hex_letters = %w[a b c d e f A B C D E F]
6
+ hex_letters = %w[0 1 2 3 4 5 6 7 8 9 a b c d e f A B C D E F]
7
7
  hex_letters.each do |register_x|
8
8
  pattern_a = pattern.gsub('V<x>', "V#{register_x}")
9
9
  bits_a = bits.gsub('xxxx', "#{register_x.to_i(16).to_s(2)}")
data/exe/gasm CHANGED
@@ -4,6 +4,13 @@ require 'gasm'
4
4
 
5
5
  include Gasm
6
6
 
7
+ disasm = false
8
+
9
+ if ARGV[0] == '-d'
10
+ disasm = true
11
+ ARGV.shift
12
+ end
13
+
7
14
  asm_desc = ARGV[0]
8
15
  asm_file = ARGV[1]
9
16
 
@@ -61,17 +68,28 @@ rescue => e
61
68
  exit(1)
62
69
  end
63
70
 
71
+ reader = Asm
72
+
73
+ # disassembly mode
74
+ if disasm
75
+ STDERR.puts 'Disassembling...'
76
+ reader = Disasm
77
+ else
78
+ STDERR.puts 'Assembling...'
79
+ end
64
80
 
65
81
  asm = if asm_file == '-'
66
- Asm.new(STDIN.read, matcher)
82
+ reader.new(STDIN.read, matcher)
67
83
 
68
84
  else
69
85
  if !File.exist?(asm_file)
70
- STDERR.puts "'#{asm_file}' asm does not exist"
86
+ STDERR.puts "File '#{asm_file}' does not exist"
71
87
  exit(1)
72
88
  end
73
-
74
- Asm.new(File.read(asm_file), matcher)
89
+
90
+ file = File.open(asm_file, "rb")
91
+ contents = file.read
92
+ reader.new(contents, matcher)
75
93
  end
76
94
 
77
- puts asm.compiled
95
+ puts asm.output
data/lib/gasm/asm.rb CHANGED
@@ -5,7 +5,7 @@ module Gasm
5
5
  @contents = contents
6
6
  end
7
7
 
8
- def compiled
8
+ def output
9
9
  lines = @contents.split("\n")
10
10
  offset = 0
11
11
 
@@ -0,0 +1,24 @@
1
+ module Gasm
2
+ class Disasm
3
+ def initialize(contents, gasm)
4
+ @gasm = gasm
5
+ @contents = contents
6
+ end
7
+
8
+ def output
9
+ result = []
10
+
11
+ index = 0
12
+ loop do
13
+ res = @gasm.disparse(@contents, index)
14
+ index += res[:amountread]
15
+ result << res[:instruction]
16
+ break if index >= @contents.length
17
+ rescue => e
18
+ result << "// -incomplete- disassembling stopped: #{e.message} at index 0x#{index.to_s(16)} '0x#{@contents[index].unpack('C')[0].to_s(16)}'"
19
+ break
20
+ end
21
+ result.join("\n")
22
+ end
23
+ end
24
+ end
@@ -11,8 +11,55 @@ module Gasm
11
11
  def strip_comment(line)
12
12
  line.split('//')[0]
13
13
  end
14
+
15
+ def disparse(contents, index)
16
+ match = nil
17
+
18
+ @desc['asm']['instructions'].each do |k, info|
19
+ bitpattern = info[:bits].tr(' ', '')
20
+
21
+ vars = {}
22
+ match = [k, info, vars, bitpattern.length >> 3]
23
+ bitpattern.split('').each_with_index do |chr, i|
24
+ byte_index = (i >> 3) + index
25
+ bit_index = i % 8
26
+
27
+ if byte_index >= contents.length
28
+ match = nil
29
+ next
30
+ end
31
+
32
+ contentbits = contents[byte_index].unpack("C")[0].to_s(2).rjust(8, '0')
33
+
34
+ c = contentbits[bit_index]
35
+ if chr == '0' || chr == '1'
36
+ if c != chr
37
+ match = nil
38
+ break
39
+ end
40
+ else
41
+ vars[chr] ||= ''
42
+ vars[chr] += c
43
+ end
44
+ end
45
+
46
+ break if match
47
+ end
48
+
49
+ raise 'unknown pattern' if match.nil?
50
+
51
+ result = match[0]
52
+ match[2].each do |var, val|
53
+ result.gsub!("<#{var}>", "$#{val.to_i(2).to_s(16)}")
54
+ end
55
+
56
+ {
57
+ amountread: match[3],
58
+ instruction: result
59
+ }
60
+ end
14
61
 
15
- NUMCHARS = %[0 1 2 3 4 5 6 7 8 9 a b c d e f o x b $ %]
62
+ NUMCHARS = %[0 1 2 3 4 5 6 7 8 9 a b c d e f o x $ %]
16
63
  def parse(line)
17
64
  line = strip_comment(line)
18
65
  line = strip_spaces(line)
@@ -21,6 +68,7 @@ module Gasm
21
68
  result = ''
22
69
  values = {}
23
70
  idx = 0
71
+ pattern = ''
24
72
 
25
73
  @desc['asm']['instructions'].each do |k, info|
26
74
  result = info[:bits]
@@ -105,6 +153,8 @@ module Gasm
105
153
  unless info[:condition].call(values.map{|k,v| [k.to_sym, v.to_i(2)]}.to_h)
106
154
  result = nil
107
155
  end
156
+
157
+ pattern = info[:bits]
108
158
 
109
159
  break unless result.nil?
110
160
  end
@@ -121,7 +171,7 @@ module Gasm
121
171
  lastvar = ' '
122
172
  output = ''
123
173
 
124
- evalues = endiannize(values)
174
+ evalues = endiannize(values, pattern)
125
175
  loop do
126
176
 
127
177
  if result[idx] == lastvar
@@ -170,20 +220,20 @@ module Gasm
170
220
  ].join("\n")
171
221
  end
172
222
 
173
- def littleendian(bitstr)
223
+ def littleendian(bitstr, len)
174
224
  # flips a bit string around to blocks of 8 little endian bytes
175
225
  # 1. reverse the string
176
226
  # 2. cut it into blocks of 8
177
227
  # 3. reverse each block of 8
178
228
  # 4. et voila
179
- bitstr.split('').reverse.each_slice(8).map{|x| x.reverse}.flatten.join('')
229
+ bitstr.rjust(len, '0').split('').reverse.each_slice(8).map{|x| x.reverse}.flatten.join('')
180
230
  end
181
231
 
182
- def endiannize(values)
232
+ def endiannize(values, pattern)
183
233
  # transforms the values array into big and small endian versions
184
234
  result = {}
185
235
  values.each do |k,v|
186
- result[k] = littleendian(v)
236
+ result[k] = littleendian(v, pattern.count(k))
187
237
  result[k.upcase] = v
188
238
  end
189
239
  result
data/lib/gasm/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Gasm
4
- VERSION = '0.1.0'
4
+ VERSION = '0.1.1'
5
5
  end
data/lib/gasm.rb CHANGED
@@ -1,4 +1,5 @@
1
1
  require 'gasm/gasm_loader'
2
2
  require 'gasm/ruby_desc'
3
+ require 'gasm/disasm'
3
4
  require 'gasm/asm'
4
5
  require 'gasm/gasm_matcher'
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: gasm
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.1.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - David Siaw
@@ -41,6 +41,7 @@ files:
41
41
  - gasm.gemspec
42
42
  - lib/gasm.rb
43
43
  - lib/gasm/asm.rb
44
+ - lib/gasm/disasm.rb
44
45
  - lib/gasm/gasm_loader.rb
45
46
  - lib/gasm/gasm_matcher.rb
46
47
  - lib/gasm/instruction_section.rb