许多(可能都是?)编程语言由汇编语言
组成如何用汇编语言实现lisp?
google有什么好的参考,手册,教程或关键字吗?
构建自己的lisp实现的任何官方规则/约定?
如尾递归应遵循一些实施例规则或其他东西..
感谢
答案 0 :(得分:23)
虽然其他评论和帖子都是正确的,但这个问题过于模糊,可能有点困惑,我不禁分享一些建议。我已经收集了许多关于实现Lisp的链接和书籍,因为我最近对语言实现有点着迷。当然,这是一个很深刻的话题,但阅读与Lisp相关的内容特别引人注目,因为如果在Lisp中实现Lisp编译器或解释器,只需使用read
,就可以跳过大量解析的强烈阅读。这使作者能够快速掌握编辑或解释的内容。这些建议是我读过或开始或正在阅读的书籍,主要涉及Scheme,而不是Common Lisp,但仍有一些兴趣。
如果您没有语言实施的背景,并且从未有过阅读有关经典Lisp和Scheme“metacircular evaluationators”的乐趣,我建议Structure and Interpretation of Computer Programs。如果您已经看过Lisp-in-Lisp(或Scheme-in-Scheme ...),您可以跳过。在SICP的最后两章中,作者为Lisp / Scheme和一些变体提供了一些不同的解释器,以及字节码编译器和虚拟机。它只是一本精彩的书,而且是免费的。
如果您没有时间阅读SICP,或者为了进入解释和编辑章节而不想轻松阅读,我建议The Little Schemer。尽管它很短,并且适用于Lisp和Scheme的新手,如果你从未见过用Lisp编写的Lisp解释器,它们确实提供了一本,这本书非常令人愉快,但由于可爱的风格,可能不适合所有人
还有另一本关于Scheme的免费书籍,类似于SICP,名为An Introduction to Scheme and its Implementation,我没有阅读,但作为几位的参考。那里有关于解释器和编译器的部分,它似乎比SICP更深入,处理像解析一样的毛茸茸的东西。它可能需要一个编辑器,但它仍然是一个令人印象深刻的产品。
如果想在Lisp中使用Lisp,你可以在更低层次上实现Lisp。
经常建议Lisp in Small Pieces。我已经阅读了大部分内容,并且可以说它绝对是一本很棒的书,充满了细节。我要用精梳梳理它,因为当你不懂东西时,它很容易撇去。我也很努力地从作者的网站上获取代码来运行;如果你得到它,我建议使用Gambit Scheme并从this发行版运行依赖Meroonet和Meroon的代码。 Lis Pie in Small Pieces提供了许多用Scheme编写的解释器,以及一个字节码编译器和一个编译器到C语言。
小件中的Lisp移动速度很快,而且非常密集。如果对你来说太过分了,可以从The Essentials of Programming Languages开始。我已经阅读了一些内容并且它非常好,但它更多的是解释器。显然其中一个旧版本(第一个?我不确定......)包括一个编译器。这三个版本之间似乎有很多变化,但第一个版本在亚马逊上非常便宜,所以请查看。
至于编译到C,这是一个有很多毛茸茸的重要主题。编译到C会带来所有这些奇怪的角落问题,例如如何优化尾调用和句柄闭包,一流的延续和垃圾收集,但它非常有趣,而且很多“真正的”Scheme实现都是这条路线。 Marc Feeley对此的介绍非常有趣,标题为The 90 Minute Scheme to C compiler。
我在编译到汇编时所用的资源较少,但是有一篇经常被推荐的论文介绍了Scheme到x86的编译,称为An Incremental Approach to Compiler Construction.它假定读者很少,但我发现它只是太快了,没有填写足够的细节。也许你会有更好的运气。
上述推荐很多来自一年多前来自mahmud的关于黑客新闻的怪物评论。它引用了许多ML资源,并使用continuation进行编译。在我的学习中我没有那么远,所以我不能说什么是好的。但这是一个非常有价值的评论。参考作品包括Andrew Appel的“Compiling with Continuations”和Paul Wilson的“Uniprocessor Garbage Collection Techniques”论文。
祝你好运!答案 1 :(得分:8)
我过去曾经想过它(然后使用C内核代替)。当然没有单一的“组装”,但对于x86 / 32bit,这就是我的计划:
基本值存储在64位节点中,其中三个最低位用作标记,含义如下:
000 -> cell (64 bits are basically two pointers: car/cdr)
001 -> fixnum (64-3-1 bits usable for values)
010 -> vector (32-3 bits for size and 32 bit for pointer to first element)
011 -> symbol (32 bits pointing to values in global env, 32 pointing to name)
100 -> native code (32 bits pointing to executable machine code, 32 bits to args)
101 -> float (using 64-3-1 bit by dropping 4 bits from mantissa)
110 -> string (using 32-3 bits for size and 32 bits pointing to bytes)
111 -> struct (32 bits pointing to definition, 32 bits pointing to content)
如果假设所有分配都是8字节的倍数(合理的,单元大小为8字节),则在考虑指针时仍然可以使用3位。实现一个简单的垃圾收集器(“活动”位)需要一个额外的位。在C实现中,我最终根据节点类型在各个部分(例如,如果是指针的高32位的最低有效位)分配该位。
我的想法是拥有两种类型的内存:“节点内存”(具有上述布局),在页面中分配并重用自由列表,“二进制内存”用于可变大小的字符串/代码/阵列。
根据节点类型需要特定代码来实现touch
函数,该函数以递归方式标记为活动节点引用的活动节点。
所有这些当然只是一种天真的方法,但我仍然使用“C”工作,我确信我也可以在汇编中完成(我的C代码在任何地方使用void *
所以是基本上只是一个便携式32位汇编程序)。对于我的C实现中的延迟,我只使用32位浮点数和整数(使用更高的32位)而不是使用所有可用位。
答案 2 :(得分:8)
查看Clozure Common Lisp以获取用于实现lisp的汇编语言示例。 Clozure CL主要在Common Lisp本身中实现,但是有一个用C语言编写的内核装配中的一些低级功能。
例如,这是一个来自 compiler / X86 / x86-lapmacros.lisp 的宏,它在x86硬件上实现原始CAR
函数,其中一个汇编指令分别为32位和64位:
(defx86lapmacro %car (src dest)
(target-arch-case
(:x8632
`(movl (@ x8632::cons.car (% ,src)) (% ,dest)))
(:x8664
`(movq (@ x8664::cons.car (% ,src)) (% ,dest)))))
如图所示,汇编代码本身以Lisp格式编码。移植到另一个平台涉及(除其他外)将这些低级操作转换为另一种汇编语言并交叉编译以在新平台上创建运行时。
ECL (Embeddable Common Lisp)通过编译到C中采用另一种方法。这样可以方便地将实现移植到具有C编译器的平台。
答案 3 :(得分:2)
您的问题基于非常过时的假设。现在,几乎没有语言实现是用汇编语言编写的,我知道没有任何Lisp实现。除了自托管实现,C是目前常用的实现语言。
如果要查看lisp函数的汇编语言表示,可以使用DISASSEMBLE function。
答案 4 :(得分:-2)