gasm 0.1.0 → 0.1.1
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 +4 -4
- data/data/gasm/cpus/6502.gasm.rb +1 -1
- data/data/gasm/cpus/chip8.gasm.rb +1 -1
- data/exe/gasm +23 -5
- data/lib/gasm/asm.rb +1 -1
- data/lib/gasm/disasm.rb +24 -0
- data/lib/gasm/gasm_matcher.rb +56 -6
- data/lib/gasm/version.rb +1 -1
- data/lib/gasm.rb +1 -0
- metadata +2 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ccae527d5bcdb0a59180066a9afc933419b48651c30db1d91f7e76f0ba94a2c0
|
4
|
+
data.tar.gz: 19b1662105f3125c1d53f98039191eb68664ad035033c354659c8283d5e5f8eb
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c58736d7157d72eef6ae7566d41cc001f0be3bf177063647119f17c98133ef839ef3720ae38143d9629bf08e4bb1a724593958d3da22253cf6af390361c3665a
|
7
|
+
data.tar.gz: a649646e47bd77f3dce4ceafc0659825055ca0911ae4eca5bfacb658bdf2057a170615fb736f4b61709999933b0eac25ac07054c8eaf28c40f26bc3ed896adbf
|
data/data/gasm/cpus/6502.gasm.rb
CHANGED
@@ -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
|
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
|
-
|
82
|
+
reader.new(STDIN.read, matcher)
|
67
83
|
|
68
84
|
else
|
69
85
|
if !File.exist?(asm_file)
|
70
|
-
STDERR.puts "'#{asm_file}'
|
86
|
+
STDERR.puts "File '#{asm_file}' does not exist"
|
71
87
|
exit(1)
|
72
88
|
end
|
73
|
-
|
74
|
-
|
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.
|
95
|
+
puts asm.output
|
data/lib/gasm/asm.rb
CHANGED
data/lib/gasm/disasm.rb
ADDED
@@ -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
|
data/lib/gasm/gasm_matcher.rb
CHANGED
@@ -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
|
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
data/lib/gasm.rb
CHANGED
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.
|
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
|