$words[name] = Word.new(name, 0, code)
end
-$input = $stdin
-$stack = []
-$state = 0
-$curr = nil
+#------------------------------------------
+# Interpreter/Compiler State
+#------------------------------------------
+$base = 10
+$input = $stdin
+$stack = []
+$state = 0
+$curr = nil
$buffer = ""
-$words = {
-# 'load-imm' => lambda {
-# puts "load-imm"
-# PROG.push(0x48)
-# PROG.push(0xc7)
-# PROG.push(0xC0 + $stack.pop)
-# imm = $stack.pop
-# PROG.push((imm >> 0) & 0xff)
-# PROG.push((imm >> 8) & 0xff)
-# PROG.push((imm >> 16) & 0xff)
-# PROG.push((imm >> 24) & 0xff)
-# },
-}
-
+$words = {}
#------------------------------------------
# Stack Manipulation
#------------------------------------------
-builtin('drop') { }
-builtin('swap') { }
-builtin('dup') { }
-builtin('over') { }
-builtin('rot') { }
-builtin('-rot') { }
-
-builtin('2drop') { }
-builtin('2swap') { }
-builtin('2dup') { }
-builtin('?dup') { }
+builtin('drop') {
+ pop()
+}
+
+builtin('swap') {
+ a = pop()
+ b = pop()
+ push a
+ push b
+}
+
+builtin('dup') {
+ push $stack.last
+}
+
+builtin('over') {
+ push $stack[-2]
+}
+
+builtin('rot') {
+
+}
+
+builtin('-rot') {
+
+}
+
+builtin('2drop') {
+
+}
+
+builtin('2swap') {
+
+}
+
+builtin('2dup') {
+
+}
+
+builtin('?dup') {
+
+}
builtin('1+') { }
builtin('1-') { }
# Aritmetic
#------------------------------------------
builtin('+') { push(pop() + pop()) }
-builtin('-') { push(pop() - pop()) }
+builtin('-') { a = pop(); push(pop() - a) }
builtin('*') { push(pop() * pop()) }
-builtin('/') { push(pop() / pop()) }
-builtin('%') { push(pop() % pop()) }
+builtin('/') { a = pop(); push(pop() / a) }
+builtin('%') { a = pop(); push(pop() % a) }
#------------------------------------------
# Comparison
builtin('0<=') { push(pop() <= 0) }
builtin('0>=') { push(pop() >= 0) }
-
#------------------------------------------
# Bitwise Operations
#------------------------------------------
#builtin('bcopy') { }
#builtin('bmove') { }
-
#------------------------------------------
# Variables
#------------------------------------------
#F_HIDDEN The HIDDEN flag's actual value.
#F_LENMASK The length mask in the flags/len byte.
-
#------------------------------------------
# Compiler
#------------------------------------------
+builtin('hex') {
+ $base = 16
+}
+
+builtin('dec') {
+ $base = 10
+}
+
+builtin('oct') {
+ $base = 8
+}
+
+builtin('bin') {
+ $base = 2
+}
+
builtin('#') {
$buffer = $input.gets
+# puts " #{$buffer.inspect}"
}
builtin('.') {
}
builtin('word') do
- if $buffer.length == 0 then
- $buffer = $input.gets
+# puts " word"
+ word = nil
+ while word.nil?
+ if $buffer.length == 0 then
+ $buffer = $input.gets
+# puts " #{$buffer.inspect}"
+ break if $buffer.nil?
+ end
+ $buffer.slice!(/^\s*/)
+ word = $buffer.slice!(/^[^\s]+/)
end
- $buffer.slice!(/^\s*/)
- push $buffer.slice!(/^[^\s]+/)
+# puts " word: #{word}"
+# puts " end word"
+ push word
end
builtin('create') do
# Assembler Words
#------------------------------------------
-def pack8(val)
- PROG.push(val & 0xff)
+def pack8(val, off = nil)
+ PROG[off || PROG.length] = (val & 0xff)
end
-def pack16(val)
- PROG.push((val >> 0) & 0xff)
- PROG.push((val >> 8) & 0xff)
+def pack16(val, off = nil)
+ off ||= PROG.length
+ PROG[off + 0] = ((val >> 0) & 0xff)
+ PROG[off + 1] = ((val >> 8) & 0xff)
end
-def pack32(val)
- PROG.push((val >> 0) & 0xff)
- PROG.push((val >> 8) & 0xff)
- PROG.push((val >> 16) & 0xff)
- PROG.push((val >> 24) & 0xff)
+def pack32(val, off = nil)
+ off ||= PROG.length
+ PROG[off + 0] = ((val >> 0) & 0xff)
+ PROG[off + 1] = ((val >> 8) & 0xff)
+ PROG[off + 2] = ((val >> 16) & 0xff)
+ PROG[off + 3] = ((val >> 24) & 0xff)
end
-def pack64(val)
- PROG.push((val >> 0) & 0xff)
- PROG.push((val >> 8) & 0xff)
- PROG.push((val >> 16) & 0xff)
- PROG.push((val >> 24) & 0xff)
- PROG.push((val >> 32) & 0xff)
- PROG.push((val >> 40) & 0xff)
- PROG.push((val >> 48) & 0xff)
- PROG.push((val >> 56) & 0xff)
+def pack64(val, off = nil)
+ off ||= PROG.length
+ PROG[off + 0] = ((val >> 0) & 0xff)
+ PROG[off + 1] = ((val >> 8) & 0xff)
+ PROG[off + 2] = ((val >> 16) & 0xff)
+ PROG[off + 3] = ((val >> 24) & 0xff)
+ PROG[off + 4] = ((val >> 32) & 0xff)
+ PROG[off + 5] = ((val >> 40) & 0xff)
+ PROG[off + 6] = ((val >> 48) & 0xff)
+ PROG[off + 7] = ((val >> 56) & 0xff)
end
def packBytes(bytes)
PROG.append(*bytes)
end
-#builtin("virt-address") {
-#
-#}
-#
-#builtin("entry-offset") {
-#
-#}
-#
-#builtin("segment-size") {
-#
-#}
-#
-#builtin("segment-size") {
+def unpack8(off)
+ PROG[off]
+end
+
+def unpack16(off)
+ return (
+ PROG[off] |
+ (PROG[off] << 8)
+ )
+end
+
+def unpack32(off)
+ (
+ (PROG[off]) |
+ (PROG[off] << 8) |
+ (PROG[off] << 16) |
+ (PROG[off] << 24)
+ )
+end
+
+def unpack64(off)
+ (
+ (PROG[off + 0]) |
+ (PROG[off + 1] << 8) |
+ (PROG[off + 2] << 16) |
+ (PROG[off + 3] << 24) |
+ (PROG[off + 4] << 32) |
+ (PROG[off + 5] << 40) |
+ (PROG[off + 6] << 48) |
+ (PROG[off + 7] << 56)
+ )
+end
+
+
+builtin("here") {
+ push PROG.length
+}
+
+builtin("@") {
+ push unpack64(pop())
+}
+
+builtin("!") {
+ off = pop()
+ val = pop()
+ pack64(val, off)
+}
+
+builtin("+!") {
+ off = pop()
+ val = pop()
+ pack64(unpack64(off) + val, off)
+}
+
+builtin("-!") {
+ off = pop()
+ val = pop()
+ pack64(unpack64(off) - val, off)
+}
+
+
+
#
-#}
+# 0x7F, 0x45, 0x4C, 0x46, 0x02, 0x01, 0x01, 0x00, # 00
+# 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, # 08
+# 0x02, 0x00, 0x3E, 0x00, 0x01, 0x00, 0x00, 0x00, # 16
+# 0x78, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, # 24 e_entry: 0x0x00400078, (virtual memory address of entry point)
+# 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, # 32
+# 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, # 40
+# 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x38, 0x00, # 48
+# 0x01, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, # 56
+# 0x01, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, # 64
+# 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, # 72
+# 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, # 78 p_vaddr: 0x00400000, (virtual address of segment in memory)
+# 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, # 86
+# 0x84, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, # 94 p_filesz: 0x00011E02, (size in bytes of the segment in the file)
+# 0x00, 0x00, 0xC0, 0x7F, 0x00, 0x00, 0x00, 0x00, # 102 p_memsz: 0x7FC00000, (siz
+
+builtin("entry-address") { push 24 }
+builtin("virt-address") { push 78 }
+builtin("segment-size") { push 102 }
builtin('pack8') { pack8(pop()) }
builtin('pack16') { pack16(pop()) }
# Input Interpreter
#------------------------------------------
def interp()
- while (not $input.eof?) || ($buffer.length > 0) do
+# puts " interp"
+ while (not $input.eof?) || ($buffer && $buffer.length > 0) do
$words['word'].code.call()
w = $stack.pop
- next if w.nil? or w.length == 0
+ break if w.nil?
if $words[w] then
if $state == 0 || (($words[w].flags & IMM) == IMM)
$words[w].code.call
else
$curr.code << $words[w].code
end
- elsif w =~ /^[0-9]+$/
+ elsif w =~ /^[0-9A-Fa-f]+$/
if $state == 0
- push w.to_i
+ push w.to_i($base)
else
$curr.code << lambda{ push w.to_i }
end
else
pp $stack
- puts "?"
+ puts "#{w.inspect} ?"
$stack = []
end
end
+# puts " end interp"
end
def interp_file(file)
+# puts "interp file: #{file}"
prev = $input
$input = File.open(file, "rb")
interp()
$input = prev
+# puts "end interp file: #{file}"
end
-
-interp_file("asm.s")
-
-#$stdin.each_line do |line|
-# line.split.each do |w|
-# end
-#end
-#
-#File.read("asm.s").split.each do |w|
-# if $words[w]
-# $words[w].call()
-# else
-# $stack.push(w.to_i($base))
-# end
-#end
-#
-# Set program length and write to disk
-PROG[96] = ((PROG.length >> 0) & 0xFF)
-PROG[97] = ((PROG.length >> 8) & 0xFF)
-PROG[98] = ((PROG.length >> 16) & 0xFF)
-PROG[99] = ((PROG.length >> 24) & 0xFF)
-File.binwrite("a.out", PROG.map{|b| b.chr }.join)
-
-
+#------------------------------------------
+# Parse Input and Generate Output
+#------------------------------------------
+if ARGV.length > 0
+ ARGV.each {|f| interp_file(f) }
+
+ # Set program length and write to disk
+ PROG[96] = ((PROG.length >> 0) & 0xFF)
+ PROG[97] = ((PROG.length >> 8) & 0xFF)
+ PROG[98] = ((PROG.length >> 16) & 0xFF)
+ PROG[99] = ((PROG.length >> 24) & 0xFF)
+ File.binwrite("a.out", PROG.map{|b| b.chr }.join)
+else
+ interp()
+end