【问题标题】:"All programs are interpreted". How?“所有程序都被解释”。如何?
【发布时间】:2011-10-06 20:05:12
【问题描述】:

计算机科学家会正确解释所有程序都是 解释,唯一的问题是在什么级别。 --perlfaq

所有程序是如何解释的?

【问题讨论】:

标签: perl


【解决方案1】:

机器代码在运行时由处理器解释,假设提供给某个架构(x86、PowerPC 等)的处理器的相同机器代码应该理论上工作相同,而不管具体情况如何模型的“内部布线”。

编辑:

我忘了提到拱门可能会为访问新寄存器之类的事情添加新指令,在这种情况下,为使用它而编写的代码将无法在该范围内的旧处理器上运行。就像您尝试使用旧版本的库,然后尝试使用仅在较新库中提供的功能时一样。

示例:许多 Linux 发行版仅作为 686 发布,尽管它属于“x86 家族”。这是由于使用了新指令。

【讨论】:

  • 另见microcode,它存在于许多现代 CPU 中:“...它驻留在特殊的高速内存中,将机器指令翻译成详细的电路级操作序列..." :-)
  • 我本来打算提出微码,但后来我意识到在 ASM 下,我真的不知道我在说什么:P
  • ...另外,Transmeta 虽然不再存在,但有一种有趣的方法可以“即时”将 x86 转换为本机 VLIW 指令集...我一直觉得它很有趣。
  • 即使使用硬连线所有指令的处理器(即中间没有真正的任何微码 - 一些 RISC 处理器这样做 AFAIK),这些电路正在解释指令.
  • ...关于这一点,我们进入电子学,然后是物理学,然后是存在主义哲学,然后是生命的意义,然后......然后......嗯......叹息。
【解决方案2】:

解释的层次真的很容易解释:

2:运行时语言(CLR、Java 运行时...)和脚本语言(Python、Ruby...)

1:程序集

0:二进制代码

编辑:我将脚本语言的级别更改为与运行时语言相同的级别。谢谢你的提示。 :-)

【讨论】:

  • 仅供参考:这些“脚本语言”实际上在大多数情况下被解释为与大多数 Java 和 CLR 字节码相同的级别:作为字节码。 (在您启动这些 VM 的 JIT 编译器之前:许多 - 至少包括 Sun 的 HotSpot 中的那个 - JIT 只是频繁执行的代码,通常只是一小部分)。
  • 从编译器和解释器的角度来看,“运行时”语言和“脚本”语言有什么区别?
  • Java 编译器 --> Javaruntime | C#、C、C++、J++ 和 VB --> CLR。这意味着运行时语言是编译器的结果。脚本语言是一种可以直接解释文本的语言。当然,您可以将 Python 或 Ruby 编译为运行时语言。但这没有意义。
  • 在过去的糟糕日子里,语言有时会从文本文件中逐行运行。命令 shell(如 Bash)可能是唯一能做到这一点的 shell。您可以调用这些脚本语言。如今,几乎所有东西都被编译成中间形式,无论是字节码还是内部解析树。事实上,Python 和 Ruby 有自己的运行时,Perl6 也一样。从理论上讲,Perl5 也不能这样。
  • "C --> CLR?"到底为什么会有人想要这样做?
【解决方案3】:

Perl 程序是由perl 程序读取的文本文件,它使perl 程序执行一系列操作。

Java 程序是一个文本文件,它已被转换为一系列字节码,然后由java 程序解释以执行一系列操作。

C 程序是一个文本文件,它通过C 编译器转换为汇编程序,然后由汇编器转换为机器代码。机器代码被加载到内存中,导致 CPU 执行一系列操作。

CPU 是由硬件工程师布置的晶体管、电阻器和其他电气位的混杂物,因此当施加电脉冲时,它会遵循物理定律支配的一系列动作。

物理学家目前正在研究是什么构成了这些规则以及如何解释它们。


基本上,每个计算机程序都由其他东西解释,然后将其转换为其他东西,最终转化为您当地附近的电子如何飞来飞去。


编辑/添加:我知道以上内容有点半开玩笑,所以让我添加一个稍微不那么愚蠢的补充:

