408 计算机组成原理 知识点记忆(4)指令系统

408 计算机组成原理 知识点记忆(4)指令系统

前言

本文基于王道考研《计算机组成原理考研复习指导》与唐朔飞《计算机组成原理》(第2版)、袁春风《计算机组成与系统结构》教材内容,结合 408 考研大纲,系统梳理指令系统的核心知识记忆点和框架,既为个人复习沉淀思考,亦希望能与同行者互助共进。

本章是软硬件的交界面,回答"机器能听懂哪些话、操作数在哪里找",指令格式与寻址方式是理解汇编与机器级代码的基础。

核心知识记忆点+理解性说明

第四章 指令系统

1. 指令格式的基本概念

机器指令(简称指令)是指示计算机执行某种操作的命令。一台计算机的所有指令的集合构成该机的指令系统,也称指令集。指令系统是指令集体系结构(ISA)中最核心的部分,ISA完整定义了软件和硬件之间的接口,是机器语言或汇编语言程序员所应熟悉的。

ISA 规定的内容主要包括:

  1. 指令格式,指令寻址方式,操作类型,以及每种操作对应的操作数的相应规定。2)操作数的类型,操作数寻址方式,以及是按大端方式还是按小端方式存放。3)程序可访问的寄存器编号、个数和位数,存储空间的大小和编址方式。4)指令执行过程的控制方式等,包括程序计数器、条件码定义等。

2. 指令格式

操作码字段 地址码字段

指令长度等于机器字长:单字长指令半(双) 半(双)

定长指令字结构 所有指令长度均相等

从指令的角度来看,操作数存放位置可以是CPU中的通用寄存器、存储单元和I/O端口。

  1. 零地址指令

    只给出操作码OP,没有显式地址。这种指令有两种可能:

  2. 不需要操作数的指令,如空操作指令、停机指令、关中断指令等。

  3. 零地址的运算类指令仅用在堆栈计算机中。通常参与运算的两个操作数隐含地从栈顶和次栈顶弹出,送到运算器进行运算,运算结果再隐含地压入堆栈。

  4. 一地址指令

  5. 只有目的操作数的单操作数指令,按A1地址读取操作数,进行OP操作后,结果存回原地址。

    指令含义:OP(A1)→A1OP(A1) \to A1OP(A1)→A1

    如操作码含义是加1、减1、求反、求补、移位等。

  6. 隐含约定目的地址的双操作数指令,按指令地址A1可读取源操作数,指令可隐含约定另一个操作数由ACC(累加器)提供,运算结果也将存放在ACC中。

    指令含义:(ACC)OP(A1)→ACC(ACC)OP(A1) \to ACC(ACC)OP(A1)→ACC

二地址三地址四地址

拓展操作码指令格式 可变长度操作码

希望降低空间开销时,缩短代码长度更重要,应采用紧凑的变长操作码和变长指令字;希望降低时间开销以取得更好性能时,应采用定长操作码和定长指令字。

指令的操作类型

  1. 算术和逻辑运算指令

    算术和逻辑运算指令有加(add)、减(sub)、比较(cmp)、乘(mul)、除(div)、与(and)、或(or)、取反(not)、取负(neg)、异或(xor)、加1(inc)、减1(dec)等。

  2. 移位指令

    移位指令有算术移位、逻辑移位、循环移位、半字交换等。有的指令系统中,一条移位指令可以移动多位,此时通常用一个桶形移位器实现移位指令。

  3. 传送指令

    传送指令通常有寄存器之间的传送(mov)、从内存单元读取数据到通用寄存器(load)、从通用寄存器写数据到内存单元(store)等。

  4. 串指令

    串指令是对字符串进行操作的指令。如串传送、串比较、检索和传送转换等指令。

  5. 顺序控制指令

    顺序控制指令用来控制程序执行的顺序。有条件转移(branch)、无条件转移(jmp)、跳步(skip)、调用(call)、返回(ret)等指令。

  6. CPU控制指令

    CPU控制指令有停机、开中断、关中断、系统模式切换以及进入特殊处理程序等指令。大多数机器将这类指令划为"特权"指令(也称为管态指令),只能在内核代码执行时使用,以防止因用户使用不当而对系统运行造成危害。

  7. 输入输出指令

    输入输出指令用于完成CPU与外部设备交换数据或传送控制命令及状态信息。大多数机器都设置了这类指令,但是它们的寻址方式一般较少,常见的只有寄存器寻址、直接寻址和寄存器间接寻址等。当外设中的I/O地址空间和主存地址空间统一编址时,可以不设置这类指令,而用访存指令完成I/O操作。

