Rubyでインラインアセンブラできるようなクラスを作ってみた

界隈でRubyが遅いとか言われているので、「インラインアセンブリできれば超早くなるんじゃね?!」と思って、やってみた。ちなみに、Linux上じゃないと動かないよ!

クラスファイルasm.rbのダウンロードはこちらから


このファイルと同じフォルダに、以下のようなsample.rbを設置しまして・・・

require "asm"

str=<<-E
.section .data
  message:
    .ascii "hello,gas!\n"

.section .text
  .global start
  start:
    //システムコール4番(write)をコールしたい。
    movl  $4,%eax
    movl  $1,%ebx
    //引数2:出力先に対して書き込みたいバッファ
    movl  $message,%ecx   
    //NULL文字を入れて12文字
    movl  $12,%edx    
    int   $0x80
E
Asm.new(str).exe("start")

以下のコマンドを実行すると・・・

$ ruby sample.rb
hello,gas!

おお、ちゃんと動きました!!これでRubyが超早くなるね☆
実行時にちょっとファイルが吐き出されちゃうけど、そんなことは気にしないでね!

挙動

えらい書くのが遅くなっていましましたが、一応挙動を説明させてもらいます。需要なさそうですが(w

  1. ソースコードを文字列(上記の例ではstr)として用意します。
  2. Asm.newの引数として、ソースコードの入った文字列strを渡します。
  3. Asmクラスのinitalizeメソッドが呼ばれます。内部では、うけとった文字列をダイナミックにアセンブルし、共有ライブラリAsmFunctions.soを生成します。Asmクラスを使用する際にmkmfが、必要な理由はここにあります。
  4. 共有ライブラリAsmFunctions.soをカレントプロセスの読み込みます。
  5. 初期化が終わり、Asmクラスのインスタンスが返ってきます。
  6. Asmクラスのインスタンスは、execメソッドを所持しています。この関数の引数として、アセンブリソースコード中でグローバルシンボルとして定義されているものを与えると、そのグローバルシンボルを呼ぶことができます。

というわけで、明らかにIOや共有ライブラリの読み込み方が遅いので、間違っても高速化なんてできません(w
ご利用の際にはご注意を。