I've been recently working my way through Programming Language Pragmatics 3rd ed to learn more about how languages work underneath, and I've gotten a lot of mileage out of looking at the assembly produced by really basic GCC-compiled C code. I'm starting to get more comfortable with static languages from the C family, and I would like to begin looking into interpreted languages as well.
最近,我通过编程语言语用学(Programming Language pragmatic atics,第三版)学习了更多关于语言背后的工作原理,通过查看真正由gcc编译的C代码生成的程序集,我学到了很多东西。我开始更熟悉来自C族的静态语言,我也想开始研究解释语言。
Ruby, being my favorite scripting language, would be an excellent candidate for this. I think it'd be OK to start with MRI for learning purposes, and figure out how exactly all of the scanning/parsing/semantic analysis/binding/scoping and other magic happens behind the scenes.
Ruby是我最喜欢的脚本语言,它是这方面的优秀候选者。我认为从MRI开始学习是可以的,并弄清楚所有的扫描/解析/语义分析/绑定/范围以及其他魔法是如何在幕后发生的。
Is this described in detail anywhere, or is there any way for me to dig into it, like say, with the disassembly of a compiled program? I haven't done much digging with interpreted languages, so I wouldn't quite know where to start as far as MRI is concerned.
这是在任何地方详细描述的,还是有任何方法可以让我深入研究它,比如,分解一个编译过的程序?我还没有深入研究过解释语言,所以就核磁共振而言,我不知道从哪里开始。
Thanks!
谢谢!
3 个解决方案
#1
2
Ruby itself is written in C, so it might be worth taking a look at the code. https://github.com/ruby/ruby
Ruby本身是用C编写的,因此有必要看看代码。https://github.com/ruby/ruby
I also recommend Patrick Farley's article about method dispatch. http://www.klankboomklang.com/2007/09/14/method-dispatch/
我还推荐Patrick Farley关于方法调度的文章。http://www.klankboomklang.com/2007/09/14/method-dispatch/
#2
4
You can peek at the YARV bytecode of any bit of Ruby source code with RubyVM::InstructionSequence
您可以通过RubyVM::InstructionSequence查看任何Ruby源代码的YARV字节码。
Here's a quick example:
这里有一个简单的例子:
class Greeter
def initialize(name)
@name = name
end
def greet!
puts @name
end
end
Greeter.new("Charlie").greet!
Then you can compile it and disassemble it:
然后你可以对它进行编译和分解:
puts RubyVM::InstructionSequence.compile(src).disassemble
And get some output like this:
得到如下输出:
== disasm: <RubyVM::InstructionSequence:<compiled>@<compiled>>==========
0000 trace 1 ( 1)
0002 putspecialobject 3
0004 putnil
0005 defineclass :Greeter, <class:Greeter>, 3
0009 pop
0010 trace 1 ( 10)
0012 getinlinecache 19, <ic:0>
0015 getconstant :Greeter
0017 setinlinecache <ic:0>
0019 putstring "Charlie"
0021 send :new, 1, nil, 0, <ic:1>
0027 send :greet!, 0, nil, 0, <ic:2>
0033 leave
== disasm: <RubyVM::InstructionSequence:<class:Greeter>@<compiled>>=====
0000 trace 2 ( 1)
0002 trace 1 ( 2)
0004 putspecialobject 1
0006 putspecialobject 2
0008 putobject :initialize
0010 putiseq initialize
0012 send :"core#define_method", 3, nil, 0, <ic:0>
0018 pop
0019 trace 1 ( 5)
0021 putspecialobject 1
0023 putspecialobject 2
0025 putobject :greet!
0027 putiseq greet!
0029 send :"core#define_method", 3, nil, 0, <ic:1>
0035 trace 4 ( 8)
0037 leave ( 5)
== disasm: <RubyVM::InstructionSequence:initialize@<compiled>>==========
local table (size: 2, argc: 1 [opts: 0, rest: -1, post: 0, block: -1] s1)
[ 2] name<Arg>
0000 trace 8 ( 2)
0002 trace 1 ( 3)
0004 getlocal name
0006 dup
0007 setinstancevariable :@name, <ic:0>
0010 trace 16 ( 4)
0012 leave ( 3)
== disasm: <RubyVM::InstructionSequence:greet!@<compiled>>==============
0000 trace 8 ( 5)
0002 trace 1 ( 6)
0004 putnil
0005 getinstancevariable :@name, <ic:0>
0008 send :puts, 1, nil, 8, <ic:1>
0014 trace 16 ( 7)
0016 leave ( 6)
#3
1
There is a Japanese book that describes inner workings of MRI 1.7.3 called the Ruby Hacking Guide. A partial English translation is available.
有一本日本的书描述了核磁共振1.7.3的内部工作,叫做Ruby黑客指南。可获得部分英文翻译。
Even though the translation is not complete and the book was based on an older version of ruby, I still find it to be a superb resource. Many things covered by the book are probably still relevant in current ruby versions, such as the structure of objects, how instance variables are stored, how method lookup is done and so on.
尽管翻译不完整,这本书基于ruby的一个旧版本,但我仍然觉得它是一个极好的资源。本书所涉及的许多内容可能仍然与当前ruby版本相关,比如对象的结构、实例变量的存储方式、方法查找方式等等。
It is a very interesting read. You have to watch out for the differences between versions, though. Always keep the ruby source code at hand.
这是一本非常有趣的读物。不过,你必须注意不同版本之间的差异。始终保持ruby源代码在手边。
#1
2
Ruby itself is written in C, so it might be worth taking a look at the code. https://github.com/ruby/ruby
Ruby本身是用C编写的,因此有必要看看代码。https://github.com/ruby/ruby
I also recommend Patrick Farley's article about method dispatch. http://www.klankboomklang.com/2007/09/14/method-dispatch/
我还推荐Patrick Farley关于方法调度的文章。http://www.klankboomklang.com/2007/09/14/method-dispatch/
#2
4
You can peek at the YARV bytecode of any bit of Ruby source code with RubyVM::InstructionSequence
您可以通过RubyVM::InstructionSequence查看任何Ruby源代码的YARV字节码。
Here's a quick example:
这里有一个简单的例子:
class Greeter
def initialize(name)
@name = name
end
def greet!
puts @name
end
end
Greeter.new("Charlie").greet!
Then you can compile it and disassemble it:
然后你可以对它进行编译和分解:
puts RubyVM::InstructionSequence.compile(src).disassemble
And get some output like this:
得到如下输出:
== disasm: <RubyVM::InstructionSequence:<compiled>@<compiled>>==========
0000 trace 1 ( 1)
0002 putspecialobject 3
0004 putnil
0005 defineclass :Greeter, <class:Greeter>, 3
0009 pop
0010 trace 1 ( 10)
0012 getinlinecache 19, <ic:0>
0015 getconstant :Greeter
0017 setinlinecache <ic:0>
0019 putstring "Charlie"
0021 send :new, 1, nil, 0, <ic:1>
0027 send :greet!, 0, nil, 0, <ic:2>
0033 leave
== disasm: <RubyVM::InstructionSequence:<class:Greeter>@<compiled>>=====
0000 trace 2 ( 1)
0002 trace 1 ( 2)
0004 putspecialobject 1
0006 putspecialobject 2
0008 putobject :initialize
0010 putiseq initialize
0012 send :"core#define_method", 3, nil, 0, <ic:0>
0018 pop
0019 trace 1 ( 5)
0021 putspecialobject 1
0023 putspecialobject 2
0025 putobject :greet!
0027 putiseq greet!
0029 send :"core#define_method", 3, nil, 0, <ic:1>
0035 trace 4 ( 8)
0037 leave ( 5)
== disasm: <RubyVM::InstructionSequence:initialize@<compiled>>==========
local table (size: 2, argc: 1 [opts: 0, rest: -1, post: 0, block: -1] s1)
[ 2] name<Arg>
0000 trace 8 ( 2)
0002 trace 1 ( 3)
0004 getlocal name
0006 dup
0007 setinstancevariable :@name, <ic:0>
0010 trace 16 ( 4)
0012 leave ( 3)
== disasm: <RubyVM::InstructionSequence:greet!@<compiled>>==============
0000 trace 8 ( 5)
0002 trace 1 ( 6)
0004 putnil
0005 getinstancevariable :@name, <ic:0>
0008 send :puts, 1, nil, 8, <ic:1>
0014 trace 16 ( 7)
0016 leave ( 6)
#3
1
There is a Japanese book that describes inner workings of MRI 1.7.3 called the Ruby Hacking Guide. A partial English translation is available.
有一本日本的书描述了核磁共振1.7.3的内部工作,叫做Ruby黑客指南。可获得部分英文翻译。
Even though the translation is not complete and the book was based on an older version of ruby, I still find it to be a superb resource. Many things covered by the book are probably still relevant in current ruby versions, such as the structure of objects, how instance variables are stored, how method lookup is done and so on.
尽管翻译不完整,这本书基于ruby的一个旧版本,但我仍然觉得它是一个极好的资源。本书所涉及的许多内容可能仍然与当前ruby版本相关,比如对象的结构、实例变量的存储方式、方法查找方式等等。
It is a very interesting read. You have to watch out for the differences between versions, though. Always keep the ruby source code at hand.
这是一本非常有趣的读物。不过,你必须注意不同版本之间的差异。始终保持ruby源代码在手边。