指令系统设计风格:

  1. 累加型指令系统 2.栈型指令系统 Java虚拟机 3 通用寄存器型指令系统 4 Load/Strore型指令系统

:表示任意寄存器,若其后带有数字,则指定其位数,如表示32位寄存器(eax,ebx,ecx,edx,esi, edi, esp或ebp) ;< reg16>表示16位寄存器(ax,bx,cx或dx) ;< reg8>表示8位寄存器(ah,al,bh,bl,ch,cl,dh,dl)。

:表示内存地址(如eaxvar+4或 dword ptr eax+ebx)。

:表示8位、16位或32位常数。表示8位常数 ;< con16>表示16位常数;表示32位常数。

  1. 数据传送指令

  2. mov指令。将第二个操作数(寄存器的内容、内存中的内容或常数值)复制到第一个操作数(寄存器或内存)。

  3. push指令。将操作数压入内存的栈,常用于函数调用。ESP是栈顶,入栈前先将ESP值减4(栈增长方向与内存地址增长方向相反),然后将操作数压入ESP指示的地址。

  4. pop指令。与push指令相反,pop指令执行的是出栈工作,出栈前先将ESP指示的地址中的内容出栈,然后将ESP值加4。

  5. 算术和逻辑运算指令

  6. add/sub 指令。add指令将两个操作数相加,相加的结果保存到第一个操作数中。sub扑令用于两个操作数相减,相减的结果保存到第一个操作数中。

  7. inc/dec指令。inc、dec指令分别表示将操作数自加1、自减1。

  8. imul指令。有符号整数乘法指令,有两种格式:1两个操作数,将两个操作数相乘,将结果保存在第一个操作数中,第一个操作数必须为寄存器;2三个操作数,将第二个和第三个操作数相乘,将结果保存在第一个操作数中,第一个操作数必须为寄存器。

  9. idiv 指令。有符号整数除法指令,它只有一个操作数,即除数,而被除数则为edx:eax中的内容(共64位),操作结果有两部分:商和余数,商送到eax,余数则送到edx。

  10. and/or/xor指令。and、or、xor指令分别是逻辑与、逻辑或、逻辑异或操作指令,用于操作数的位操作,操作结果放在第一个操作数中。

  11. not指令。位翻转指令,将操作数中的每一位翻转,即 0→10 \to 10→1、1→01 \to 01→0。

  12. neg指令。取负指令。

  13. shl/shr 指令。逻辑移位指令,shl为逻辑左移,shr为逻辑右移,第一个操作数表示被操作数,第二个操作数指示移位的位数。

  14. 控制流指令

    维持着一个指示当前执行指令的指令指针(IP),当一条指令执行后,此指针自动指向下一条指令。IP寄存器不能直接操作,但可以用控制流指令更新。通常用标签(label)指示程序中的指令地址,在x86汇编代码中,可在任何指令前加入标签。

  15. jmp指令。jmp指令控制IP转移到label所指示的地址(从label中取出指令执行)。

  16. jcondition 指令。条件转移指令,依据CPU状态字中的一系列条件状态转移。CPU状态字中包括指示最后一个算术运算结果是否为0,运算结果是否为负数等。

  17. cmp/test指令。cmp指令的功能相当于sub指令,用于比较两个操作数的值。test指令的功能相当于and指令,对两个操作数进行逐位与运算。与sub和and指令不同的是,这两类指令都不保存操作结果,仅根据运算结果设置CPU状态字中的条件码。4)call/ret指令。分别用于实现子程序(过程、函数等)的调用及返回。call 指令将下一条指令的地址(返回地址)入栈,然后无条件转移到由标签指示的指令。与其他简单的跳转指令不同,call指令保存该指令的下一条指令的地址(当call指令结束后,返回保存的地址)。ret指令实现子程序的返回机制,ret指令弹出栈中保存的指令地址,然后无条件转移到保存的指令地址执行。call和ret是程序(函数)调用中最关键的两条指令。

有些机器的左移指令会生成OF标志。还有的机器在算术左移时将操作数的最高位移入进位标志,通过判断符号标志和进位标志是否相等来判断是否发生了溢出。

各种指令的数据通路图

过程调用的机器级表示

call/ret指令主要用于过程调用,它们都属于一种无条件转移指令。

