[计算机科学#8]:指令与程序的奥秘
【核知坊】:释放青春想象,码动全新视野。
我们希望使用精简的信息传达知识的骨架,启发创造者开启创造之路!!!
内容摘要:本文简要探讨了软件与硬件之间的联系,并重点介绍了英特尔公司开发的 4004 微处理器。在计算机底层,常见的指令操作均以二进制序列的形式呈现,这些操作通过物理逻辑电路得以实现,完成不同的“原子操作”。我们的程序正是由这些“原子操作”组合而成。由于程序具有高度的灵活性,计算机因此具备了多种多样的数据处理方式。
关键词:指令 程序 英特尔4004
其他相关文章:
[计算机科学#7]:CPU的三阶段,取指令、解码、执行-CSDN博客
[计算机科学#6]:从锁存器到内存,计算机存储的构建与原理-CSDN博客
[计算机科学#5]:计算机的“数学大脑”——核心部件ALU揭秘-CSDN博客
硬件与软件
硬件(Hardware)
硬件是指计算机系统中所有可见、可触摸的物理组件和设备。这些组件构成了计算机的物理基础,是计算机能够运行和执行任务的物质载体。例如,我们之前学过的 CPU 就属于硬件。CPU 在物理上是由精密的逻辑电路组成的,CPU 的内部逻辑电路由复杂的晶体管、逻辑门和其他微电子元件组成。
CPU 的功能上限是由其内部逻辑电路的设计和规模决定的。每条 CPU 指令实际上都映射在特定的逻辑电路上,这些电路的规模和结构决定了指令的复杂性和功能范围。使用CPU就需要考虑如何挑选或组合指令,灵活的实现不同的复杂功能。
CPU 主要材料是硅,硅的电子物理特性使其能够高效地传导和控制电流,因此被广泛用于各种电子元器件的生产与制造。这种特性使得硅成为现代电子设备中不可或缺的材料,尤其是在 CPU、内存和其他微芯片的制造中。
软件(Software)
软件是计算机系统中所有不可见的、以数字形式存储和运行的程序、数据和文档。它是计算机系统的“灵魂”,通过一系列指令告诉硬件如何执行任务。软件的编写和运行过程可以类比为一份详细的“代办事项清单”,它必须严格遵循一定的格式和规则,以确保硬件能够正确理解和执行。 软件的编写需要遵循严格的格式和规则,这些规则类似于文字的颜色、大小和数量等格式要求。例如,编程语言有固定的语法和语义规则,开发者必须按照这些规则编写代码。通过编写符合规则的软件,并使用编译器将它们转换为机器可识别的二进制码,软件能够有效地指导硬件执行复杂的任务。最终,这些二进制代码通过物理存储单元的高低电平或其他物理特性被存储和执行,从而实现软件的功能。
指令与程序
指令的定义
指令是计算机硬件能够识别和执行的最基本操作命令。指令是计算机硬件能够直接执行的最小单位,每条指令对应一个具体的“原子操作”。每条指令都由两部分组成:
-
操作码(Opcode):告诉计算机要执行什么操作(如加法、减法、跳转等)。
-
操作数(Operand):操作的对象,可以是数据、内存地址或寄存器等。
程序的定义
程序是由一系列指令组成的序列,用于完成特定的任务。程序是人类为了实现某种功能而编写的代码,它通过指令告诉计算机如何执行操作。
指令与程序的关系
-
程序由指令构成:程序本质上是一系列指令的集合。程序员通过编写代码(如C语言、Python等),将高级语言转换为计算机能够理解的指令序列(通过编译器或解释器)。
-
指令是程序的执行基础:计算机硬件只能直接执行指令。程序运行时,计算机逐条读取指令并执行它们,从而完成程序的功能。
-
程序的灵活性源于指令的组合:虽然每条指令的功能相对简单,但通过组合不同的指令,可以实现复杂的逻辑和功能。程序的灵活性和强大功能正是基于指令的多样性和组合方式。
英特尔 4004 微处理器
英特尔 4004 是英特尔公司于 1971 年发布的世界上第一个商用微处理器芯片,标志着计算技术的重大突破。作为 4 位 CPU,4004 是大规模集成技术的早期成果,首次展示了 MOS 硅栅技术(SGT)的优势,实现了更高的晶体管密度和更快的运行速度。
4004 的开发始于 1969 年,最初是为 Busicom 公司设计的电子计算器芯片组。英特尔工程师 Marcian Hoff 提出了基于 RAM 存储数据的单芯片 CPU 架构,Federico Faggin 领导的设计团队于 1970 年开始工作,并于 1971 年 3 月交付了第一个运行的 4004 芯片。Faggin 在设计中应用了自对准栅极技术和“自举负载”,显著提高了电路密度和性能。4004 的成功为后续英特尔处理器奠定了基础,包括 1974 年的改进型 4040 以及 8 位的 8008 和 8080 处理器。
英特尔 4004 的46个指令集
在计算机底层,所有指令(包括操作码和操作数)都以唯一的二进制序列表示,而计算机硬件通过高低电平或电流的有无来识别这些二进制信号。然而,对于人类来说,直接阅读和理解这些二进制代码非常困难。为了方便编程,人们为每个操作码赋予了一个易于理解的名称,这种名称被称为助记符。
代码 | 助记符 | 操作码 (OPR) | 操作数 (OPA) | 操作描述 |
---|---|---|---|---|
0 | NOP | 0000 | 0000 | 无操作。 |
1 | JCN | 0001 A₂,A₂,A₂,A₂ | C1, C2, C3, C4, A₁, A₁, A₁, A₁ | 如果条件C1, C2, C3, C4为真,则跳转到ROM地址A₂,A₂,A₂,A₂,A₁, A₁, A₁, A₁,否则顺序执行下一条指令。 |
2 | FIM | 0010D₂,D₂,D₂,D₂ | RRR0, D₁,D₁,D₁,D₁ | 从ROM直接取立即数D₂,D₂,D₂,D₂,D₁,D₁,D₁,D₁到索引寄存器对RRR。 |
3 | FIN | 0011 | RRR0 | 从ROM间接获取。将索引寄存器对位置0的内容作为地址发送出去。获取的数据放入寄存器对位置RRR。 |
3 | JIN | 0011 | RRR1 | 间接跳转。将寄存器对RRR的内容作为地址发送出去在A和A₂ 指令周期中的时间。 |
4 | JUN | 0100A₂,A₂,A₂,A₂ | A3,A3,A3,A3,A₁, A₁, A₁, A₁ | 无条件跳转到ROM地址A3,A3,A3,A3,A₂,A₂,A₂,A₂,A₁,A₁,A₁,A₁ |
5 | JMS | 0101A₂,A₂,A₂,A₂ | A3,A3,A3,A3,A₁, A₁, A₁, A₁ | 跳转到子程序ROM地址A3,A3,A3,A3,A₂,A₂,A₂,A₂,A₁,A₁,A₁,A₁,并将旧地址压入堆栈(堆栈级别+1)。 |
6 | INC | 0110 | RRRR | 增加寄存器RRRR的内容。 |
7 | ISZ | 0111A₂,A₂,A₂,A₂ | RRRR,A₁, A₁, A₁, A₁ | 寄存器RRRR的增量内容。转到ROM地址A₂,A₂,A₂,A₂,A₁, A₁, A₁, A₁(在包含此ISZ指令的同一ROM中)如果结果≠0,否则按顺序转到下一条指令。 |
8 | ADD | 1000 | RRRR | 将寄存器RRRR的内容与累加器内容相加(带进位)。 |
9 | SUB | 1001 | RRRR | 将寄存器RRRR的内容从累加器中减去(带借位)。 |
A | LD | 1010 | RRRR | 将寄存器RRRR的内容加载到累加器中。 |
B | XCH | 1011 | RRRR | 交换索引寄存器RRRR和累加器的内容。 |
C | LDM | 1101 | DDDD | 将数据DDDD加载到累加器中。 |
D | BBL | 1100 | DDDD | 从堆栈返回(堆栈级别-1),并将数据DDDD加载到累加器中。 |
F0 | CLB | 1111 0000 | - | 清除累加器和进位标志。 |
F1 | CLC | 1111 0001 | - | 清除进位标志。 |
F2 | IAC | 1111 0010 | - | 累加器加1。 |
F3 | CMC | 1111 0011 | - | 取反进位标志。 |
F4 | CMA | 1111 0100 | - | 取反累加器内容。 |
F5 | RAL | 1111 0101 | - | 累加器和进位标志左移。 |
F6 | RAR | 1111 0110 | - | 累加器和进位标志右移。 |
F7 | TCC | 1111 0111 | - | 将进位标志传送到累加器,并清除进位标志。 |
F8 | DAC | 1111 1000 | - | 累加器减1。 |
F9 | TCS | 1111 1001 | - | 传输进位减法并清除进位标志。 |
FA | STC | 1111 1010 | - | 设置进位标志。 |
FB | DAA | 1111 1011 | - | 十进制调整累加器。 |
FC | KBP | 1111 1100 | - | 键盘处理。将累加器内容从一出四码转换为二进制码。 |
FD | DCL | 1111 1101 | - | 指定命令行。 |
代码 | 助记符 | 操作码 (OPR) | 操作数 (OPA) | 操作描述 |
---|---|---|---|---|
2- | SRC | 0010 | RRR1 | 发送寄存器控制。将索引寄存器对RRR的内容作为地址发送到ROM和RAM。 |
E0 | WRM | 1110 0000 | - | 将累加器的内容写入之前选择的RAM主存储器字符中。 |
E1 | WMP | 1110 0001 | - | 将累加器的内容写入之前选择的RAM输出端口(输出线)。 |
E2 | WRR | 1110 0010 | - | 将累加器的内容写入之前选择的ROM输出端口(1/0线)。 |
E3 | WPM | 1110 0011 | - | 将累加器的内容写入之前选择的读/写程序存储器的半字节中(仅用于4008/4009或4289)。 |
E4 | WRO | 1110 0100 | - | 将累加器的内容写入之前选择的RAM状态字符0。 |
E5 | WR1 | 1110 0101 | - | 将累加器的内容写入之前选择的RAM状态字符1。 |
E6 | WR2 | 1110 0110 | - | 将累加器的内容写入之前选择的RAM状态字符2。 |
E7 | WR3 | 1110 0111 | - | 将累加器的内容写入之前选择的RAM状态字符3。 |
E8 | SBM | 1110 1000 | - | 从累加器中减去之前选择的RAM主存储器字符(带借位)。 |
E9 | RDM | 1110 1001 | - | 将之前选择的RAM主存储器字符读入累加器。 |
EA | RDR | 1110 1010 | - | 将之前选择的ROM输入端口的内容读入累加器(1/0线)。 |
EB | ADM | 1110 1011 | - | 将之前选择的RAM主存储器字符与累加器内容相加(带进位)。 |
EC | RDO | 1110 1100 | - | 将之前选择的RAM状态字符0读入累加器。 |
ED | RD1 | 1110 1101 | - | 将之前选择的RAM状态字符1读入累加器。 |
EE | RD2 | 1110 1110 | - | 将先前选择的RAM状态字符2读入读入累加器。 |
EF | RD3 | 1 110 1111 | 将先前选择的RAM状态字符3读入读入累加器。 |
停止指令
指令示例
HALT
指令的机器码是 0xF4
。
运行原理
-
当 CPU 执行
HALT
指令时,它会停止当前的指令执行,进入一种低功耗的“暂停”状态。 -
CPU 会等待下一个外部中断信号(如时钟中断、硬件中断等)来唤醒它。
-
在多核处理器中,
HALT
指令通常用于让某个核心进入空闲状态,以节省电力。
条件指令
条件指令用于根据某些条件(如比较结果)决定是否执行后续指令。这些指令通常依赖于处理器的状态寄存器。
指令示例
-
CMP AX, BX
:比较寄存器 AX 和 BX 的值。 -
JZ label
:如果零标志(ZF)为 1(即 AX == BX),则跳转到标签label
。 -
JNZ label
:如果零标志(ZF)为 0(即 AX != BX),则跳转到标签label
。
运行原理
-
CMP
指令会更新处理器的状态寄存器(如零标志 ZF、符号标志 SF 等)。 -
条件跳转指令(如
JZ
、JNZ
)会检查状态寄存器的特定标志位,根据标志位的值决定是否跳转到指定的地址。
循环指令
循环指令用于重复执行一段代码,直到满足某个条件为止。
指令示例
-
MOV CX, 10
:将循环次数设置为 10。 -
LOOP_START:
-
...
(循环体代码) -
LOOP LOOP_START
:每次循环后,CX
寄存器的值减 1,如果CX
不为 0,则跳转回LOOP_START
。
-
运行原理
-
LOOP
指令会自动将CX
寄存器的值减 1,并检查其值是否为 0。 -
如果
CX
不为 0,则跳转到指定的标签,继续执行循环体。
跳跃指令
跳跃指令用于改变程序的执行顺序,跳转到指定的地址。
指令示例
-
JMP label
:无条件跳转到标签label
。 -
JE label
:如果零标志(ZF)为 1,则跳转到标签label
。 -
JNE label
:如果零标志(ZF)为 0,则跳转到标签label
。
运行原理
-
JMP
指令会直接将程序计数器(PC)的值更新为目标地址,从而改变程序的执行顺序。 -
条件跳转指令(如
JE
、JNE
)会检查状态寄存器的标志位,根据标志位的值决定是否跳转。
文章总结
本文简要探讨了软件与硬件之间的联系,重点介绍了英特尔公司开发的4004微处理器。在计算机底层,指令操作以二进制序列的形式呈现,通过物理逻辑电路实现不同的“原子操作”。程序正是由这些“原子操作”组合而成,其高度的灵活性使得计算机能够以多种多样的方式处理数据。
感谢阅览,如果你喜欢该内容的话,可以点赞,收藏,转发。由于 Koro 能力有限,有任何问题请在评论区内提出,Koro 看到后第一时间回复您!!!
其他精彩内容:
[计算机科学#2]:从继电器到晶体管的电子计算机发展史(庞然大物的进化)-CSDN博客
[计算机科学#3]:布尔逻辑 (计算机数学基础)-CSDN博客
[计算机科学#4]:二进制如何塑造数字世界(0和1的力量)-CSDN博客
参考内容:
Crash Course Computer Science(Y-T)