欢迎来到机器的心脏!
你好!今天我们将深入探讨电脑的内部世界。你有没有想过,电脑究竟是如何理解像 x = 5 + 2 这样的程序代码呢?电脑并不使用 Python 或 Java;它们使用的是电信号的语言——二进制(Binary)(即 0 和 1)。
在本章中,我们将学习汇编语言(Assembly Language)。你可以把它想象成人类世界与电脑底层电信号之间的“桥梁”。它强大且快速,让你能够完全掌控处理器(Processor)。如果刚开始觉得它看起来有点“机器化”也不用担心——一旦你掌握了其中的规律,这就像是在解一个有趣的逻辑谜题!
1. 机器码与汇编语言
在编写任何程序之前,我们需要先了解“低阶(Low-level)”语言的两个层级:
机器码(Machine Code):这是处理器唯一能直接理解的东西,完全由二进制(例如 01101010)组成。对人类来说,要在不犯错的情况下阅读或编写机器码几乎是不可能的。
汇编语言(Assembly Language):为了让事情变得简单,我们使用助记符(Mnemonics)。助记符是一种简短、易于记忆的缩写,代表了特定的机器码指令。例如,与其输入一长串二进制代码来相加两个数字,我们只需写下 ADD。
重点复习:
• 机器码 = 1 和 0 的组合(给电脑看)。
• 汇编语言 = 像 ADD 或 LDR 这样的助记符(给人类看)。
• 汇编器(Assembler) = 将汇编语言转换为机器码的软件。
你知道吗?每一种不同类型的处理器(例如你手机里的处理器与笔记本电脑里的处理器)都有其专属的指令集(Instruction Set)。这意味着为某种处理器编写的汇编语言程序,可能无法在另一种处理器上执行!
2. 指令格式
每一条汇编语言指令通常分为两个主要部分。你可以把它想象成一个简单的句子:包含一个动词和一个名词。
操作码(Opcode,即动词)
操作码(Operation Code 的缩写)告诉处理器要做什么。常见的例子包括 ADD(相加)、SUB(相减)或 MOV(移动)。
操作数(Operand,即名词)
操作数告诉处理器对什么进行操作。它可以是一个固定的数字、一个内存地址,或是一个寄存器(Register,即 CPU 内超高速的小型存储空间)。
比喻:如果你正在按照食谱做菜,指令是“切洋葱”,那么操作码就是“切”,而操作数就是“洋葱”。
关键总结: 指令 = 操作码(动作)+ 操作数(数据或位置)。
3. 寻址模式:寻找数据
“寻址模式(Addressing Modes)”告诉 CPU 如何解读操作数。Oxford AQA 要求你掌握三种特定的类型。不用担心,我们用一个比喻来说明!
1. 立即寻址(Immediate Addressing):
操作数本身就是你要使用的实际数值。
例子: ADD #5(直接将数字 5 相加)。
比喻: 有人直接递给你 \( \$5 \) 现金。你手里立刻就有了这些钱!
2. 直接寻址(Direct Addressing):
操作数是一个内存地址。CPU 必须前往该地址才能找到数值。
例子: LDR R1, 101(前往内存位置 101,将其中的内容载入到寄存器 R1)。
比喻: 有人给你一个储物柜号码。你必须亲自去那个储物柜才能拿到钱。
3. 间接寻址(Indirect Addressing):
操作数是一个寄存器,该寄存器中存放的是数据的内存地址。
例子: 如果寄存器 R2 里存着数字“200”,而你使用间接寻址,CPU 会先前往位置 200,才能找到真正的数据。
比喻: 你拿到一张纸条,上面写着:“储物柜的钥匙在蓝色盒子里。”你得先去蓝色盒子找到钥匙,才能前往相应的位置拿到钱。
常见错误: 学生常混淆“直接寻址”与“立即寻址”。记住:立即寻址直接使用该数字(通常标有 # 号),而直接寻址则将数字视为一个“门牌号码”,用来寻找另一个数值。
4. OxfordAQA 汇编语言指令集
在考试中,你将会使用基于 ARM 处理器的特定指令集。以下是你必须掌握的最重要指令:
数据传输
• LDR (Load): 从内存中复制一个值到寄存器。
• STR (Store): 将一个值从寄存器复制到内存中。
• MOV (Move): 将一个值从一个地方复制到另一个地方(例如在两个寄存器之间)。
算术与逻辑
• ADD: 将两个值相加。
• SUB: 将两个值相减。
• AND, OR, NOT, XOR: 执行位运算。
• LSL (Logical Shift Left): 将位向左移(乘以 2)。
• LSR (Logical Shift Right): 将位向右移(除以 2)。
程序流程(分支)
通常,CPU 会按顺序一条接一条地执行指令。分支(Branching)允许程序“跳转”到代码的其他部分。
• CMP (Compare): 比较两个值(通常在跳转指令前使用)。
• B (Branch): 无条件跳转到特定标签。
• BEQ / BNE: 条件跳转(若相等则跳转 / 若不相等则跳转)。
• HALT: 停止程序执行。
5. 追踪与编写程序
当题目要求你“追踪(trace)”一个程序时,你的角色就像是一台电脑。你需要一步步执行指令,并记录寄存器与内存中的变化。
执行流程示例:
1. MOV R1, #10 (寄存器 R1 现在存有 10)。
2. MOV R2, #5 (寄存器 R2 现在存有 5)。
3. ADD R1, R1, R2 (将 R1 和 R2 相加,结果存回 R1。R1 现在是 15)。
4. STR R1, 100 (将数值 15 存储到内存位置 100)。
记忆小撇步: 大多数指令都遵循此格式:目的位置(Destination), 来源 1(Source 1), 来源 2(Source 2)。排在第一个的寄存器几乎总是存放“答案”的地方!
最终总结:重点复习
1. 汇编语言是人类可读的: 我们使用助记符(简短词汇)而不是二进制。
2. 指令结构: 每一条指令都有操作码(指令内容)和操作数(数据或位置)。
3. 寻址方式至关重要: 区分立即寻址(直接用数字)、直接寻址(用地址)和间接寻址(用存放地址的寄存器)。
4. 寄存器速度极快: 汇编语言的核心在于数据在寄存器与主内存(RAM)之间的移动。
5. 程序流程: 使用 CMP 和 Branch 指令在汇编语言中实现“if 判断”和“循环”。
如果刚开始觉得很难也不用担心!汇编语言是一种逻辑性极强的语言。一旦你习惯了手动将数据移入移出小盒子(寄存器)的概念,一切就会变得豁然开朗。继续练习简单的 ADD 和 MOV 指令吧!