当年学写程序的时古老的物理设备,“打孔卡(Punched Card)”。在纸带或者卡片上打洞,变成一条条纸带或卡片,再交给当时的计算机去处理。
在特定的位置上打洞或者不打洞,来代表“0”或者“1”。
为什么不能用 C 或者 Python 高级语言来写呢?CPU没有能力理解。即使今天计算机,仍只能处理“机器码”(一连串的“0”和“1”)。
高级语言怎么变成“0”和“1”的?一串串“0”和“1”又是怎么在 CPU 中处理的?“机器码”和“计算机指令”到底是怎么回事。
一、在软硬件接口中,CPU帮我们做了什么事?
CPU 就是计算机的大脑。CPU 的全称是 Central Processing Unit,中文是中央处理器。
硬件角度:CPU 就是超大规模集成电路,通过电路实现了加法、乘法乃至各种各样的处理逻辑。
软件角度,CPU执行各种计算机指令(InstructionCode)的逻辑机器。这里指令好比机器语言
不同 CPU 能听懂语言不一样。个人电脑用是 Intel 的 CPU,苹果手机是 ARM 的 CPU。两组不同的计算机指令集,英文叫 Instruction Set(集合)。
计算机程序成千上万条指令组成的,存储在存储器中,这种计算机叫作存储程序型计算机(Stored-programComputer)。
没有现代计算机之前,发明了一种叫 Plugboard Computer “插线板计算机”。布满了各种插口和插座的板子上,不同的电线来连接不同的插口和插座,完成各种计算任务。 IBM 的 Plugboard:
二、从编译到汇编,代码怎么变成机器码?
代码怎么变成指令,被 CPU 执行的呢? C 语言程序:
让这段程序在Linux上跑起来,需翻译成汇编语言(ASM,Assembly Language)的程序,这个过程叫编译(Compile)成汇编代码。
汇编器(Assembler)翻译汇编代码成机器码(Machine Code)。由“0”和“1”组成机器码(一串串的 16 进制数字)是计算机指令。Linux:
汇编代码:$ gcc -g -c test.c
机器码:$ objdump -d -M intel -S test.o
左侧数字,就是机器码;右 push、mov、add、pop 汇编代码。一行 C 语言代码,对应一条或两条机器码和汇编代码。
用 GCC(GUC 编译器套装,GUI Compiler Collectipon)编译器时,直接把代码编译成机器码呀,为什么要汇编代码呢?机器码摸不着头脑,汇编代码多少也能“猜”出含义。 add、mov 容易记, 不像8b 45 f8 指令
三、解析指令和机器码
日常 Intel CPU,有 2000 条左右的 CPU 指令,分成五大类。
(1)算术类指令。加减乘除
(2)数据传输类指令。给变量赋值、内存里读写数据
(3)逻辑类指令。与或非
(4)条件分支类指令。“if/else”
(5)无条件跳转指令。调用函数时
汇编器怎么把汇编代码,翻译成为机器码:
MIPS 指令是32 位的整数,高 6 位叫操作码(Opcode),代表具体是什么样的指令,剩下 26 位有三种格式,分别是 R、I 和 J。
R 指令:算术和逻辑操作,有读和写寄存器地址。位移操作有位移操作的位移量,操作码不够时,功能码扩展操作码表示对应的具体指令的。
I 指令,数据传输、条件分支,运算时候用并非变量还是常数的时候。没有位移量、操作码、第三个寄存器,把这三部分合并成了一个地址值或者一个常数。
J 指令:高 6 位之外的 26 位都是跳转后地址。
加法算术指令 add t0,t0,t0, s1, $s2, 例,用十进制表示代码。
MIPS 指令里 opcode 是 0,rs 代表第一个寄存器 s1 的地址是 17,rt 代表第二个寄存器 s2 的地址是 18,rd 代表目标的临时寄存器 t0 的地址,是 8。不是位移操作,位移量是 0。这些数字拼一起,变成了MIPS 加法指令。
二进制数,用 16 进制表示。 0X02324020。数字是指令对应机器码。
1000 1100 1001 0000 0000 1000 00
打孔代表 1,没有打孔代表 0,用 4 行 8 列代表一条指令来打一个穿孔纸带,这条命令长这样:
总结延伸
打孔卡,就是存储程序型计算机。
机器码,程序员“编译”成卡片的。程序存储成打孔卡片。程序运行的逻辑处理一串“0”和“1”组成的机器码。
解释型语言,通过解释器在程序运行时候逐句翻译, Java 这样使用虚拟机的语言,虚拟机对编译出来的中间代码进行解释,即时编译成为机器码来最终执行。
推荐阅读
日常使用 Intel CPU 的指令集有所了解,《计算机组成与设计:软 / 硬件接口》第 5 版的 2.17 小节。
课后思考
把一个数字在命令行里面打印出来,背后对应的机器码是什么?通过 GCC 把这个的汇编代码和机器码打出来。