假定过程P(调用者)调用过程Q(被调用者),过程调用的执行步骤如下:

  1. P将入口参数(实参)放到Q能访问到的地方。
  2. P将返回地址存到特定的地方,然后将控制转移到Q。
  3. Q保存P的现场(通用寄存器的内容),并为自己的非静态局部变量分配空间。
  4. 执行过程Q。
  5. Q恢复P的现场,将返回结果放到P能访问到的地方,并释放局部变量所占空间。
  6. Q取出返回地址,将控制转移到P。
    步骤2)是由call指令实现的,步骤6)通过ret指令返回到过程P。在上述步骤中,需要为入口参数、返回地址、过程P的现场、过程Q的局部变量、返回结果找到存放空间。
    用户可见寄存器数量有限,调用者和被调用者需共享寄存器,若直接覆盖对方的寄存器,则会导致程序出错。因此有如下规范:寄存器EAX、ECX和EDX是调用者保存寄存器,当P调用Q时,若Q需用到这些寄存器,则由P将这些寄存器的内容保存到栈中,并在返回后由P恢复它们的值。寄存器EBX、ESI、EDI是被调用者保存寄存器,当P调用Q时,Q必须先将这些寄存器的内容保存在栈中才能使用它们,并在返回P之前先恢复它们的值。
    每个过程都有自己的栈区,称为栈帧,因此,一个栈由若干栈帧组成,寄存器EBP指示栈帧的起始位置,寄存器ESP指示栈顶,栈从高地址向低地址增长。过程执行时,ESP会随着数据的入栈而动态变化,而EBP固定不变。当前栈帧的范围在EBP和ESP指向的区域之间。

下面用一个简单的C语言程序来说明过程调用的机器级实现。

int add(int x, int y) {

return x+y;

}

int caller () {

int templ=125;

int temp2=80;

int sum=add(templ,temp2);

return sum;

}

经GCC编译后,caller过程对应的代码如下:

caller:

push ebp

mov ebp, esp

sub esp, 24

mov ebp-12,125 #M R\[ebp-12]-125, E0 temp1=125mov ebp-8,80 #M R\[ebp-8]-80, EJ temp2=80mov eax, dword ptr ebp-8 #ReaxMR\[ebp-8], EpReax=temp2mov esp+4 , eax #MR\[esp+4]←Reax,即temp2 入栈mov eax, dword ptr ebp-12 #Reax <MR\[ebp -12], E| Reax=temp1mov esp,eax #MR\[esp]←Reax,即temp1入栈call add #调用add,将返回值保存在eax中

mov ebp-4, eax #MR\[ebp-4]←Reax,即add返回值送summov eax,dword ptr ebp-4 #Reax<MR\[ebp-4],即sum作为返回值leave

ret

假定caller被过程P调用。执行第4行的指令后,ESP所指的位置如图中所示,可以看出GCC为caller的参数分配了24字节的空间。从汇编代码中可以看出,caller 中只使用了调用者保存寄存器EAX,没有使用任何被调用者保存寄存器,因此在caller栈帧中无须保存除EBP外的任何寄存器的值;caller有三个局部变量temp1、temp2和sum,皆被分配在栈帧中;在用call指令调用add函数之前,caller先将入口参数从右向左依次将temp2和temp1的值(即80和125)保存到栈中。在执行call指令时再把返回地址压入栈中。此外,在最初进入caller时,还将EBP的值压入了栈,因此caller的栈帧中用到的空间占 4+12+8+4=284+12+8+4=284+12+8+4=28 字节。但是,caller的栈帧共有 4+24+4=324+24+4=324+24+4=32 字节,其中浪费了4字节的空间(未使用)。这是因为GCC为保证数据的严格对齐而规定每个函数的栈帧大小必须是16字节的倍数。

call指令执行后,add函数的返回参数存放在EAX中,因此call指令后面的两条指令中,指令"mov ebp-4,eax"将add的结果存入sum变量的存储空间,该变量的地址为Rebp-4;指令"mov eax,dword ptr ebp-4"将sum变量的值作为返回值送到寄存器EAX中。

在执行ret指令之前,应将当前栈帧释放,并恢复旧EBP的值,上述第14行leave指令实现了这个功能,leave指令功能相当于以下两条指令的功能:

mov esp, ebp

pop ebp

其中,第一条指令使ESP指向当前EBP的位置,第二条指令执行后,EBP恢复为P中的旧值,并使ESP指向返回地址。

