Rubyでアセンブラ
id:metanest:20070124#p4 id:metanest:20070125#p1 のリファクタリング
instance_evalによるselfのすりかえを使ってみた
#!/usr/local/bin/ruby19 # coding:utf-8 # vi:set ts=3 sw=3: # vim:set sts=0 noet: require 'dl/import' module RASM class CodeGen def initialize @buf = '' end def push_code s @buf << s end def emit_code result = @buf @buf = '' result end end class AsmHelper < BasicObject EAX = :EAX EBX = :EBX ECX = :ECX EDX = :EDX def initialize codeGen @buf = codeGen end def add op0, op1 @buf.push_code "add #{op0.to_s}, #{op1.to_s}\n" end def mov op0, op1 @buf.push_code "mov #{op0.to_s}, #{op1.to_s}\n" end def mul op @buf.push_code "mul #{op.to_s}\n" end def ret @buf.push_code "ret\n" end end def self.asm &blk codegen = CodeGen.new helper = AsmHelper.new codegen helper.instance_eval &blk funcname = '_' + rand.to_s[2..-1] code = '' code << "bits 64\n" code << "section .text\n" code << "global #{funcname}\n#{funcname}:\n" code << codegen.emit_code basename = "/tmp/#{funcname}" tempfile = open "#{basename}.asm", 'w' tempfile.write code tempfile.close system "nasm -f elf64 #{basename}.asm" system "rm #{basename}.asm" system "gcc -shared -fPIC -o #{basename}.so #{basename}.o" system "rm #{basename}.o" handler = Module.new do extend DL::Importer dlload "#{basename}.so" extern "int #{funcname}()" end system "rm #{basename}.so" [handler, funcname] end end def bar a, b, c RASM.asm { mov EAX, a add EAX, b mov EBX, c mul EBX ret } end handler, funcname = bar 3, 4, 5 result = handler.__send__ funcname p result