RError.com

RError.com Logo RError.com Logo

RError.com Navigation

  • 主页

Mobile menu

Close
  • 主页
  • 系统&网络
    • 热门问题
    • 最新问题
    • 标签
  • Ubuntu
    • 热门问题
    • 最新问题
    • 标签
  • 帮助
主页 / 问题 / 1274359
Accepted
Betflop
Betflop
Asked:2022-04-25 00:34:53 +0000 UTC2022-04-25 00:34:53 +0000 UTC 2022-04-25 00:34:53 +0000 UTC

解释器和编译器最终会生成相同的机器代码吗?

  • 772

在我的理解中,编译器获取程序的源代码,例如,

A = 2;
B = 3;
print(2 + 3);

编译它,在输出我们得到机器码。假设,有条件地,结果是 3 个命令:

1110
1101
1010

此外,我们不再需要编译器,我们可以将编译后的代码传输到任何地方(同一个处理器的地方)并且它会成功执行。

解释器会依次处理每一行,将其转换为其虚拟机的中间字节码,然后虚拟机将其命令依次翻译成机器码,即处理器命令

  1. 问题:最终解释器会执行相同的命令吗?

    1110
    1101
    1010
    
  2. 如果是这样,为什么永远不可能得到解释语言的编译代码?

  3. 另外,当他们谈论编译器时,他们使用编译器执行整个程序的短语,这是什么意思?毕竟,处理器还是会依次执行机器代码,一次一条指令?也就是说,到底什么是编译后的代码,解释后的代码在发送到处理器的一个命令上会执行什么?

ассемблер
  • 2 2 个回答
  • 10 Views

2 个回答

  • Voted
  1. Best Answer
    gbg
    2022-04-25T00:48:41Z2022-04-25T00:48:41Z

    第一种说法并不完全正确——尽管解释器执行的程序实际上可以和编译后的程序做同样的事情,但粗略地说,指令会出现在编译程序的指令之间,服务于解释器的内部工作.

    通常解释器一次通过一个表达式,解析这个表达式并立即执行它。根本没有代码生成。还有一个过渡选项——这是 JIT 编译(js、java),这已经是纯解释器(BASIC)和纯编译器(C++)之间的中间情况

    第二个子问题——有时你可以,如果你缩小可能的行动的数量。例如,KPHP允许您将 PHP 程序转换为 C++ 代码。

    为什么不能总是编译翻译语言的程序(许多语言都有)的最有力的例子eval()是执行该语言的字符串的函数。因此,有必要在编译后的程序中实现整个解释器。

    此外,从编译的程序中删除了很多东西——变量名、函数名、类型信息。有时,编写为带有方法的类的内容被吹成几条机器指令 - 因此从解释语言编译程序没有用 - 优化(为此您必须忍受 C++ 的不便)变得不可能。

    我从来没有听说过编译器会做一些“整体”的事情。编译器遍历程序(有时不止一次),然后立即为整个翻译单元创建二进制代码。

    • 5
  2. eanmos
    2022-04-25T02:27:41Z2022-04-25T02:27:41Z

    考虑一下当你给编译器一个高级编程语言的程序作为输入的情况。它会给你一个汇编语言的输出程序。以可执行文件、目标文件的形式,或者它可以简单地在屏幕上显示汇编代码。没关系,因为编译器的任务只是将程序从高级语言翻译成汇编语言。这就像一个从俄语到英语的翻译器。

    如果你给解释器一个高级编程语言的程序作为输入,解释器不会给你任何其他输出程序,它会执行你传递给它的程序。他怎么做并不重要。他可以用它为所欲为:他可以将其翻译成字节码并在虚拟机上执行;无法在任何地方翻译任何内容并立即转到 AST *并执行它;可以翻译成本机代码(汇编程序)并已经执行。这是最后一种情况,当解释器将代码翻译成处理器的本机指令时,称为JIT 编译‡。

    可以看出,编译器并没有执行程序,它只是将它从一种语言翻译成另一种语言。但是解释器执行程序,他是否将其翻译成某种东西并不重要,这是他自己的事。


    关于你的问题:

    1. 没有必要,主要的是观察到的程序行为保持不变。你可以编写不同的指令,最终做同样的事情。

    2. 为什么不,为什么不。例如,您可以获取JavaScript 代码的 JIT 编译结果。

    3. “*...他们使用这样的短语,编译器执行整个程序... ”,我从未听说过,您自己现在知道编译器什么都不做。“即 最后,解释的编译代码将在发送到处理器的 1 个命令上执行?仅在解释程序的情况下,这不是直接发生的,而是通过中介 - 解释器发生的。


    例如,让我们编写一个简单的语言解释器,它将具有三个运算符:递增计数器+、递减计数器-和输出计数器@。整个程序就是这三个字符的字符串。

    这就是这种语言的解释器的样子:

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    static unsigned int counter = 0;
    
    void increment_counter(void) { counter++;               }
    void decrement_counter(void) { counter--;               }
    void     print_counter(void) { printf("%u\n", counter); }
    
    int
    main(int argc, char *argv[])
    {
        /* Наша программа предается как первый аргумент командной строки. */
        char *source = argv[1];
    
        /* Проходим по всем символами нашей программы (операторам). */
        for (size_t i = 0; i < strlen(source); i++) {
            const char operator = source[i];
    
            /* Смотрим, что у нас за текущий оператор и выполняем его. */
            if (operator == '+')
                increment_counter();
            else if (operator == '-')
                decrement_counter();
            else if (operator == '@')
                print_counter();
        }
    }
    

    请注意,没有从我们的语言到汇编语言的翻译。当我们的解释器遇到一个 operator+时,它只是调用一些函数来做一些事情,在这种情况下增加一个计数器。

    也就是说,解释器理解我们想要得到的东西,没有将任何东西翻译成汇编程序,只是做了所有需要的事情。


    *这称为 tree-walk 解释。

    †好吧,如果您不考虑各种微架构细节,例如指令级别的并行性。

    ‡例如,有 HotSpot JVM。在执行程序时,它会在程序代码中找到这些经常执行且占用大量处理器时间的地方,并将它们编译成本机处理器指令,以便这些地方(它们称为热点)运行得更快。这是 JIT 编译技术的一个示例,即动态编译。

    • 4

