Skip to content

Commit

Permalink
Removed duplication thanks to caliper @ http://devver.net
Browse files Browse the repository at this point in the history
  • Loading branch information
samsonjs committed Oct 21, 2009
1 parent dd29747 commit de366ea
Show file tree
Hide file tree
Showing 6 changed files with 74 additions and 104 deletions.
5 changes: 4 additions & 1 deletion asm/binary.rb
Expand Up @@ -616,7 +616,7 @@ def inc(op)

def dec(op)
if register?(op)
# dec r16 / dec r32
# dec reg32
asm { emit_byte(0x48 + op.regnum) }
else
raise "unsupported DEC instruction, op=#{op.inspect}"
Expand Down Expand Up @@ -655,6 +655,7 @@ def and_(dest, src)
raise "unsupported AND instruction: dest=#{dest.inspect}, src=#{src.inspect}"
end
end
alias_method :and, :and_


def xor(dest, src)
Expand All @@ -674,6 +675,7 @@ def xor(dest, src)
def not_(op)
group3(op, 2, 'NOT')
end
alias_method :not, :not_


def neg(op)
Expand Down Expand Up @@ -816,6 +818,7 @@ def loop_(label)
emit_byte(delta)
end
end
alias_method :loop, :loop_


# Opcode group #3. 1-byte opcode, 1 operand (r/m8 or r/m32).
Expand Down
9 changes: 4 additions & 5 deletions asm/cstruct.rb
Expand Up @@ -304,10 +304,9 @@ class MachHeader < CStruct
puts MachHeader::MemberSizes.inspect
puts "# of MachHeader members: " + MachHeader.size.to_s + ", size in bytes: " + MachHeader.bytesize.to_s
mh = MachHeader.new(0xfeedface, 7, 3, "foobar")
puts "magic(#{MachHeader.sizeof(:magic)}): " + mh[:magic].inspect
puts "cputype(#{MachHeader.sizeof(:cputype)}): " + mh[:cputype].inspect
puts "cpusubtype(#{MachHeader.sizeof(:cpusubtype)}): " + mh[:cpusubtype].inspect
puts "segname(#{MachHeader.sizeof(:segname)}): " + mh[:segname].inspect
%w[magic, cputype, cpusubtype, segname].each do |field|
puts "#{field}(#{MachHeader.sizeof(field.to_sym)}): " + mh[field.to_sym].inspect
end
puts mh.pack_pattern.inspect
binstr = mh.serialize
puts "values: " + mh.values.inspect
Expand All @@ -317,4 +316,4 @@ class MachHeader < CStruct
puts "serialized: " + binstr.inspect
puts "unserialized: " + newbinstr.inspect
puts "new == old ? " + (newbinstr == binstr).to_s
end
end
46 changes: 18 additions & 28 deletions asm/machofile.rb
Expand Up @@ -131,56 +131,46 @@ def text(data, sectname='__text', segname='__TEXT')
end


# Define a standard data section under the current segment (if present).
# This behaves similarly to the text method.
#
def data(data, sectname='__data', segname='__DATA')
# Basis for #data, #const, and #bss methods.
def segment_based_on_filetype(segname, options={})
unless @current_segment
permissions = VM_PROT_READ
permisions |= VM_PROT_WRITE if options.delete(:writable)
segment(segname_based_on_filetype(segname)) do |seg|
seg[:maxprot] = VM_PROT_READ | VM_PROT_WRITE
seg[:initprot] = VM_PROT_READ | VM_PROT_WRITE
seg[:initprot] = seg[:maxprot] = permissions
end
end

section(sectname, segname, data)

yield if block_given?
return self
end

# Define a standard data section under the current segment (if present).
# This behaves similarly to the text method.
#
def data(data, sectname='__data', segname='__DATA')
segment_based_on_filetype(segname, :writable => true) do
section(sectname, segname, data)
end
end

# Define a standard const section under the current segment (if present).
# This behaves similarly to the data method.
#
def const(data, sectname='__const', segname='__DATA')
unless @current_segment
segment(segname_based_on_filetype(segname)) do |seg|
seg[:maxprot] = VM_PROT_READ
seg[:initprot] = VM_PROT_READ
end
segment_based_on_filetype(segname) do
section(sectname, segname, data)
end

section(sectname, segname, data)

return self
end


# Define a standard BSS section under the current segment (if present).
# This behaves similarly to the data method but accepts a VM size instead
# of a blob, and no data is written to file since this section is for
# uninitialized data.
#
def bss(vmsize, sectname='__bss', segname='__DATA')
unless @current_segment
segment(segname_based_on_filetype(segname)) do |seg|
seg[:maxprot] = VM_PROT_READ | VM_PROT_WRITE
seg[:initprot] = VM_PROT_READ | VM_PROT_WRITE
end
segment_based_on_filetype(segname, :writable => true) do
section(sectname, segname, '', vmsize)
end

section(sectname, segname, '', vmsize)

return self
end


Expand Down
43 changes: 14 additions & 29 deletions asm/machosymtab.rb
Expand Up @@ -18,37 +18,22 @@ def bss_offset
return 0x2800
end

def all_symbols
symbols = []

# Functions (section #1, __text)
#
# All labels are exported. This should be changed and only functions exported!
# TODO fixme ...
#
def make_symbols(vars, type, segnum)
# Note: Sorting a Ruby hash gives an alist, e.g. [[<key>, <value>], ...]
# We can use map on it as if it were a hash so it works nicely.
#
symbols +=
@labels.sort { |a,b| a[1] <=> b[1] }.
map do |name,addr|
MachOSym.new(name, N_SECT | N_EXT, 1, 0, addr)
end