执行完leave指令后,ret指令就可从ESP所指处取返回地址,以返回P执行。当然,编译器也可通过pop指令和对ESP的内容做加法来进行退栈操作,而不一定要使用leave指令。add 过程经GCC编译并进行链接后,对应的代码如下所示:

8048469:55 push ebp

804846a:89 e5 mov ebp, esp

804846c:8b 45 0c mov eax, dword ptr ebp+12

804846f:8b 55 08 mov edx, dword ptr ebp+8

8048472:8d 04 02 lea eax, edx+eax

8048475:5d pop ebp

8048476:c3 ret

通常,一个过程对应的机器级代码都有三个部分:准备阶段、过程体和结束阶段。

上述第1、2行的指令构成准备阶段的代码段,这是最简单的准备阶段代码段,它通过将当前栈指针ESP传送到EBP来完成将EBP指向当前栈帧底部的任务,如图4.12所示,EBP指向add栈帧底部,从而可以方便地通过EBP获取入口参数。这里add的入口参数x和y对应的值(125和80)分别在地址为Rebp+8、Rebp+12的存储单元中。

上述第3、4、5行的指令序列是过程体的代码段,过程体结束时将返回值放在EAX中。这里好像没有加法指令,实际上第5行lea指令执行的是加法运算Redx+Reax=x+y。

上述第6、7行的指令序列是结束阶段的代码段,通过将EBP弹出栈帧来恢复EBP在caller过程中的值,并在栈中退出add 过程的栈帧,使得执行到ret指令时栈顶中已经是返回地址。这里的返回地址应该是caller代码中第12行的指令"movebp-4,eax"的地址。add 过程中没有用到任何被调用者保存寄存器,没有局部变量,此外,add是一个被调用过程,并且不再调用其他过程,因此也没有入口参数和返回地址要保存,因此,在add的栈帧中除了需要保存EBP,无须保留其他任何信息。

3. 寻址方式

采用虚拟存储机制,有效地址就是虚拟地址不采用 主存物理地址

指令寻址 顺序寻址;跳跃寻址 绝对转移 直接给出目标地址 相对转移 相对于当前PC偏移数据寻址 操作码 寻址特征 形式地址A 操作数在存储器中的真实地址 有效地址EA

如果任何一个通用寄存器都可作为变址寄存器,则必须在指令中明确地给出一个通用寄存器的编号,并标明作为变址寄存器使用;若处理器中有一个专门的变址寄存器,则无须在指令中明确给出。

使用专用的基址寄存器被称为是隐式基址寻址,使用指定的通用寄存器作为基址寄存器被称为是显式基址寻址。

对于两次间接寻址,指令字中的A依然是形式地址,访问主存地址为A的存储单元,取出后发现存储字首位为"1"(多次间接寻址需要用存储字中的第一位作标志位,用来说明该存储字是否是有效地址),说明该存储字中的A1并不是有效地址,还需要继续寻址。随后访问主存地址为A1的存储单元,取出后发现存储字的首位为"0",说明该存储字中的地址是有效地址EA。

中断:典型的由I/O设备触发的与当前正在执行的指令无关的异步事件

异常:处理器执行一条指令时,由处理器在其内部检测到的,与正在执行的指令相关的同步事件

4. 数据的对齐和大/小端存放方式

关于对结构体的对齐,主要包括两个方面:

一是对结构体的整体进行对齐(要求结构体的最终大小必须是最大元素对齐大小的整数倍);二是对结构体数据成员的对齐(每个数据成员的起始地址必须是自身对齐大小的整数倍)。

5. CISC和RISC的基本概念

复杂指令系统计算机CISC X86 大多数微程序精简 RISC ARM,MIPS 硬布线为主组合逻辑 只有LOAD/STORE(取数/存数指令访存)

6. 高级语言程序与机器级代码之间的对应

编译器、汇编器与链接器的基本概念;选择结构语句的机器级表示循环结构语句的机器级表示;过程(函数)调用对应的机器级表示

总结(本章速记)

本章知识骨架:

    1. 指令格式的基本概念
    1. 指令格式
    1. 寻址方式
    1. 数据的对齐和大/小端存放方式
    1. CISC和RISC的基本概念
    1. 高级语言程序与机器级代码之间的对应
      编译器、汇编器与链接器的基本概念;选择结构语句的机器级表示循环结构语句的机器级表示;过程(函数)调用对应的机器级表示