相关问题

  • 难以在大会中创建 (for) 语句

  • call 如何使用堆栈?

  • STM32 中的中断/异常向量,汇编器

  • 寄存器和数据大小

  • 请帮助 turbo pascal 程序中的汇编程序

  • 举例说明将字符串输出到屏幕的过程 [关闭]

Sidebar

Stats

  • 问题 10021
  • Answers 30001
  • 最佳答案 8000
  • 用户 6900
  • 常问
  • 回答
  • Marko Smith

    表格填充不起作用

    • 2 个回答
  • Marko Smith

    提示 50/50,有两个,其中一个是正确的

    • 1 个回答
  • Marko Smith

    在 PyQt5 中停止进程

    • 1 个回答
  • Marko Smith

    我的脚本不工作

    • 1 个回答
  • Marko Smith

    在文本文件中写入和读取列表

    • 2 个回答
  • Marko Smith

    如何像屏幕截图中那样并排排列这些块?

    • 1 个回答
  • Marko Smith

    确定文本文件中每一行的字符数

    • 2 个回答
  • Marko Smith

    将接口对象传递给 JAVA 构造函数

    • 1 个回答
  • Marko Smith

    正确更新数据库中的数据

    • 1 个回答
  • Marko Smith

    Python解析不是css

    • 1 个回答
  • Martin Hope
    Alexandr_TT 2020年新年大赛! 2020-12-20 18:20:21 +0000 UTC
  • Martin Hope
    Alexandr_TT 圣诞树动画 2020-12-23 00:38:08 +0000 UTC
  • Martin Hope
    Air 究竟是什么标识了网站访问者? 2020-11-03 15:49:20 +0000 UTC
  • Martin Hope
    Qwertiy 号码显示 9223372036854775807 2020-07-11 18:16:49 +0000 UTC
  • Martin Hope
    user216109 如何为黑客设下陷阱,或充分击退攻击? 2020-05-10 02:22:52 +0000 UTC
  • Martin Hope
    Qwertiy 并变成3个无穷大 2020-11-06 07:15:57 +0000 UTC
  • Martin Hope
    koks_rs 什么是样板代码? 2020-10-27 15:43:19 +0000 UTC
  • Martin Hope
    Sirop4ik 向 git 提交发布的正确方法是什么? 2020-10-05 00:02:00 +0000 UTC
  • Martin Hope
    faoxis 为什么在这么多示例中函数都称为 foo? 2020-08-15 04:42:49 +0000 UTC
  • Martin Hope
    Pavel Mayorov 如何从事件或回调函数中返回值?或者至少等他们完成。 2020-08-11 16:49:28 +0000 UTC

热门标签

javascript python java php c# c++ html android jquery mysql

Explore

  • 主页
  • 问题
    • 热门问题
    • 最新问题
  • 标签
  • 帮助

Footer

RError.com

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

帮助

© 2023 RError.com All Rights Reserve   沪ICP备12040472号-5