作者回复: l'hao同学你好,是二进制,16进制只是为了显示方便,毕竟一串0和1在显示上太没有效率了
作者回复: 梨子同学你好,你把把上一行的二进制,四位四位一读,每四位当成是一个16进制数,就会得到这个结果
作者回复: 顺序是根据用什么样的机器读取来的,我们这里假设就是从左往右一列一列读取的。
一列卡片代表一个数,白色代表没有打孔,黑色代表打孔。3换算成二进制就是 0011,也就是上面两个不打孔,下面两个打孔,4就换算成 0100,也就是第二个打孔,其他的不打孔
作者回复: json同学你好,第一台计算机ENIAC,如果你去计算机历史博物馆看一下真机就会明白,他的各种输入都是一些旋钮,可以认为是类似用机器码在编程,后来才有了汇编、C这样越来越高级的语言。
编程语言是自举的,并不需要第一个编译器就是用自己这个语言来写的。通常是先有了别的语言写好的编译器,然后再用自己来写自己语言的编译器。
更详细的关于鸡蛋问题,可以直接看Wikipedia上,讲了多种这个问题的解决方案
https://en.wikipedia.org/wiki/Bootstrapping_(compilers)
作者回复: 杨怀同学你好,其实有一步到位的,就是两个步骤都通过一个命令先后执行,顺序完成,gcc现在就可以一个命令直接变成可执行的binary。
只是为了方便debug,你可以认为通过机器语言我们也可以反推出汇编语言长什么样子。
作者回复: 👍,周曙光爱学习同学你好,这个理解和比喻很形象
作者回复: 一步同学你好,
不同指令集里,对应的汇编代码会对应这个指令集的机器码呀。
大家不要把“汇编语言”当成是像C一样的一门统一编程语言。
“汇编语言”其实可以理解成“机器码”的一种别名或者书写方式,不同的指令集和体系结构的机器会有不同的“机器码”
高级语言在转换成为机器码的时候,是通过编译器进行的,需要编译器指定编译成哪种汇编/机器码。
物理机自己执行的时候只有机器码,并不认识汇编代码。
编译器如果支持编译成不同的体系结构的汇编/机器码,就要维护很多不同的对应关系表,但是这个表并不会太大。以最复杂的Intel X86的指令集为例,也只有2000条不同的指令而已。
作者回复: Geek_guo同学你好,加法在电路层面怎么执行,我们会在加法器里面讲解。
我们的指令运行,怎么和ALU这样的算术逻辑单元串联起来,我们会在CPU里面讲解,尽请期待啊。
作者回复: 可以的,这个就是历史上的CISC和RISC的争论。
其实指令集都在不断更新微调。而体系结构最近RISC-V又火起来了。
因为纯粹靠提升频率硬件的方法已经没有什么空间了,所以其实又进入了优化指令集乃至整个体系结构的阶段了。
作者回复: Sharongo同学你好,
因为放不下啊,也放不起啊,而且这样怎么做到前面讲的“可编程”和“可存储”呢?
作者回复: 是啊,我们在讲解CPU的时候,你可以从电路的角度来理解指令是怎么在硬件层面执行的。
作者回复: 如果在这个映射关系里面,可以认为shell脚本是被bash解释器来运行的,调用对应的编译好的二进制可执行文件相当于bash解释器在做对应的“翻译”动作
作者回复: 给你力量同学你好,
1. 你的理解是对的。不过其实历史上汇编不只是为了让程序员可以更容易读代码,也是为了让程序员更容易写代码。毕竟无论是打孔带,旋钮还是其他的更“古老”的方式来编程都太没有效率了。
2. 是的,应该说是三大类opcode,每一类里面有很多不同的具体的opcode。
作者回复: 机器码的差异不在于操作系统(也就是不在于Linux/Windows)。而是在于体系结构(Intel X86/ARM/MIPS)。
不同平台的汇编语言也是不同的,所以同样的高级语言编译器在不同的平台上编译出来的代码也是不一样的。
作者回复: 发条橙子同学你好,也希望你过了一个愉快的五一啊。
CPU的“指令集”是一个抽象的概念,你可以认为实际是被变成了CPU的电路。
我们具体的一个个程序的指令,是存在内存里的,或者说,是程序用一个文件格式存在磁盘上,然后通过装载器加载到内存里面,再一条条加载到指令寄存器里面,然后执行的。
关于汇编语言,你可以这样认为,不过厂商一般会直接提供对应的汇编语言和汇编器,但是也的确有支持多种指令集的第三方汇编语言和汇编器。