- 浏览: 3052685 次
- 性别:
- 来自: 海外
文章分类
- 全部博客 (430)
- Programming Languages (23)
- Compiler (20)
- Virtual Machine (57)
- Garbage Collection (4)
- HotSpot VM (26)
- Mono (2)
- SSCLI Rotor (1)
- Harmony (0)
- DLR (19)
- Ruby (28)
- C# (38)
- F# (3)
- Haskell (0)
- Scheme (1)
- Regular Expression (5)
- Python (4)
- ECMAScript (2)
- JavaScript (18)
- ActionScript (7)
- Squirrel (2)
- C (6)
- C++ (10)
- D (2)
- .NET (13)
- Java (86)
- Scala (1)
- Groovy (3)
- Optimization (6)
- Data Structure and Algorithm (3)
- Books (4)
- WPF (1)
- Game Engines (7)
- 吉里吉里 (12)
- UML (1)
- Reverse Engineering (11)
- NSIS (4)
- Utilities (3)
- Design Patterns (1)
- Visual Studio (9)
- Windows 7 (3)
- x86 Assembler (1)
- Android (2)
- School Assignment / Test (6)
- Anti-virus (1)
- REST (1)
- Profiling (1)
- misc (39)
- NetOA (12)
- rant (6)
- anime (5)
- Links (12)
- CLR (7)
- GC (1)
- OpenJDK (2)
- JVM (4)
- KVM (0)
- Rhino (1)
- LINQ (2)
- JScript (0)
- Nashorn (0)
- Dalvik (1)
- DTrace (0)
- LLVM (0)
- MSIL (0)
最新评论
-
mldxs:
虽然很多还是看不懂,写的很好!
虚拟机随谈(一):解释器,树遍历解释器,基于栈与基于寄存器,大杂烩 -
HanyuKing:
Java的多维数组 -
funnyone:
Java 8的default method与method resolution -
ljs_nogard:
Xamarin workbook - .Net Core 中不 ...
LINQ的恶搞…… -
txm119161336:
allocatestlye1 顺序为 // Fields o ...
最近做的两次Java/JVM分享的概要
之前被NS老兄激起了兴趣发过beef帖,主要是显示可以很容易的写出Ruby扩展用于直接生成机器码,连接到Ruby的对象系统上,然后像调用普通Ruby方法一样去使用。我觉得这个很有趣,想看看有没有好的办法做个internal DSL出来在Ruby里写类似MASM语法的汇编,然后让Bk201生成机器码出来执行。
昨天看到某帖之后又把我的兴趣激起来了……在动手实现DSL之前,我先搜了一下Ruby assembler,发现Ryan Davis写了个叫Wilson的库,功能跟我想要的很类似,虽然语法有点不同,好歹还是NASM而不是AT&T式的。当前版本是1.1.1。我现在是在Windows XP SP3/Ruby 1.8.6上测试的。
安装该库用:
加载该库用require 'wilson'。它会对Ruby一些核心类做monkey patch,要注意。
原本Wilson是为在Mac上使用而编写,但整个代码都是纯Ruby的,所以在Windows上使用稍微修改一下平台相关的代码就行。在ruby安装目录的gems/1.8/gems/wilson-1.1.1/lib/目录下,
wilson.rb,第1135-1136行:
.dylib是Mac上的动态链接库文件的后缀。这里要改为:
就可以在Windows上正常使用了。
Wilson在一些测试里会使用到RubyInline,有兴趣的话也可以装上:
加载该库用require 'inline'。
如果把MASM语法下op dest, src的形式看作前缀表达式,那么Wilson的DSL表现出来的就是dest.op src形式的“中缀表达式”。所以原本写作xor eax, eax的汇编,在Wilson就写作eax.xor eax。习惯了之后这么写也挺顺的。
让我们来看看Wilson in action~
Wilson的实现暂时还不太完善,例如说声明一个汇编方法用defasm,其参数包括生成方法的名字和参数列表(的名字),但在定义方法体时却暂时还无法用名字与引用参数,只能通过arg(0)、arg(1)之类的形式去引用。寻址模式中放大倍数的版本也都还没实现,上面代码中的ary_store本来可以用lea ecx, dword ptr [ecx + edx*4]一条指令完成一个乘法和一个加法,但Wilson还不支持edx*4的形式,非要用的话只好如下所示:
把机器码硬插到stream里……OTL
另外Wilson在把某些指令汇编到机器码时有问题。我试过跟ebx相关的几条指令,生成出来的都是错的:(测试摘自Wilson里的test_wilson.rb,注释是我添加的)
为什么作者的测试用例里assert的数据就已经跟我所知道的机器码不一致了 OTL
回头我把它修修看看有没有必要发个patch过去……人家或许对Windows没兴趣,顺带就对这patch没兴趣了 =v=
顺带说说上面的例子是如何能运行的。注意到我什么错误检查都没做,所以传入的参数跟我预期的使用方式不符的话程序基本上就要crash了。
第一个例子比较直观,只有最后的dec eax指令可能有点怪。这是因为Ruby的Fixnum表现的是31位带符号整数,普通的31位补码表示的整数要转换为Fixnum的公式是(n << 1) + 1。例子中a与b都是Fixnum,它们的高31位就是原本的数值,而末尾的1则是Fixnum的tag。把它们直接相加,虽然高位是对位加起来了,但末尾的tag本来不该参与运算却也相加了,于是通过dec eax指令把多加的tag再减回去。
后两个例子都涉及到CRuby中对象布局的实现细节。CRuby 1.8.6里有这两个结构体:
数组对象的背后就是靠RArray结构体来支撑的,而它的开头又包含了一个RBasic结构体。可以把RBasic看作是所有Ruby对象都有的header。由此可以知道,在32位x86上,RArray的len成员位于偏移量4*2 == 8的位置上,表示该数组对象的长度(元素个数);ptr成员位于偏移量4*4 == 16的位置上,它所指向的就是数组的实际内容,是一大块连续的空间。
在第二个例子,ary_len里,首先把第一个参数放入eax中。这个参数是指向一个RArray实例的指针。然后再把eax += 8,得到RArray.len的地址。接着通过mov eax, dword ptr [eax]指令,把RArray.len的值取出来。最后使用to_ruby“宏”将数字转换为Ruby的Fixnum,返回。
在第三个例子,ary_store里,过程跟前一个例子差不多,关键思路是达到RARRAY(ary)->ptr[idx] = val的目的。
OK,可以靠Wilson做点更有趣的事情了 ^ ^
用上硬插,状况就跟Bk201的现状差不多了
昨天看到某帖之后又把我的兴趣激起来了……在动手实现DSL之前,我先搜了一下Ruby assembler,发现Ryan Davis写了个叫Wilson的库,功能跟我想要的很类似,虽然语法有点不同,好歹还是NASM而不是AT&T式的。当前版本是1.1.1。我现在是在Windows XP SP3/Ruby 1.8.6上测试的。
安装该库用:
gem install wilson
加载该库用require 'wilson'。它会对Ruby一些核心类做monkey patch,要注意。
原本Wilson是为在Mac上使用而编写,但整个代码都是纯Ruby的,所以在Windows上使用稍微修改一下平台相关的代码就行。在ruby安装目录的gems/1.8/gems/wilson-1.1.1/lib/目录下,
wilson.rb,第1135-1136行:
dir = File.join(Config::CONFIG["prefix"], "lib") dlload File.join(dir, "libruby.dylib")
.dylib是Mac上的动态链接库文件的后缀。这里要改为:
dir = File.join(Config::CONFIG["prefix"], "bin") dlload File.join(dir, Config::CONFIG["LIBRUBY_SO"])
就可以在Windows上正常使用了。
Wilson在一些测试里会使用到RubyInline,有兴趣的话也可以装上:
gem install rubyinline
加载该库用require 'inline'。
如果把MASM语法下op dest, src的形式看作前缀表达式,那么Wilson的DSL表现出来的就是dest.op src形式的“中缀表达式”。所以原本写作xor eax, eax的汇编,在Wilson就写作eax.xor eax。习惯了之后这么写也挺顺的。
让我们来看看Wilson in action~
require 'rubygems' require 'wilson' class A defasm :add, :a, :b do a, b = arg(0), arg(1) eax.mov a eax.add b eax.dec end defasm :ary_len, :ary do ary = arg(0) eax.mov ary eax.add 4*2 # skip RBasic.flags and RBasic.klass eax.mov eax.m to_ruby eax end defasm :ary_store, :ary, :idx, :val do ary, idx, val = arg(0), arg(1), arg(2) eax.mov ary ecx.mov(eax + 4*4) # address of RArray.ptr edx.mov idx from_ruby edx edx.shl 2 ecx.add edx edx.mov val ecx.m.mov edx end end a = A.new p a.add(3, 5) #=> 8 p a.ary_len([]) #=> 0 p a.ary_len([2, 4, 6, 8]) #=> 4 ary = [1, 2, 3] a.ary_store(ary, 2, 4) #=> [1, 2, 4] p ary #=> [1, 2, 4]
Wilson的实现暂时还不太完善,例如说声明一个汇编方法用defasm,其参数包括生成方法的名字和参数列表(的名字),但在定义方法体时却暂时还无法用名字与引用参数,只能通过arg(0)、arg(1)之类的形式去引用。寻址模式中放大倍数的版本也都还没实现,上面代码中的ary_store本来可以用lea ecx, dword ptr [ecx + edx*4]一条指令完成一个乘法和一个加法,但Wilson还不支持edx*4的形式,非要用的话只好如下所示:
class A defasm :ary_store, :ary, :idx, :val do ary, idx, val = arg(0), arg(1), arg(2) eax.mov ary ecx.mov(eax + 4*4) # RArray.ptr edx.mov idx from_ruby edx # ecx.lea(ecx + edx*4) # this is not supported by Wilson yet # hack: lea ecx, dword ptr [ecx + edx*4] self.stream.concat [0x8D, 0x0C, 0x91] edx.mov val ecx.m.mov edx end end
把机器码硬插到stream里……OTL
另外Wilson在把某些指令汇编到机器码时有问题。我试过跟ebx相关的几条指令,生成出来的都是错的:(测试摘自Wilson里的test_wilson.rb,注释是我添加的)
def test_mov_ebx_m_ecx_edx_offset # mov ebx, dword ptr [ecx + edx + 1] # 8B 5C 11 01 asm.ebx.mov(asm.ecx + asm.edx + 1) # this test looks broken # 8B 1C 51 01 # wrong machine code assert_equal [0x8B, 0b00011100, 0b01010001, 1], stream end def test_mov_ebx_m_ecx_edx_big_offset # mov ebx, dword ptr [ecx + edx + 256] # 8B 9C 11 00 01 00 00 asm.ebx.mov(asm.ecx + asm.edx + 256) # this test looks broken as well... # 8B 1C 91 00 01 00 00 # wrong machine code assert_equal [0x8B, 0b00011100, 0b10010001, 0, 1, 0, 0], stream end def test_mov_m_ecx_edx_offset_ebx # mov dword ptr [ecx + edx + 1], ebx # 89 5C 11 01 (asm.ecx + asm.edx + 1).mov asm.ebx # this test looks broken # 89 1C 51 01 # is everything related to ebx broken? assert_equal [0x89, 0b00011100, 0b01010001, 1], stream end
为什么作者的测试用例里assert的数据就已经跟我所知道的机器码不一致了 OTL
回头我把它修修看看有没有必要发个patch过去……人家或许对Windows没兴趣,顺带就对这patch没兴趣了 =v=
顺带说说上面的例子是如何能运行的。注意到我什么错误检查都没做,所以传入的参数跟我预期的使用方式不符的话程序基本上就要crash了。
第一个例子比较直观,只有最后的dec eax指令可能有点怪。这是因为Ruby的Fixnum表现的是31位带符号整数,普通的31位补码表示的整数要转换为Fixnum的公式是(n << 1) + 1。例子中a与b都是Fixnum,它们的高31位就是原本的数值,而末尾的1则是Fixnum的tag。把它们直接相加,虽然高位是对位加起来了,但末尾的tag本来不该参与运算却也相加了,于是通过dec eax指令把多加的tag再减回去。
后两个例子都涉及到CRuby中对象布局的实现细节。CRuby 1.8.6里有这两个结构体:
struct RBasic { unsigned long flags; VALUE klass; }; struct RArray { struct RBasic basic; long len; union { long capa; VALUE shared; } aux; VALUE *ptr; };
数组对象的背后就是靠RArray结构体来支撑的,而它的开头又包含了一个RBasic结构体。可以把RBasic看作是所有Ruby对象都有的header。由此可以知道,在32位x86上,RArray的len成员位于偏移量4*2 == 8的位置上,表示该数组对象的长度(元素个数);ptr成员位于偏移量4*4 == 16的位置上,它所指向的就是数组的实际内容,是一大块连续的空间。
在第二个例子,ary_len里,首先把第一个参数放入eax中。这个参数是指向一个RArray实例的指针。然后再把eax += 8,得到RArray.len的地址。接着通过mov eax, dword ptr [eax]指令,把RArray.len的值取出来。最后使用to_ruby“宏”将数字转换为Ruby的Fixnum,返回。
在第三个例子,ary_store里,过程跟前一个例子差不多,关键思路是达到RARRAY(ary)->ptr[idx] = val的目的。
OK,可以靠Wilson做点更有趣的事情了 ^ ^
评论
2 楼
RednaxelaFX
2009-09-20
night_stalker 写道
硬插也没什么不好 …… AOT 而已 ……
用上硬插,状况就跟Bk201的现状差不多了
1 楼
night_stalker
2009-09-20
硬插也没什么不好 …… AOT 而已 ……
发表评论
-
字符串的一般封装方式的内存布局 (0): 拿在手上的是什么
2013-11-04 18:22 21508(Disclaimer:未经许可请 ... -
字符串的一般封装方式的内存布局
2013-11-01 12:55 0(Disclaimer:未经许可请 ... -
RubyConf notes
2011-11-08 19:10 0symmetric coroutine Fiber#trans ... -
ShanghaiOnRails第八次线下活动——你不需要知道的Ruby实现
2010-11-12 15:39 2850上个月底正好赶上参加了ShanghaiOnRails 第八次线 ... -
JRuby的运行模式
2010-11-01 11:21 0// 老的JRuby还是用org.jruby.evaluato ... -
你不需要知道的Ruby草稿
2010-10-27 11:25 0一些Ruby实现 Ruby 1.8 树遍历解释 Ruby 1 ... -
Ruby里的fiber/coroutine例子
2010-01-26 18:33 0Ruby 1.9开始支持fiber。与“fiber”一词的一般 ... -
JRuby使用技巧收集
2009-12-28 09:35 0java.lang.Thread.new { puts &qu ... -
特殊类型的eigenclass
2009-12-17 03:39 0Fixnum的实例没有eigenclass true、fals ... -
奇怪的参数
2009-12-08 02:25 0默认参数与闭包的组合 真正的问题不是只是默认参数看起来很诡异, ... -
MacRuby的执行模式
2009-12-07 07:41 0mailing-list macruby-devel http ... -
Rubinius的执行模型
2009-12-05 15:22 0Rubinius wants to help YOU make ... -
Ruby 1.8和1.9中String#hash的实现
2009-11-22 18:23 01.8 string.c int rb_str_hash(s ... -
To囧:拿你来测测Watir...
2009-11-21 22:38 3447iaimstar 写道@RednaxelaFX 你最近ruby ... -
[标题党] MagLev中GC类的真相……
2009-11-21 14:46 0注意到本文的标题:我是说“GC类”的真相,不是说GC的真相哦~ ... -
小试rubyzip的一个脚本
2009-11-17 20:42 3462呼,今天开始3天都是新人培训,总算可以抽点时间发一帖。 现在在 ... -
爬一下Google和百度看口碑对它们做的SEO效果如何
2009-11-09 00:27 0#!/usr/bin/env ruby require ... -
把Mechanize的html_parser改回到Hpricot
2009-11-08 14:45 3120记得我最初开始用Nokogir ... -
使用新的RubyInstaller
2009-11-07 02:37 0Hpricot的安装需要编译,需要devkit -
Ruby metaprogramming tech notes
2009-09-28 15:39 0class Builder def self.build ...
相关推荐
标题中的"Go1.9.2.windows-amd64.msi"是指Go编程语言的1.9.2版本在Windows操作系统上使用的64位安装程序。Go,也被称为Golang,是由Google开发的一种静态类型的、编译式的、跨平台的编程语言。它设计简洁、高效,...
"Wilson.Win32.IO" 是一个专为解决`PathTooLongException`问题的源代码库,它几乎重新实现了 .NET Framework ...此外,对于跨平台的应用,需要考虑在非Windows系统上的适配,因为它们可能不接受长路径或使用不同的API。
本书《Windows PowerShell Step by Step》(第三版)由微软官方认证专家 Ed Wilson 撰写,是学习 Windows PowerShell 的权威指南。本书全面覆盖了 Windows PowerShell 5.0 的新特性和高级功能,并通过逐步指导的方式...
在Windows上,多个Python安装可能会相互冲突,并且您的“ python”命令可能会运行不同的版本,而不是您打算的版本。 从命令行运行“ python --version”以检查您的Python版本。 PyWD2015支持Pyt
在Windows上,虽然系统调用机制不同,但基本思路相似,需要调用Windows API函数,如`WriteFile`和`ExitProcess`。 编译汇编程序时,你可以使用Yasm命令行工具: ```bash yasm -f win32 hello.asm -o hello.obj ```...
根据给定文件的信息,我们可以总结出关于《Windows PowerShell 2.0 Best Practices》一书的重要知识点,本书由Ed Wilson撰写并由Microsoft Press于2010年出版。 ### 关键知识点概览 #### 1. **Windows PowerShell ...
在Windows上使用GCC通常涉及到MinGW(Minimalist GNU for Windows)或MSYS2等环境,它们提供了与Linux类似的编译环境。 1. **MinGW**: MinGW是GCC在Windows上的一个移植版本,它包含了头文件、库以及Gnu工具集,...
这些内容组合在一起,构成了一个完整的Go语言开发环境,使得开发者能够在Windows平台上进行Go语言的应用开发。 总之,"go1.9.2.windows-amd64"是一个适用于64位Windows系统的Go语言版本,通过提供的MSI安装文件,...
在学习和使用这份源码时,开发者可以了解如何利用Windows API与操作系统交互,实现输入法的核心功能。此外,通过阅读和理解源码,还可以学习到C语言在处理复杂逻辑和用户界面方面的技巧。对于希望开发自己的输入法...
《Windows Scripting Self-Paced Learning Guide》是一本由Microsoft Press出版的专业书籍,作者为Ed Wilson。该书旨在为读者提供一个系统学习Windows脚本编程的方法。通过本书的学习,读者可以掌握Windows环境下...
使用绿色按钮将文件下载为zip格式,或使用Git将存储库克隆到您的计算机上。 发行版 版本v1.0对应于已出版书籍中的代码,没有更正或更新。 会费 请参阅文件Contributing.md,以获取有关如何为该存储库做出贡献的更多...
它为读者提供了深入理解和高效使用Windows PowerShell所需的知识和技巧。本书覆盖了从基础知识到高级主题的广泛内容,适合不同层次的学习者。 #### 书籍结构与主要内容 本书分为两个主要部分:理解Windows ...
本书由Ed Wilson编写,并获得微软公司的授权出版,旨在帮助读者深入了解和掌握Windows PowerShell 3.0的强大功能。 ### 一、Windows PowerShell 3.0概述 在第一章“Windows PowerShell 3.0概述”中,作者首先介绍...
- **收购协调员**:Jessica Wilson。 - **全球业务发展副总裁**:Richard Kristof。 - **技术编辑**:Rory McCaw。 - **校对编辑**:Carl Wikander。 - **索引编制者**:Jack Lewis。 - **生产和编辑服务**:Apollo ...
9. `Howtoinstall.txt`:安装指南,提供了关于如何在用户的系统上安装和运行这个图形查看器的步骤。 综上所述,Don W. Wilson的开源项目是一个用Delphi开发的图形查看器,支持多种图像格式,并且采用了创新的3D绘制...