关键速记清单:

  • ISA 规定的内容主要包括:
  • 操作码字段 地址码字段
  • 指令长度等于机器字长:单字长指令半(双) 半(双)
  • 定长指令字结构 所有指令长度均相等
  • 零地址指令
  • 只给出操作码OP,没有显式地址。这种指令有两种可能:
  • 不需要操作数的指令,如空操作指令、停机指令、关中断指令等。
  • 一地址指令
  • 指令含义:OP(A1)→A1OP(A1) \to A1OP(A1)→A1
  • 如操作码含义是加1、减1、求反、求补、移位等。
  • 指令含义:(ACC)OP(A1)→ACC(ACC)OP(A1) \to ACC(ACC)OP(A1)→ACC
  • 二地址三地址四地址
  • 拓展操作码指令格式 可变长度操作码
  • 指令的操作类型
  • 算术和逻辑运算指令
  • 移位指令
  • 传送指令
  • 顺序控制指令
  • CPU控制指令
  • 输入输出指令
  • 指令系统设计风格:
  • 数据传送指令
  • not指令。位翻转指令,将操作数中的每一位翻转,即 0→10 \to 10→1、1→01 \to 01→0。
  • neg指令。取负指令。
  • 控制流指令
  • 各种指令的数据通路图
  • 过程调用的机器级表示
  • call/ret指令主要用于过程调用,它们都属于一种无条件转移指令。
  • 假定过程P(调用者)调用过程Q(被调用者),过程调用的执行步骤如下:
  • P将入口参数(实参)放到Q能访问到的地方。
  • P将返回地址存到特定的地方,然后将控制转移到Q。
  • 执行过程Q。
  • Q取出返回地址,将控制转移到P。
  • 下面用一个简单的C语言程序来说明过程调用的机器级实现。
  • int add(int x, int y) {
  • return x+y;
  • int caller () {
  • int templ=125;
  • int temp2=80;
  • int sum=add(templ,temp2);
  • return sum;
  • 经GCC编译后,caller过程对应的代码如下:
  • caller:
  • push ebp
  • mov ebp, esp
  • sub esp, 24
  • mov esp, ebp
  • pop ebp
  • 8048469:55 push ebp
  • 804846a:89 e5 mov ebp, esp
  • 8048475:5d pop ebp
  • 8048476:c3 ret
  • 采用虚拟存储机制,有效地址就是虚拟地址不采用 主存物理地址
  • 中断:典型的由I/O设备触发的与当前正在执行的指令无关的异步事件
  • 关于对结构体的对齐,主要包括两个方面:

结语

指令系统是软件与硬件之间最古老的一份契约。CISC 与 RISC 的争论,本质是"把复杂度交给编译器还是交给硬件";寻址方式的丰富程度,直接决定了机器码的表达力与译码代价;而大/小端、边界对齐这些看似琐碎的细节,恰恰是理解内存布局、结构体大小与跨平台兼容的关键。学习本章最好的方法,是拿一段 C 代码反汇编出来逐行对照------当你能读懂一条 mov 背后的取数路径,指令系统才真正属于你。

参考资料

  1. 王道考研《计算机组成原理考研复习指导》
  2. 唐朔飞.计算机组成原理(第2版).
  3. 袁春风.计算机组成与系统结构.
相关推荐
Heorine1 小时前
408 计算机组成原理 知识点记忆(5)中央处理器
考研
2601_9499506319 小时前
考研英语资料太散?用小程序把真题、词汇和错题放到一起
人工智能·学习·考研·小程序·刷题·小程序推荐
搜词研究员3 天前
# 德立教育和达德教育哪个好?学历提升选哪家?
考研·职场和发展·学习方法·高考
博界IT精灵3 天前
浮点数的表示--IEEE 754浮点数标准
考研
唐维康3 天前
昆明理工891计算机考研真题:2022—2026五年完整收录整理
考研
aichitang20243 天前
快乐泛函每一天:希尔伯特空间中的最佳逼近与正交投影定理
人工智能·考研·算法·ai·面试·泛函分析
唐维康4 天前
昆工817信号与系统2026真题分值与复习建议
考研·昆明理工大学
唐维康4 天前
2026年昆工891考研真题应用题分值分布与重点题型解析
考研
IT毕设实战小研4 天前
基于安卓的考研资讯系统设计与实现
android·大数据·vue.js·爬虫·python·考研·课程设计