计算机指令
计算机指令
“计算机指令”到底是什么、结构是怎样的、常见指令有哪些、各种架构的异同等。
一、什么是计算机指令?
一条指令就是告诉 CPU 执行“一步操作”的命令。
这些操作可能包括:
| 指令作用分类 | 举例 |
|---|---|
| 算术运算 | add, sub, mul, div |
| 逻辑运算 | and, or, xor, not |
| 数据传输 | load, store, mov |
| 跳转控制 | jmp, call, ret, beq |
| 系统调用 | syscall, int(中断) |
这些指令是用机器码(01串)或汇编语言写的,最终是给 CPU 解码执行的。
二、CPU 执行指令的流程
一个 CPU 的基本执行流程叫做 “取-译-执行”(Fetch-Decode-Execute):
- 取指(Fetch):从内存中读取一条指令;
- 译码(Decode):识别这条指令的意思;
- 执行(Execute):执行这个动作,如加法、写寄存器、跳转等;
- 写回(Write-back):将结果保存回寄存器或内存。
每条指令就是 CPU 的一块“积木”,拼成一个完整程序。
三、一条指令的结构是什么样?
通常包含几个部分(按字节排列):
| 字段 | 功能 |
|---|---|
| 操作码(Opcode) | 表示是加法、跳转还是其他操作 |
| 寄存器编号 | 指出哪两个寄存器参与操作 |
| 立即数 / 偏移量 | 某些操作需要一个常数,或偏移地址等信息 |
| 补充字段 | 某些架构可能有 SIB 字节、ModR/M 等特殊字段(如 x86) |
例子:MIPS 架构中一条加法指令
add $t0, $t1, $t2
意思是 $t0 = $t1 + $t2
机器码表示:
| 字段 | 位数 |
|---|---|
| opcode 操作码(加法是 000000) | 6 |
rs($t1)源寄存器 $t1 的编号 |
5 |
rt($t2)源寄存器 $t2 的编号 |
5 |
rd($t0)结果写入的 $t0 编号寄存器 |
5 |
| shamt 移位量(对加法来说为0) | 5 |
| funct(ADD) | 6 |
总共 32位(即4字节),这是一条“定长指令”。
四、RISC 与 CISC 指令集设计的不同
| 架构 | 类型 | 特点 |
|---|---|---|
| ARM | RISC | 简洁、固定长度、寄存器操作为主,适合嵌入式 |
| MIPS | RISC | 教学用典范,结构清晰,每条指令一件事 |
| x86 | CISC | 指令复杂,支持很多组合、操作可直接访问内存,变长指令 |
五、常见指令分类和示例
| 类型 | 指令示例 | 说明 |
|---|---|---|
| 算术 | add r1, r2, r3 |
r1 = r2 + r3 |
| 逻辑 | and r1, r2, r3 |
r1 = r2 AND r3 |
| 比较 | cmp r1, r2 |
比较两个寄存器的值 |
| 赋值 | mov r1, r2 |
把 r2 的值赋给 r1 |
| 加载/存储 | ldr r1, [r2] / str |
从内存读取/写入数据 |
| 跳转 | jmp label, beq label |
跳到其他地方执行指令(控制流) |
| 系统 | syscall, int 0x80 |
操作系统调用 |
六、不同架构的指令示例对比(加法)
| 架构 | 汇编指令 | 含义 |
|---|---|---|
| x86 | add eax, ebx |
eax = eax + ebx |
| MIPS | add $t0, $t1, $t2 |
$t0 = $t1 + $t2 |
| ARM | ADD R0, R1, R2 |
R0 = R1 + R2 |
偏移量和跳转
1. 偏移量是一种“描述位置”的方式
偏移量的本质是:
“我不告诉你具体去哪,而是告诉你从当前位置出发,往前或往后走多少”。
2. 跳转为什么常常用偏移量?
在汇编语言中,跳转(分支)指令需要告诉 CPU —— “下一条该执行哪条指令?”
有两种方式可以告诉 CPU:
类型 例子 描述 绝对地址跳转 j 0x00401020直接跳到具体地址 相对偏移跳转 beq $t0, $t1, +4从当前 PC 加上偏移跳过去 ✅ 大多数“条件跳转(branch)”都采用偏移量,因为它:
- 编码小巧(只需要表示“跳几条指令”)
- 可移植(无论程序搬到哪里,偏移相对不变)
- 支持前跳/后跳(例如循环、if 判断)
3. 所以是否“涉及跳转”就一定有偏移?
不是“所有跳转一定用偏移”,但:
指令类型 是否使用偏移 原因 条件跳转(如 beq)✅ 一般使用偏移 因为它描述“从当前 PC 向前/向后跳几条” 绝对跳转(如 j)❌ 使用的是地址 通常是固定地址跳转,不一定使用偏移 函数跳转(如 jal)✅ 或 ❌ 有些用偏移,有些用地址,取决于目标是否固定 跳寄存器(如 jr $ra)❌ 跳到寄存器保存的地址,和偏移无关
This post is licensed under
CC BY 4.0
by the author.