计科幼幼班

今天的分享可以(粗浅)解答以下几个问题: - 如何制作一台计算机 - 苹果的 Rosetta 是怎么把 x86 的程序运行在 arm 上的 - Steam Deck 是怎么把 Windows 的游戏运行在 Linux 上的 ![](https://img2023.cnblogs.com/blog/3224918/202309/3224918-20230907122604638-303195272.jpg) ![](https://img2023.cnblogs.com/blog/3224918/202309/3224918-20230907122604677-612295529.jpg) ![](https://img2023.cnblogs.com/blog/3224918/202309/3224918-20230907122604703-1910172391.jpg) ## 如何制作一台计算机 - [制作教程1](https://www.bilibili.com/video/BV1j7411g7GE/) - [制作教程2](https://www.bilibili.com/video/BV11h411w7bc/) - [正经的制作教程](https://www.nand2tetris.org/) [逻辑门](https://zh.wikipedia.org/zh-cn/%E9%82%8F%E8%BC%AF%E9%96%98)是什么? 是数字逻辑电路中的基本单元,可以用真值表定义一个逻辑门,以 [NAND](https://en.wikipedia.org/wiki/NAND_logic)(Not AND)逻辑门为例: | Input A | Input B | Output | |-------|---|--------| | 0 | 0 | 1 | | 0 | 1 | 1 | | 1 | 0 | 1 | | 1 | 1 | 0 | Q:它有什么用? A:我们只用它就可以制作出计算机 开工:[https://nandgame.com](https://nandgame.com) 先来制作 NAND 本身,下面是用于制作 NAND 的原材料: ![](https://img2023.cnblogs.com/blog/3224918/202309/3224918-20230907122604529-1291671408.jpg) 三个圆是元器件的引脚,上面的引脚是输出,下面是控制(c)和输入(in)。 控制端的原理很简单,就是电磁铁,c 通电,则 relay 的舌片被磁铁吸住,控制 relay 开或关。 in 是电源,始终有电,我们把有电的状态叫做 1,没电叫做 0 relay(default on): - c 没电,则电路接通,输出 1 - c 有电,则电路断开,输出 0 relay(default off): - c 没电,则电路断开,输出 0 - c 有电,则电路接通,输出 1 实践时间,不提供解法。跟着 nandgame 一路把第一部份所有逻辑门写完。 到这里对数字电路应该有了初步的认识,但这个课程后面还有很多东西,有条件的话我们后面再分享: - [ALU(算术逻辑单元)](https://zh.wikipedia.org/zh-hk/%E7%AE%97%E8%A1%93%E9%82%8F%E8%BC%AF%E5%96%AE%E5%85%83) ![](https://img2023.cnblogs.com/blog/3224918/202309/3224918-20230907122604568-1841018314.jpg) - 如何实现存储(bit, byte, 寄存器,内存) - 机器语言与汇编语言,汇编器 - 高级编程语言,编译器 - 操作系统 - 应用程序 ## 苹果的 Rosetta 是怎么把 x86 的程序运行在 arm 上的 https://support.apple.com/zh-tw/HT211861 > Rosetta 2 可讓配備 Apple 晶片的 Mac 使用專為配備 Intel 處理器的 Mac 所開發的 App。 比如我们制作了一个 CPU,它支持一系列指令(只是举例哈): - 写入寄存器a - 读取寄存器a - 写入寄存器b - 读取寄存器b - 将第一个、第二个数相加,结果写入寄存器a 指令集就是规定了这样一系列指令,如果某个 CPU 实现了这些指令,就可以说它支持某个指令集。 然后我们写了一段代码`1x3+2=?`,并以这个 CPU 为目标,编译出来的二进制形如: - 将 1 写入寄存器a - 将 1 写入寄存器b - 相加 - 将 1 写入寄存器b - 相加 - 将 2 写入寄存器b - 相加 - 读取寄存器a 这个二进制在我们的 CPU 上执行完,寄存器a中的数字就是代码的执行结果。但是如果我们拿为另一个 CPU 编译的二进制,在我们的 CPU 上执行: - 将 1 写入寄存器a - 将 3 写入寄存器b - **相乘** <<<< - 将 3 写入寄存器b - 相加 - 读取寄存器a 执行就会失败,原因是我们的 CPU 并不支持 **相乘** 这个指令。简单来说,X86 和 ARM 就是这样两个互不相容的指令集,所以为 X86 编译的二进制不能运行在 ARM 上。 那 Rosseta 是怎么做到的呢?还是以上面的相乘操作举例,我们可以把 `1x3` 改成 `1+1+1`,将不支持的 `x` 改成 `+` 来实现,这样就能在我们的 CPU 中运行为其他 CPU 编译的二进制了。 ## Steam Deck 是怎么把 Windows 的游戏运行在 Linux 上的 Steam Deck 的 CPU 是 X86 的,Windows 上的游戏(大多)也是为 X86 编译的。既然它们的 CPU 都是相同的指令集,为什么二进制不能共用呢? 因为 Steam Deck 运行的 Steam OS 是 Linux 的,所以问题其实是,应用程序为什么不能跑在不同的操作系统上。 这里牵扯到两个概念: - 可执行文件格式,比如 - Linux 中的 [ELF](https://en.wikipedia.org/wiki/Executable_and_Linkable_Format) - Windows 中的 [PE](https://en.wikipedia.org/wiki/Portable_Executable) - [操作系统 API](https://en.wikipedia.org/wiki/Category:Operating_system_APIs),比如 - [POSIX](https://en.wikipedia.org/wiki/Category:POSIX) - [Windows APIs](https://en.wikipedia.org/wiki/Category:Windows_APIs) - Java 虚拟机提供给字节码的 API 也算是一种 System API 首先可执行文件格式是啥?exe?但 exe 在 linux 中是运行不了的。 举个可能不太恰当的例子,我们编写了一个图片查看器,支持 jpg 格式。这时如果要求它打开一个 png 图片,它就会说“未知文件格式,无法打开”。 是我们的屏幕无法显示 png 中保存的图片么?不是的,是我们的图片查看器不知道如何提取出 png 中的图片信息,它不认识 png 这种图片格式。 在这个例子中: - 图片查看器 -> Window - jpg -> exe(PE) - png -> ELF Window 认识 exe(PE) 这种可执行文件格式,可以解读并且让 CPU 执行其中的指令。 但不认识 ELF 这种可执行文件格式,所以无法解读出其中的指令。所以不是 CPU 不能执行指令,而是操作系统不知道怎么提取出指令,进而交给 CPU 执行。 PE 可执行文件格式: ![](https://img2023.cnblogs.com/blog/3224918/202309/3224918-20230907122605326-1620604517.jpg) 所以 wine 是怎么在 linux 中执行 exe 的呢?既然操作系统不认识 exe,wine 自己去解析就行了嘛。然后把解析出的结果交给 linux 去执行就可以了。 但实际上还是不行,原因是不同的操作系统提供的“操作系统 API”不一样。比如 [Windows API](https://en.wikipedia.org/wiki/Windows_API) 中包含 GUI 相关的 API,创建窗口之类的,但 POSIX 中没有。 假设有这样一个 OS A,他的窗口必须“有,且只有一个标题”,当二进制想要创建一个自己的窗口,可以调用这个 OS 提供的一个 API: ``` // 创建一个标题为 Hello world 的窗口 create_window("Hello world") ``` 但还有另一个 OS B,它规定窗口必须有主标题和副标题,它提供的创建窗口 API 可能就是这样: ``` // 创建一个标题为 Hello World,副标题为 subtitle 的窗口 create_window("Hello world", "subtitle") ``` 如果我们尝试在 OS B 上执行为 OS A 编写的应用程序,当调用到 `create_window` 这个操作系统 API 时,就会出错,因为少传了副标题。 所以 wine 还得为 window 的应用程序提供兼容的操作系统 API,当应用程序调用到某个 Windows API 的时候,转为帮它调用对应的 linux 下的 API。 这样一来,对应用程序来说就像是在 Windows 中运行一样。 注意:文中的例子都是超级简化版本,只为了方便理解不保证正确全面,不要当真
posted @ 2023-09-07 12:26  印度海鲜拉面  阅读(50)  评论(0)    收藏  举报