# Constants (section #2, __const)
symbols += @consts.sort { |a,b| a[1] <=> b[1] }.
map do |name, addr|
MachOSym.new(name, N_SECT, 2, 0, addr)
end

# Variables (section #3, __bss)
#
# TODO FIXME the last var exported ends up after main somewhere... WTF?!
symbols += @vars.sort { |a,b| a[1] <=> b[1] }.
map do |name, addr|
MachOSym.new(name, N_SECT, 3, 0, addr)
end

vars.sort { |a,b| a[1] <=> b[1] }.
map do |name, addr|
MachOSym.new(name, type, segnum, 0, addr)
end
end

def all_symbols
# TODO FIXME:
# - the last var exported ends up after main somewhere... WTF?!
# - All labels are exported. This should be changed and only functions exported!
symbols = make_symbols(@labels, N_SECT | N_EXT, 1) + # Functions (section #1, __text)
make_symbols(@consts, N_SECT, 2) + # Constants (section #2, __const)
make_symbols(@vars, N_SECT, 3) # Variables (section #3, __bss)
return symbols
end

Expand Down
24 changes: 12 additions & 12 deletions build.rb
Expand Up @@ -49,16 +49,21 @@ def compile(infile, outfile, asm)
exit(1)
end

# assemble using nasm, return resulting filename.
def assemble(filename, binformat='elf')
f = base(filename)
outfile = "#{f}.o"
output = `nasm -f #{binformat} -g -o #{outfile} #{filename} 2>&1`
def run_and_warn_on_failure(command, name)
output = `#{command}`
if $?.exitstatus != 0
puts
print output
raise "nasm failed: #{$?.exitstatus}"
name = command.split.first
raise "#{name} failed: #{$?.exitstatus}"
end
end

# assemble using nasm, return resulting filename.
def assemble(filename, binformat='elf')
f = base(filename)
outfile = "#{f}.o"
run_and_warn_on_failure("nasm -f #{binformat} -g -o #{outfile} #{filename} 2>&1")
return outfile
end

Expand All @@ -71,12 +76,7 @@ def link(filename, platform='linux')
else
raise "unsupported platform: #{platform}"
end
output = `#{cmd} #{args} -o #{f} #{filename} 2>&1`
if $?.exitstatus != 0
puts
print output
raise "ld failed: #{$?.exitstatus}"
end
run_and_warn_on_failure("#{cmd} #{args} -o #{f} #{filename} 2>&1")
`chmod u+x #{f}`
return f
end
Expand Down
51 changes: 22 additions & 29 deletions compiler.rb
Expand Up @@ -190,25 +190,23 @@ def divide
# bit expressions #
###################

def bitor_expr
match('|')
term
def bit_expr(op, token)
match(token)
if block_given? yield else term end
asm.pop(EBX)
asm.or_(EAX, EBX)
asm.send(op, EAX, EBX)
end

def bitand_expr
match('&')
signed_factor
asm.pop(EBX)
asm.and_(EAX, EBX)
def bitor_expr
bit_expr(:or, '|')
end

def xor_expr
match('^')
term
asm.pop(EBX)
asm.xor(EAX, EBX)
bit_expr(:xor, '^')
end

def bitand_expr
bit_expr(:and, '&') { signed_factor }
end


Expand Down Expand Up @@ -323,6 +321,9 @@ def eq_relation
# true (-1) if the difference was below zero and false (0)
# otherwise (using JL, jump if less than).
def cmp_relation(a, b, options={})
expression
asm.pop(EBX)

# Invert the sense of the test?
invert = options[:invert]

Expand All @@ -347,8 +348,6 @@ def cmp_relation(a, b, options={})
#
# if a > b then b - a < 0
def gt_relation
expression
asm.pop(EBX)
cmp_relation(EAX, EBX) # b - a
end

Expand All @@ -357,8 +356,6 @@ def gt_relation
#
# if a < b then a - b < 0
def lt_relation
expression
asm.pop(EBX)
cmp_relation(EBX, EAX) # a - b
end

Expand All @@ -367,8 +364,6 @@ def lt_relation
#
# if a >= b then !(a < b)
def ge_relation
expression
asm.pop(EBX)
# Compare them as in less than but invert the result.
cmp_relation(EBX, EAX, :invert => true)
end
Expand All @@ -378,8 +373,6 @@ def ge_relation
#
# if a <= b then !(a > b)
def le_relation
expression
asm.pop(EBX)
# Compare them as in greater than but invert the result.
cmp_relation(EAX, EBX, :invert => true)
end
Expand Down Expand Up @@ -474,20 +467,20 @@ def simple_loop(name)
asm.emit_label(end_label)
end

def while_stmt
simple_loop('while') do |end_label|
def condition_loop(name, jump_instruction)
simple_loop(name) do |end_label|
condition
skip_any_whitespace
asm.jz(end_label)
asm.send(jump_instruction, end_label)
end
end

def while_stmt
condition_loop('while', :jz) # done when == 0 (falsish)
end

def until_stmt
simple_loop('until') do |end_label|
condition
skip_any_whitespace
asm.jnz(end_label)
end
condition_loop('until', :jnz) # done when != 0 (truthy)
end

def repeat_stmt
Expand Down

0 comments on commit de366ea

Please sign in to comment.