指令集种类
本节主要了解 CISC 和 RISC 的概念,可能在选择题中考察。后面不同位数计算机指令的差异 以及 AT&T、Intel 指令集可能在大题中间接考察。
复杂和精简指令集
CISC(Complex Instruction Set Computer)和 RISC(Reduced Instruction Set Computer)是两种不同的计算机体系结构设计哲学,它们在指令集架构和执行方式上有显著的差异。
CISC
- 指令集复杂:CISC 指令集包含大量复杂的指令,其中一条指令可以执行多种操作,包括内存访问、算术运算、逻辑运算等。
- 指令不定长:CISC 支持多种长度的指令。
- 多寻址模式:CISC 指令通常支持多种寻址模式,允许直接访问内存,因此可以在一条指令中执行复杂的操作。
- 微程序控制:CISC 计算机通常使用微程序控制单元,指令解码和执行过程相对复杂。
- 复杂硬件:CISC 处理器通常包括大量的硬件单元,用于支持复杂的指令集,这使得 CISC 芯片相对较大。
CISC 的典型芯片就是 x86 系列,如 Intel 的 Core i 系列处理器和 AMD 的 Ryzen 系列处理器。
RISC
- 指令集精简:RISC 计算机的指令集更加精简,通常包含较少、更简单的指令。每条指令只执行一种操作。
- 指令定长:RISC 指令集中所有指令长度相同。
- 固定寻址模式:RISC 指令通常只支持一种或者很少种寻址模式,鼓励将数据加载到寄存器中后再执行操作。
- 硬布线控制:RISC 计算机使用硬布线控制单元,指令解码和执行过程较为简单。
- 精简硬件:RISC 处理器通常采用更精简的硬件,以提高性能和降低成本。
上图体现了 CISC 和 RISC 的差别:RISC 寄存器数量比 CISC 更多,CISC 的访存指令比 RISC 更加复杂(CSIC 单条指令完成的工作 RISC 需要多条指令才能完成)。
程序示例
这一节举个实际的例子说明一下 CISC 和 RISC 上的汇编代码区别。
for (i = 0; i < 24; i++)
for (j = 0; j < 24; j++)
...
a[i][j] = 10;
...
对于上述的循环代码段,编译器将其编译为如下的 intel x86 汇编代码(CISC) 和 arm mips 汇编代码(RISC):
for (i = 0; i < 24; i++)
1 00401072 C7 45 F8 00 00 00 00 mov dword ptr [ebp-8], 0 ; i = 0,初始化 i 变量
2 00401079 EB 09 jmp 00401084h ; 跳转到循环条件检查
3 0040107B 8B 55 F8 mov eax, [ebp-8] ; 读取 i 的值到 eax
... ... ...
7 00401088 7D 32 jge 004010BCh ; 若 i >= 24,跳出循环
for (j = 0; j < 64; j++)
8 0040108A C7 45 FC 00 00 00 00 mov dword ptr [ebp-4], 0 ; j = 0,初始化 j 变量
... ... ...
a[i][j] = 10;
... ... ...
19 004010AE C7 84 82 00 20 42 00 0A 00 00 00
mov dword ptr [ecx+edx*4+00422000h], 0Ah
; 存储 10 到 a[i][j],计算地址:
; ecx = i, edx = j
; a[i][j] = 10
20 ... ...
for (i = 0; i < 24; i++)
1 00401000 20020000 addi $v0, $zero, 0 # i = 0
2 00401004 08004004 j 0x00401010 # 跳转到循环条件检查
3 00401008 8C430008 lw $v1, 8($fp) # 读取 i
... ... ...
7 00401010 1C600018 bge $v1, 24, 0x00401040 # if (i >= 24) 跳出循环
for (j = 0; j < 64; j++)
8 00401014 20040000 addi $a0, $zero, 0 # j = 0
... ... ...
a[i][j] = 10;
17 00401028 00031880 sll $v1, $v1, 6 # i × 64
18 0040102C 00641820 add $v1, $v1, $a0 # i × 64 + j
19 00401030 00031880 sll $v1, $v1, 2 # (i × 64 + j) × 4
20 00401034 3C010042 lui $at, 0x0042 # 加载基地址高 16 位
21 00401038 34222000 ori $v0, $at, 0x2000 # 完整基地址 0x00422000
22 0040103C 00621020 add $v0, $v1, $v0 # 计算目标地址
23 00401040 2405000A li $a1, 10 # 10 存入 $a1
24 00401044 AC450000 sw $a1, 0($v0) # a[i][j] = 10
25 ... ...
CISC 和 RISC 的简要对比如下所示:
特性 | CISC | RISC |
---|---|---|
指令集 | 复杂,指令数量多 | 精简,指令数量少 |
指令长度 | 不定长 | 固定长度 |
寻址模式 | 多种寻址模式 | 较少寻址模式 |
控制方式 | 微程序控制 | 硬布线控制 |
硬件复杂度 | 复杂 | 精简 |
优点 | 功能强大,一条指令可完成复杂操作 | 性能高,功耗低 |
缺点 | 硬件复杂,指令执行效率相对较低 | 功能相对简单,复杂操作需要多条指令完成 |
不同位数 cpu 的指令
从 8086(16 位 intel 处理器)再到后来的 32 位以及 64 位的 CPU,差异主要体现在以下几个方面:
- 寄存器位数和命名不同:32 位寄存器有
E
前缀,64 位寄存器有R
前缀。 - 指令集不同:32 位处理器相比 16 位处理器有着更加复杂的指令集,64 位处理器的指令集也比 32 位更加复杂。
下表中给出了不同位数寄存器的对比,注意每个寄存器的开头都与一个单次相对应,在最初 8086 的设计中这是代表一种语义。
寄存器 | 16 位 | 32 位 | 64 位 | 类型 |
---|---|---|---|---|
Accumulator | AX | EAX | RAX | General |
Base | BX | EBX | RBX | General |
Counter | CX | ECX | RCX | General |
Data | DX | EDX | RDX | General |
Source Index | SI | ESI | RSI | Pointer |
Destination Index | DI | EDI | RDI | Pointer |
Base Pointer | BP | EBP | RBP | Pointer |
Stack Pointer | SP | ESP | RSP | Pointer |
Instruction Pointer | IP | EIP | RIP | Pointer |
Code Segment | CS | - | - | Segment |
Data Segment | DS | - | - | Segment |
AT&T 和 Intel 指令
在 x86 汇编指令集中,常有 AT&T 和 Intel 两种格式,两种格式有较大差异。在考试中主要考察的是 Intel 格式,但是 AT&T 也需稍作了解,在遇到指令时能辨认出即可。
Intel 格式
# 寄存器访问
mov eax,1
mov ebx,0ffh
# 内存访问
mov eax,[ebx]
mov eax,[ebx+3]
AT&T 格式
# 寄存器访问
movl $1,%eax
movl $0xff,%ebx
# 内存访问
movl (%ebx),%eax
movl 3(%ebx),%eax
两种指令格式的不同主要在于 Intel 格式的 目的操作数在左,源操作数在右,而 AT&T 格式 目的操作数在右,源操作数在左。
两种指令格式的具体表格如下表所示:
特性 | Intel 格式 | AT&T 格式 |
---|---|---|
操作数顺序 | 目的,源 | 源,目的 |
寄存器 | eax, ebx... | %eax, %ebx... |
常数 | 10, 0x20... | $10, $0x20... |
内存寻址 | [] | () |