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