RError.com

RError.com Logo RError.com Logo

RError.com Navigation

  • 主页

Mobile menu

Close
  • 主页
  • 系统&网络
    • 热门问题
    • 最新问题
    • 标签
  • Ubuntu
    • 热门问题
    • 最新问题
    • 标签
  • 帮助
主页 / 问题 / 1113379
Accepted
Krutos VIP
Krutos VIP
Asked:2020-04-21 16:02:05 +0000 UTC2020-04-21 16:02:05 +0000 UTC 2020-04-21 16:02:05 +0000 UTC

机器代码和编译成它 - 怎么样?

  • 772
  • 编译为本机代码是如何工作的,它是如何工作的?
  • 如何自己编写机器码程序?
  • 例如,如何用 JS、Python、C 或 C++ 编写这样的编译器?

我想使用它,因为我一直梦想着.exe自己构建它,而不需要现成的编译器的帮助。

компиляция
  • 1 1 个回答
  • 10 Views

1 个回答

  • Voted
  1. Best Answer
    eanmos
    2020-04-21T16:57:59Z2020-04-21T16:57:59Z

    裸机

    每个特定处理器(例如,Intel Core i3-4160 或 ARM Cortex-A9)都有自己的微架构并实现指令集架构。

    • 微架构在电子元件和逻辑门级别定义处理器的结构。

    • 指令集级架构 (ISA)粗略地定义了处理器可以执行的指令。这种架构是从微架构中抽象出来的。来自不同社区的处理器可能实现相同的架构(例如,许多 Intel 和 AMD 处理器实现相同的x86系列架构)。

    如果两个处理器实现相同的 ISA,那么它们可以执行相同的程序。ISA 定义了程序员可以使用哪些命令,可以使用哪些寄存器,如何使用分页、虚拟内存等。此外,它还定义了处理器可以理解的命令格式。

    每个处理器程序只是一组连续的指令。当它启动时,处理器从内存中的一个称为复位向量的地址处选择一条指令,并开始执行该程序,直到电源关闭。

    用机器代码编写程序非常简单——您只需要获取处理器实现的 ISA 参考(例如,英特尔 64 和 IA-32 架构软件开发人员手册)并逐字节编写必要的指令。

    当然,在我们这个时代,没有人用机器代码编写代码,因为一个人很难处理大量的数字和复杂的指令格式(尤其是在 x86 中)。由于这种复杂性,已经创造了汇编语言,它为处理器指令引入了简单的助记符。

    例如,一条 x86 汇编指令MOV可以编码大约 20 条不同的处理器指令MOV1。汇编程序读取您的汇编语言程序并将其转换为二进制文件2,该文件再次只是对连续处理器指令进行编码的字节序列。

    这是汇编语言程序的摘录可能如下所示:

    cli
    lgdt (gdtr)
    mov %cr0, %eax
    or $0x1, %eax
    mov %eax, %cr0
    

    这是机器语言程序的样子:

    0000000 05ea 007c 3100 8ec0 8ed8 bcd0 7c00 1688
    0000010 7cdb c031 c08e 00bb 8a80 db16 b67c b100
    0000020 b502 b000 e830 0053 59e8 8400 75c0 fa30
    0000030 010f f416 0f7c c020 8366 01c8 220f eac0
    0000040 7c44 0008 b866 0010 d88e c08e e08e e88e
    0000050 d08e 00bc 07c0 e800 03a4 0000 ebf4 befd
    0000060 7cbc 03e8 f400 fdeb 5350 30fc b4ff ac0e
    0000070 c084 0474 10cd f7eb 585b b4c3 cd02 7213
    0000080 3102 c3c0 1e9c 0657 fa56 c031 d88e 10bf
    0000090 f705 8ed0 bec0 0500 058a 2650 048a 2650
    00000a0 04c6 c600 be05 8026 be3c 2658 0488 8858
    00000b0 3105 74c0 4001 075e 1f5f c39d 3241 2030
    00000c0 7369 6420 7369 6261 656c 2e64 4820 6c61
    00000d0 2074 6874 2065 5043 2e55 0000 0000 0000
    00000e0 0000 0000 ffff 0000 9a00 00cf ffff 0000
    00000f0 9200 00cf 0017 7cdc 0000 0000 0000 0000
    

    显然,汇编代码更易于阅读和编写。

    现在你有足够的知识可以像打开字典一样打开参考书,用机器码编写程序并在处理器上执行它。但是,如果您想编写一个可以在任何操作系统上运行的程序,这将不起作用。

    操作系统

    操作系统是另一个抽象层次,它完全剥夺了我们无限期使用处理器的能力,迫使它执行我们的任何命令3。操作系统做了很多不同的事情,但让我们只关注一个——运行可执行文件。

    正如我所说,每个处理器程序只是一个指令序列,但每个操作系统程序都是一个特殊的字节序列,它具有特殊的结构,不仅包括处理器指令。

    以 Windows 10 为例,它适用于具有称为Portable Executable.exe的特殊格式的可执行文件。它有一个相当复杂的结构。除了实际的机器指令集之外,它还包含确定段的地址和大小、导入和导出表、特殊签名等所需的信息。

    因此,例如,为了手动编写将在 Windows 10 上运行的机器代码程序,我们除了编写程序本身外,还需要将其转换为可移植可执行文件格式。

    但即使这样也不够。我们必须熟悉称为ABI的约定,并使用这些约定而不是其他约定用机器代码编写程序。

    这里有必要将所有拼图拼凑在一起:程序必须对处理器有效,二进制文件的格式必须是操作系统可以理解的,程序必须能够与操作系统正确通信等。如果您在十六进制编辑器中编写程序,这一切都很难确保。

    您可以从用汇编语言编写程序开始(是的,您还必须学习特定汇编语言的语法和英特尔或 AT&T的方言)。NASM中的“Hello, World”如下所示:

    ; ----------------------------------------------------------------------------
    ; helloworld.asm
    ;
    ; This is a Win32 console program that writes "Hello, World" on one line and
    ; then exits.  It needs to be linked with a C library.
    ; ----------------------------------------------------------------------------
    
        global  _main
        extern  _printf
    
        section .text
    _main:
        push    message
        call    _printf
        add     esp, 4
        ret
    message:
        db  'Hello, World', 10, 0
    

    你需要它吗?

    如今,计算机已经变得非常复杂,有几十层抽象。甚至现代处理器的 ISA 指令也不是原子实体,并且处理器将每条指令作为一组更小的指令执行 -微操作(微操作由此类微操作组成)。

    事实上,用汇编语言(尤其是机器语言)编写的能力是毫无用处的。能够简单地阅读和理解汇编程序列表更加实用,并且可以真正派上用场。

    这首先是不切实际的,因为没有什么比“你好,世界!”更复杂的了。在机器代码中你不会写。在汇编器中 - 是的,您可以编写它,但要花大量时间在上面,这些时间可以花在更有用的事情上。


    1. 有趣的是,MOVx86 中的指令是图灵完备的,即任何程序都可以单独使用该指令编写。甚至还有一个只使用这一条指令的特殊编译器。

    2. 一些汇编程序可以立即生成所需格式的可执行文件。包括便携式可执行文件。

    3. 我说的是现代操作系统,如 Windows 或 Linux。

    • 10

相关问题

  • 在 Sublime Text 3 中编译时的输入问题

  • 您的 CPU 支持未编译此 TensorFlow 二进制文件以使用的指令:AVX AVX2

  • 如何在 VisualStudio 的项目生成阶段设置输出二进制文件的名称

  • 使用 MinGW 和 MSYS2 构建库,配置 ./Configure

Sidebar

Stats

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

    如何从列表中打印最大元素(str 类型)的长度?

    • 2 个回答
  • Marko Smith

    如何在 PyQT5 中清除 QFrame 的内容

    • 1 个回答
  • Marko Smith

    如何将具有特定字符的字符串拆分为两个不同的列表?

    • 2 个回答
  • Marko Smith

    导航栏活动元素

    • 1 个回答
  • Marko Smith

    是否可以将文本放入数组中?[关闭]

    • 1 个回答
  • Marko Smith

    如何一次用多个分隔符拆分字符串?

    • 1 个回答
  • Marko Smith

    如何通过 ClassPath 创建 InputStream?

    • 2 个回答
  • Marko Smith

    在一个查询中连接多个表

    • 1 个回答
  • Marko Smith

    对列表列表中的所有值求和

    • 3 个回答
  • Marko Smith

    如何对齐 string.Format 中的列?

    • 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