在解释语言中,您可以通过一个简单的步骤从文本文件转到在您的计算机上运行的文件。

编译语言是您必须在中间采取额外步骤将语言文本转换为机器码或字节码的地方。

后者可以很容易地通过简单的转换转换成前者:

制作一个名为interpreted-c的程序,它可以接收一个或多个C文件,并且可以运行一个不带任何参数的程序:

#!/bin/sh
MYEXEC=/tmp/myexec.$$
gcc -o $MYEXEC ${1+"$@"} && $MYEXEC
rm -f $MYEXEC

现在您的C 程序属于哪个定义?比较和对比:

$ perl foo.pl
$ interpreted-c foo.c

【讨论】:

  • +1 但是,Java HotSpot 和类似的东西可能会 JIT 到机器代码以便完整......并且不确定 Parrot 上的 Perl 将如何分类,等等......(另外,它的价值, .NET 提供了一种“预 JIT”的方式)。
  • 添加到它,如果需要,编译器也可以生成汇编代码,以后可以组装。所以在这种情况下没有编译到机器代码级别,但最终每件事都会被转换:)
  • 不存在“编译语言”或“解释语言”。语言是一种语言,您可以为它编写编译器或解释器或两者兼而有之。一种语言本身并不局限于其中一种。比如还有C解释器,很多语言都有解释器和编译器。顺便说一下。编译器只是转换为另一种语言的东西。如果您有一个将 JavaScript 转换为 Perl 的程序,那么它也是一个编译器。顺便说一句,perl 在执行之前将 Perl 代码编译为字节码,然后执行,就像 java 一样。
  • @Sid Burn, Nit:Perl 源代码不会编译为字节码,而是编译为 OP 结构树。粗略地说,它被编译成操作码。
  • @Mark Mann,wrt 你的补充,解释的引用是“所有程序都被解释”,而不是“所有程序都可以被解释”
【解决方案4】:

我的第一个想法是查看 CPU 内部 — 见下文 — 但这是不对的。答案比这简单得多。

对 CPU 的高级描述是:

1. execute the current op
2. grab the next op
3. goto 1

比较一下 Perl 的解释器:

while ((PL_op = op = op->op_ppaddr(aTHX))) {
}

(是的,就是这样。)

毫无疑问,CPU 是一个解释器。

它只是说明了对某些东西是否被解释进行分类是多么无用。


原答案:

即使在 CPU 级别,程序也会被重写为更简单的指令,以允许 CPU 更快地执行更多的指令。这是通过更改它们的执行顺序并并行执行它们来完成的。例如,英特尔的超线程。

更深入地讲,每条指令都被视为自己的程序,用于路由电子信号。请参阅微码。

【讨论】:

    【解决方案5】:

    我可以编写一个 Game Boy 解释器,其工作方式类似于 Java 虚拟机的工作方式,将 z80 机器指令视为字节码。假设原版是用 C1 编写的,那是否意味着 C 突然变成了一种解释性语言,只是因为我像使用它一样使用它?

    从另一个角度来看,gcc 可以将 C 编译成机器码,供许多不同的处理器使用。没有理由目标机器必须与您正在编译的机器相同。事实上,这是为 AVR 和其他微控制器编译 C 代码的常用方法。

    作为抽象问题,编译器的工作是将平面文本翻译成结构,然后将该结构翻译成可以在某处执行的东西。无论执行什么,在真正执行之前都可能有自己的层次结构分解。

    一旦你开始按照这些思路思考,就会有很多力量可用。

    这方面的好书是Structure and Interpretation of Computer Programs。即使你只读完第一章(或第一章的一半),我想你也会学到很多东西。

    1我认为大多数 Game Boy 的东西都是手工编码的 ASM,但原则仍然存在。

    【讨论】:

      猜你喜欢
      • 2023-03-17
      • 1970-01-01
      • 2021-07-23
      • 2020-10-04
      • 1970-01-01
      • 2018-03-14
      • 1970-01-01
      • 2019-09-10
      • 1970-01-01
      相关资源
      最近更新 更多