导图社区 第四章 指令系统
这是一篇关于408考研,期末考试,计算机组成原理,指令系统思维导图,专为计算机专业学生、考研 / 软考备考者、计算机底层原理学习者打造,是系统梳理指令系统核心知识的高效学习工具。思维导图的结构化呈现方式,将指令格式、寻址方式、高级语言与机器级代码的对应关系、汇编指令格式、控制流语句的机器级表示、函数调用的机器级表示、CISC/RISC 对比七大核心模块拆解为层级清晰、逻辑连贯的分支框架,同时融入高频考点标注、代码示例与对比说明,帮助使用者快速构建指令系统的知识体系,精准攻克指令格式设计、寻址方式、汇编指令与机器级代码转换等重难点与高频考点。对于计算机专业学生与考研 / 软考备考者而言,这份思维导图模板可直接用于课堂笔记整理、期末复习、考点梳理,将指令格式、定长 / 变长操作码设计、相对 / 基址寻址实现、AT&T 与 Intel 汇编格式区别、选择 / 循环 / 函数调用的机器级表示、RISC 与 CISC 对比等零散知识点系统化,降低理解与记忆难度,提升备考效率;对于计算机底层原理学习者,模板清晰呈现了指令系统的核心概念、汇编与机器代码的映射逻辑,可用于入门学习、逆向工程 / 汇编语言学习的知识框架搭建,快速建立对计算机指令执行逻辑的整体认知。模板完整覆盖指令系统核心考点:从指令的基本格式与操作码设计,到数据寻址方式与指令寻址;从高级语言语句到机器级指令的转换,到汇编指令格式差异;从控制流语句(分支、循环)的机器级实现,到函数调用的栈帧结构与参数传递;再到 CISC 与 RISC 指令系统的特征对比,均以思维导图形式清晰呈现,层级分明,便于快速查阅、重点标记与按需编辑修改,适配备考笔记、课程复习提纲、学习课件等多种场景。
编辑于2026-05-07 15:59:21这是一篇关于408考研,期末考试,计算机组成原理,输入输出系统思维导图,专为计算机专业学生、考研(如 408 统考)/ 软考备考者、计算机硬件底层原理学习者打造,是系统梳理 I/O 系统核心知识的高效学习工具。思维导图的结构化呈现方式,将 I/O 系统的基本概念、I/O 接口、I/O 控制方式、中断处理流程四大核心模块拆解为层级清晰、逻辑连贯的分支框架,同时融入高频考点标注、原理示意图与对比表格,帮助使用者快速构建输入 / 输出系统的知识体系,精准攻克 I/O 控制方式对比、DMA 传输原理、中断处理流程、磁盘调度算法等重难点与高频考点。对于计算机专业学生与考研 / 软考备考者而言,这份思维导图模板可直接用于课堂笔记整理、期末复习、考点梳理,将 I/O 接口的软硬件构成、程序查询 / 中断 / DMA 控制方式的差异、中断响应与处理全过程、磁盘调度计算等零散知识点系统化,降低理解与记忆难度,提升备考效率;对于计算机底层原理学习者,模板清晰呈现了主机与外设数据交互的完整逻辑,可用于入门学习、硬件原理学习的知识框架搭建,快速建立对计算机输入输出系统的整体认知。模板完整覆盖输入 / 输出系统核心考点:从 I/O 系统的基本概念、接口的分类与工作原理,到程序查询、中断、DMA 三种核心 I/O 控制方式的对比;从中断响应与完整处理流程,到磁盘调度算法、DMA 传输原理等计算类高频考点,均以思维导图形式清晰呈现,层级分明,便于快速查阅、重点标记与按需编辑修改,适配备考笔记、课程复习提纲、学习课件等多种场景。该模板借助万兴脑图软件绘制,助力计算机学习者高效掌握输入 / 输出系统核心知识。
这是一篇关于408考研,期末考试,计算机组成原理,总线的思维导图,专为计算机专业学生、考研 / 软考备考者、计算机底层原理学习者打造,是系统梳理总线系统核心知识的高效学习工具。思维导图的结构化呈现方式,将总线概述、总线仲裁、总线操作和定时、总线标准四大核心模块拆解为层级清晰、逻辑连贯的分支框架,同时融入关键原理示意图、性能计算要点与对比说明,帮助使用者快速构建总线系统的知识体系,精准攻克总线分类、仲裁方式、传输定时与性能分析等重难点与高频考点。对于计算机专业学生与考研 / 软考备考者而言,这份思维导图模板可直接用于课堂笔记整理、期末复习、考点梳理,将总线的特性与分类、集中式 / 分布式仲裁方式、同步 / 异步传输定时、总线性能指标计算等零散知识点系统化,降低理解与记忆难度,提升备考效率;对于计算机底层原理学习者,模板清晰呈现了计算机系统中各部件通过总线进行数据传输的完整逻辑,可用于入门学习、硬件原理学习的知识框架搭建,快速建立对计算机系统互连机制的整体认知。模板完整覆盖总线系统核心考点:从总线的基本概念、分类与特性,到总线仲裁的集中式与分布式实现;从总线操作的同步 / 异步 / 半同步定时方式,到总线标准与性能指标计算,均以思维导图形式清晰呈现,层级分明,便于快速查阅、重点标记与按需编辑修改,适配备考笔记、课程复习提纲、学习课件等多种场景。
这是一篇关于408考研,期末考试,计算机组成原理,中央处理器的思维导图,专为计算机专业学生、考研 / 软考备考者、计算机底层原理学习者打造,是系统梳理 CPU 核心知识的高效学习工具。思维导图的结构化呈现方式,将 CPU 的功能和基本结构、指令执行过程、数据通路、控制器、指令流水线、多处理器系统六大核心模块拆解为层级清晰、逻辑连贯的分支框架,同时融入高频考点标注、关键概念对比与计算要点,帮助使用者快速构建 CPU 工作原理的知识体系,精准攻克数据通路设计、流水线性能分析、中断处理流程等重难点与高频考点。对于计算机专业学生与考研 / 软考备考者而言,这份思维导图模板可直接用于课堂笔记整理、期末复习、考点梳理,将 CPU 结构、指令执行周期、数据通路设计、硬布线 / 微程序控制器对比、流水线冲突处理、多处理器系统分类等零散知识点系统化,降低理解与记忆难度,提升备考效率;对于计算机底层原理学习者,模板清晰呈现了 CPU 从指令取指到执行的完整工作流程,可用于入门学习、底层原理学习的知识框架搭建,快速建立对计算机核心部件的整体认知。模板完整覆盖中央处理器核心考点:从 CPU 的功能与基本结构、指令执行的完整过程,到数据通路的设计原理与分类;从硬布线与微程序控制器的工作原理与对比,到指令流水线的性能指标、冲突处理与多发技术;再到多处理器系统的基本概念与硬件多线程技术,均以思维导图形式清晰呈现,层级分明,便于快速查阅、重点标记与按需编辑修改,适配备考笔记、课程复习提纲、学习课件等多种场景。
社区模板帮助中心,点此进入>>
这是一篇关于408考研,期末考试,计算机组成原理,输入输出系统思维导图,专为计算机专业学生、考研(如 408 统考)/ 软考备考者、计算机硬件底层原理学习者打造,是系统梳理 I/O 系统核心知识的高效学习工具。思维导图的结构化呈现方式,将 I/O 系统的基本概念、I/O 接口、I/O 控制方式、中断处理流程四大核心模块拆解为层级清晰、逻辑连贯的分支框架,同时融入高频考点标注、原理示意图与对比表格,帮助使用者快速构建输入 / 输出系统的知识体系,精准攻克 I/O 控制方式对比、DMA 传输原理、中断处理流程、磁盘调度算法等重难点与高频考点。对于计算机专业学生与考研 / 软考备考者而言,这份思维导图模板可直接用于课堂笔记整理、期末复习、考点梳理,将 I/O 接口的软硬件构成、程序查询 / 中断 / DMA 控制方式的差异、中断响应与处理全过程、磁盘调度计算等零散知识点系统化,降低理解与记忆难度,提升备考效率;对于计算机底层原理学习者,模板清晰呈现了主机与外设数据交互的完整逻辑,可用于入门学习、硬件原理学习的知识框架搭建,快速建立对计算机输入输出系统的整体认知。模板完整覆盖输入 / 输出系统核心考点:从 I/O 系统的基本概念、接口的分类与工作原理,到程序查询、中断、DMA 三种核心 I/O 控制方式的对比;从中断响应与完整处理流程,到磁盘调度算法、DMA 传输原理等计算类高频考点,均以思维导图形式清晰呈现,层级分明,便于快速查阅、重点标记与按需编辑修改,适配备考笔记、课程复习提纲、学习课件等多种场景。该模板借助万兴脑图软件绘制,助力计算机学习者高效掌握输入 / 输出系统核心知识。
这是一篇关于408考研,期末考试,计算机组成原理,总线的思维导图,专为计算机专业学生、考研 / 软考备考者、计算机底层原理学习者打造,是系统梳理总线系统核心知识的高效学习工具。思维导图的结构化呈现方式,将总线概述、总线仲裁、总线操作和定时、总线标准四大核心模块拆解为层级清晰、逻辑连贯的分支框架,同时融入关键原理示意图、性能计算要点与对比说明,帮助使用者快速构建总线系统的知识体系,精准攻克总线分类、仲裁方式、传输定时与性能分析等重难点与高频考点。对于计算机专业学生与考研 / 软考备考者而言,这份思维导图模板可直接用于课堂笔记整理、期末复习、考点梳理,将总线的特性与分类、集中式 / 分布式仲裁方式、同步 / 异步传输定时、总线性能指标计算等零散知识点系统化,降低理解与记忆难度,提升备考效率;对于计算机底层原理学习者,模板清晰呈现了计算机系统中各部件通过总线进行数据传输的完整逻辑,可用于入门学习、硬件原理学习的知识框架搭建,快速建立对计算机系统互连机制的整体认知。模板完整覆盖总线系统核心考点:从总线的基本概念、分类与特性,到总线仲裁的集中式与分布式实现;从总线操作的同步 / 异步 / 半同步定时方式,到总线标准与性能指标计算,均以思维导图形式清晰呈现,层级分明,便于快速查阅、重点标记与按需编辑修改,适配备考笔记、课程复习提纲、学习课件等多种场景。
这是一篇关于408考研,期末考试,计算机组成原理,中央处理器的思维导图,专为计算机专业学生、考研 / 软考备考者、计算机底层原理学习者打造,是系统梳理 CPU 核心知识的高效学习工具。思维导图的结构化呈现方式,将 CPU 的功能和基本结构、指令执行过程、数据通路、控制器、指令流水线、多处理器系统六大核心模块拆解为层级清晰、逻辑连贯的分支框架,同时融入高频考点标注、关键概念对比与计算要点,帮助使用者快速构建 CPU 工作原理的知识体系,精准攻克数据通路设计、流水线性能分析、中断处理流程等重难点与高频考点。对于计算机专业学生与考研 / 软考备考者而言,这份思维导图模板可直接用于课堂笔记整理、期末复习、考点梳理,将 CPU 结构、指令执行周期、数据通路设计、硬布线 / 微程序控制器对比、流水线冲突处理、多处理器系统分类等零散知识点系统化,降低理解与记忆难度,提升备考效率;对于计算机底层原理学习者,模板清晰呈现了 CPU 从指令取指到执行的完整工作流程,可用于入门学习、底层原理学习的知识框架搭建,快速建立对计算机核心部件的整体认知。模板完整覆盖中央处理器核心考点:从 CPU 的功能与基本结构、指令执行的完整过程,到数据通路的设计原理与分类;从硬布线与微程序控制器的工作原理与对比,到指令流水线的性能指标、冲突处理与多发技术;再到多处理器系统的基本概念与硬件多线程技术,均以思维导图形式清晰呈现,层级分明,便于快速查阅、重点标记与按需编辑修改,适配备考笔记、课程复习提纲、学习课件等多种场景。
第四章 指令系统
4.1指令格式
指令的基本格式
指令的作用
改变程序执行流
处理数据
指令集体系结构(ISA)
完整定义了软件和硬件之间的接口
是计算机硬件的语言系统
是软件和硬件之间接口的一个完整定义
包含了基本数据类型、指令集、寄存器(个数和位数)、寻址模式、存储体系、中断和异常处理及外部 IO
和机器指令有关
指令的基本格式
操作码OP+地址码A
区别
I/O指令
操作码+命令码+设备码
按地址码数目的不同
零地址指令
OP
只有操作码
分类
不需要操作数的指令
空操作指令、停机指令和关中断指令
零地址的运算类指令
也称堆栈运算指令
参与的两个操作数来自栈顶和次栈顶单元
从堆栈中取出两个操作数,再将结果压入堆栈
操作数固定隐含在某个位置
如在栈中
补充
堆栈指令的访存次数
取决于采用的是软堆栈还是硬堆栈
软堆栈(堆栈区由内存实现)
对于双目运算需要访问4次内存
取指令、取源数 1、取源数 2、存结果
硬堆栈(堆栈区由寄存器实现)
只需在取指令时访问一次内存
一地址指令
OP+A
分类
只有目的操作数的单操作指令
如加1、减1、取反、求补等
指令含义:
OP(A1)→A1
取指→读A1→写A1
完成一条指令需要访存3次
隐含目的地址的双操作指令
需要两个操作数,但其中一个操作数隐含在某个寄存器(如隐含在ACC)
隐含寻址
指令含义:
(ACC)OP(A1)→ACC
取指→读A1
完成一条指令需要访存2次
注
A1指某个主存地址,(A1)表示A1所指向的地址中的内容
类比C语言指针
()表示指针所指位置的内容
二地址指令
OP+A1(目的操作数)+A2(源操作数)
常用于需要两个操作数的算术运算、逻辑运算相关指令
指令含义:
(A1)OP(A2)→A1
取指→读A1 →读A2 →写A1(存到A1)
完成一条指令需要访存4次
三地址指令
OP+A1+A2+A3(结果)
常用于需要两个操作数的算术运算、逻辑运算相关指令
指令含义:
(A1)OP(A2)→A3
取指→读A1 →读A2 →写A3
完成一条指令需要访存4次
四地址指令
OP+A1+A2+A3(结果)+A4(下址)
指令含义:
(A1)OP(A2)→A3
取指→读A1 →读A2 →写A3
A4=下一条将要执行指令的地址
正常情况下
取指令之后 PC+1,指向下一条指
四地址指令
执行指令后,将PC的值修改为A4所指地址
只是修改PC,不是进行访存
完成一条指令需要访存4次
注
若指令总长度固定不变,则地址码数量越多,寻址能力越差
n位地址码的直接寻址范围=2^n
指令系统的分类
按总长度分类
定长指令字结构:
指令系统中所有指令的长度都相等
变长指令字结构:
指令系统中各种指令的长度不等
按照操作码长度分类
定长操作码:
指令系统中所有指令的操作码长度都相同
操作码的位数
可以直接反映系统当中最多可以支持多少条指令
一般n位操作码字段的指令系统最大能够表示2^n条指令
指令字的最高位部分分配固定的若干位表示操作码
优点
控制器的译码电路设计简单
简化计算机硬件设计,提高指令译码和识别速度
缺点
指令数量增加时会占用更多固定位, 留给表示操作数地址的位数受限
灵活性较低
可变长操作码:
指令系统中各指令的操作码长度可变
控制器的译码电路设计复杂,但灵活性较高
扩展操作码指令格式
定长指令字结构+可变长操作码
根据开头的位数来确定是几地址指令
不同地址数的指令使用不同长度的操作码
对使用频率较高的指令
分配较短的操作码;
使用频率较低的指令
分配较长的操作码
尽可能减少指令译码和分析的时间
注
不允许短码是长码的前缀
哈夫曼树“前缀编码”
各指令的操作码不能重复
优点
在指令字长有限的前提下仍保持比较中富的指令种类
缺点
增加了指令译码和分析的难度,使控制器的设计复杂化

按操作类型分类
数据传送类:
进行主存与CPU之间的数据传送
1.数据传送
LOAD
作用: 把存储器(源)中的数据放到寄存器(目的)中
STORE
作用: 把寄存器中的数据放到存储器中
运算类
2.算术逻辑操作
算术:加、减、乘、除、增1、减1、求补、浮点运算、十进制运算
逻辑:与、或、非、异或、位操作、位测试、位清除、位求反.
3.移位操作
算术移位、逻辑移位、循环移位(带进位和不带进位)
程序控制类
改变程序执行的顺序
4.转移操作
用来实现程序执行流的改变(程序跳转)
会导致PC的改变
有条件/无条件
条件转移
先判断条件是否成立,才决定是否转移
条件转移
JZ: 结果为0;
JO: 结果溢出
JC:结果有进位
无条件转移
不用判断条件就可以转移
函数调用和返回
CALL和RETURN
无条件转移JMP
直接/间接
直接转移
转移目标地址直接放在指令中,执行时直接将地址码送入PC
间接转移
转移目标地址存放在寄存器或内存单元中
相对/绝对
相对转移
转移目标地址为当前PC值加上偏移量,偏移量一般在指令中
绝对转移
转移目标地址直接由指令或寄存器给出
陷阱(Trap)与陷阱指令
输入输出类(I/O)
进行CPU和I/O设备之间的数据传送
5.输入输出操作
CPU寄存器与IO端口之间的数据传送(端口即IO接口中的寄存器)
注:
指令集
所有指令的集合构成该指令的指令系统
机器指令是计算机运行的最小功能单位
一台计算机只能执行自己指令系统中的指令,不能执行其他系统的指令
Eg: x86 架构、ARM架构
4.2指令的寻址方式
指令寻址和数据寻址
指令寻址:
寻找下一条要执行的指令地址
始终由程序计数器PC给出
指令寻址
分类
顺序寻址
( PC)+“1”→PC
”1“理解为1个指令字长,实际加的值会因指令长度、编址方式而不同
该系统采用定长指令字结构
指令字长=存储字长=16bit=2B
主存按字编址
(PC)+ 1→PC
主存按字节编址
( PC)+ 2→PC
该系统采用变长指令字结构
主存按字节编址
读入一个字,根据操作码判断这条指令的总字节数n
修改PC的值( PC)+n→PC
根据指令的类型,CPU可能还要进行多次访存,每次读入一个字
跳跃寻址
由转移指令指出
JMP:无条件转移指令
把PC中的内容改成某指令地址,类似C语言的goto
直接改变PC的值
改变了程序的执行流
分类
绝对转移
相对转移
注:
每一条指令的执行都分为“取指令”、“执行指令” 两个阶段
先加一,(取指阶段结束)再执行
PC始终是下一条指令地址,执行时才会出现跳转,再改变PC的值
数据寻址
指令格式
一地址指令
操作码+寻址特征+形式地址A
地址码前加上几个比特位标识地址码采用什么样的寻址方式
二地址指令
操作码+寻址特征+形式地址A1+寻址特征+形式地址A2
有效地址(EA)
根据 寻址特征+形式地址A
求出操作数的真实地址,称为有效地址(EA)
数据寻址方式
假设指令字长=机器字长=存储字长
直接寻址

EA=A
指令字中的形式地址A就是操作数的真实地址EA,即EA=A。.
共访存2次
取指令访存1次 ,执行指令访存1次
暂不考虑存结果
优点
简单,指令的执行过程仅访问一次主存,不需要专门计算操作数的地址
缺点
A的位数决定了该指令操作数的寻址范围
操作数地址不易修改灵活性差
间接寻址
一次间接

EA=(A)
形式地址是操作数地址的地址
操作数有效地址所在的存储单元的地址
共访存3次
取指令访存1次, 执行指令访存2次
两次间接

1说明后面还需要寻址
0表示后面操作数是最终地址的地址
优点
可扩大寻址范围
有效地址EA的位数大于主存形式地址A的位数
便于编制程序
用间接寻址可以方便地完成子程序返回
缺点
指令在执行阶段要多次访存
一次间址 需要两次访存,多次寻址需要根据存储字的最高位确定几次访存
指令执行效率低
寄存器寻址

EA=Ri
操作数在由Ri所指的寄存器内
直接给出操作数所在的寄存器编号
共访存1次
取指令访存1次 执行指令访存0次
优点
指令在执行阶段不访问主存,只访问寄存器
指令字短且执行速度快,支持向量/矩阵运算
缺点
寄存器昂贵,寄存器个数有限
寻址能力有限
寄存器间接寻址
EA=(Ri)
操作数在寄存器Ri所存的地址中
寄存器Ri给出的不是一个操作数,而是操作数所在主存单元的地址即EA=(Ri)
共访存两次
取指令访存1次 执行指令访存1次
优点
与一般间接寻址相比速度更快
缺点
但指令的执行阶段需要访问主存
有括号需要间接寻址
隐含寻址

不是明显地给出操作数的地址,而是在指令中隐含着操作数的地址
另一个操作数隐含在ACC中
优点
有利于缩短指令字长
缺点
需增加存储器操作数或隐含地址的硬件
立即数寻址
又称为立即数

#表示立即寻址特征
0……011就是想要的操作数
形式地址A就是操作数本身(操作数的值而非地址)
一般采用补码形式
共访存一次
取指令访存1次 执行指令访存0次
优点
指令执行阶段不访问主存,指令执行时间最短
缺点
A的位数限制了立即数的范围。
A的位数为n,且立即数采用补码时,可表示的数据范围为 -2^(n-1)~2^(n-1)-1
偏移寻址
A形式地址
视作偏移量
以某个地址作为起点+偏移量
区别
起点不同
基址寻址
以程序的起始存放地址作为“起点”
每个程序存放位置不固定
程序运行前,CPU将BR的值修改为该程序的起始地址
存在操作系统进程控制块PCB中
操作数的有效地址
将CPU中基址寄存器(BR) 的内容加上指令格式中的形式地址A

EA=(BR)+A
基址寄存器
专用基址寄存器
面向操作系统,内容由操作系统或管理程序确定
注
OS课中的“重定位寄存器”就是“基址寄存器”
通用寄存器
由用户决定哪个寄存器作为基址寄存器,内容由操作系统确定
OP+寻址特征+Ri+A
在指令中指明要将哪个通用寄存器作为基址寄存器使用
Ri为用户指定的基址寄存器
要用几个bit指明寄存器?
根据通用寄存器总数判断
注:
基址寄存器是面向操作系统的,其内容由操作系统或管理程序确定
在程序执行过程中,基址寄存器的内容不变(作为基地址),形式地址可变(作为偏移量)。
当采用通用寄存器作为基址寄存器时,可由用户决定哪个寄存器作为基址寄存器,但其内容仍由操作系统确定。
优点
可扩大寻址范围
基址寄存器的位数大于形式地址A的位数
便于程序“浮动”,方便实现多道程序并发运行
可用于编制浮动程序
用户不必考虑自己的程序存于主存的哪一空间区域
整个程序在内存里边的浮动
让BR指向程序的起始地址
变址寻址
操作数的有效地址
程序员自己决定从哪里作为“起点”(IX)
EA=(IX)+A
有效地址EA等于指令字中的形式地址A与变址寄存器IX的内容相加之和
A与主存寻址空间有关
IX
可为变址寄存器(专用)
也可用通用寄存器作为变址寄存器
类似基址寻址两种寄存器的图
注
变址寄存器是面向用户的
在程序执行过程中,变址寄存器的内容可由用户改
IX作为偏移量
形式地址A作为基地址不变
区别
基址寻址中,BR保持不变作为基地址,A作为偏移量
变址寄存器的值普通程序员可以采用指令的形式修改
特点
可扩大寻址范围
数组处理过程中,设定A为数组的首地址,不断改变变址寄存器IX中的内容
形成数组中任一数据的地址
有利于处理数组问题和编制循环程序
基址&变址复合寻址
先基址后变址寻址:
EA=(IX)+(BR)+A
相对寻址
以程序计数器PC所指地址作为“起点”
相对于下一条指令的偏移
操作数的有效地址
EA=(PC)+A
PC的内容加上形式地址A
A是相对于PC所指地址的位移量
可正可负,补码表示
PC取值后进行了自增运算,自增长度与当前指令长度有关
特点
便于程序浮动
操作数的地址不是固定的,它随着PC值的变化而变化
与指令地址之间总是相差一个固定值
一段代码在程序内部的浮动
相对寻址广泛应用于转移指令
注
ACC加法指令的地址码,可采用“分段”方式解决,即程序段、数据段分开
分段使得程序浮动而数组起始地址不变
PC M+4
区别:偏移起点不同
堆栈寻址
有效地址
SP所指向的地址
操作数存放在堆栈中
系统的堆栈的两种实现方式
硬堆栈
寄存器堆栈
用寄存器来实现堆栈
该寄存器称为堆栈指针(SP)

该存储区中被读/写单元的地址是用一个特定的寄存器给出
SP寄存器指向的栈顶元素作为操作数地址
对栈的压入/弹出都不需要访存
速度快,成本高
软堆栈
主存中划分堆栈
弹出/压入栈顶元素要进行一次访存
访问速度慢,成本低
在实际的系统中通常采用软堆栈
软堆栈可用于函数调用时保存当前函数的相关信息
注
和数据结构栈的出栈入栈类似
要看指针指向栈顶元素还是下一个位置
补充
堆栈
是存储器(或专用寄存器组)中一块特定的按“后进先出(LIFO) ”原则管理的存储区
总结

高级语言与机器级代码之间的对应关系
注
只需关注x86汇编语言;若考察其他汇编语言题目会详细注释
题目给出某段简单程序的C语言、汇编语言、机器语言表示。能结合C语言看懂汇编语言的关键语句(看懂常见指令、选择结构、循环结构、函数调用)
汇编语言、机器语言一一对应,要能结合汇编语言分析机器语言指令的格式、寻址方式
不会考:将C语言人工翻译为汇编语言或机器语言
x86架构CPU中的寄存器
每个寄存器都是32bit
都是e/E开头
通用寄存器
eax、ebx、ecx、edx
E= Extended = 32bit
都以X结尾
(X=未知)
什么数据都可以存
只使用通用寄存器更低的16个比特
去掉E
AX(低16bit)
BX(低16bit)
CX(低16bit)
DX(低16bit)
mov ax, bx
将bx的16比特复制到ax16
mov ax, word ptr [af996h]
单字(16比特)复制到ax
只使用指定的8bit
AH(8bit)
AL8bit
BH8bit
BL8bit
CH8bit
CL8bit
DH8bit
DL8bit
mov ah, byte ptr [af996h]
mov ah, 5
变址寄存器
esi、edi
都以I结尾
变址寄存器可用于线性表、字符串的处理
只能使用固定32比特
堆栈寄存器
ebp、esp
堆栈基指针(Base Pointer)
栈基(栈底)
堆栈顶指针(Stack Pointer)
都以P结尾
堆栈寄存器用于实现函数调用
程序执行流改变
只能使用固定32比特
常用的x86指令
要求
不允许两个操作数同时来自主存
访问主存次数越多,指令执行速度越慢
mov eax,[ebp-8] mov [esp+4],eax
不能两个[]
mov不支持两个操作数同时来自主存
目的操作数(d)不能是常量
只能来自寄存器或者主存
存放结果
最终处理完的结果放在目的操作数d中
s可以来自寄存器可以来自主存,可以是常量
常见的算术运算指令
加add
add d,s
#计算d+s,结果存入d
减subtract
sub d,s
#计算d-s,结果存入d
乘multiply
mul d,s
#无符号数d*s,乘积存入d
imul d,s
#有符号数d*s,乘积存入d
除divide
div s
#无符号数除法
idiv s
#有符号数除法
注
被除数隐含寻址,s是除数
被除数会被提前放到eax,edx之中
edx:eax/s,商存入eax,余数存入edx
在进行除法运算之前,需要把被除数进行位扩展
如,32位的被除数除以32位的除数,需要把被除数扩展为64位,需要两个寄存器
每个以e开头的寄存器32位
取负数negative
neg d
#将d取负数,结果存入d
自增++(increase)
inc d
#将d++,结果存入d
自减--(decrease)
dec d
#将d--,结果存入d
常见的逻辑运算指令
与
and d,s
#将 d、s逐位相与,结果放回d
或
or d,s
#将 d、s逐位相或,结果放回d
非
not d
#将d逐位取反,结果放回d
异或
xor d,s
#将 d、s逐位异或,结果放回d
左移
shl d,s
#将d逻辑左移s位,结果放回d
通常s是常量
右移
shr d,s
#将d逻辑右移s位,结果放回d(通常s是常量)
其他指令
用于实现分支结构、循环结构的指令
cmp、test、jmp、jxxx
用于实现函数调用的指令
push、pop、call、ret
用于实现数据转移的指令
mov指令
#mov指令功能:
将源操作数s复制到目的操作数d所指的位置
目的操作数d,源操作数s
destination:目的地
source:来源、发源地
mov eax, ebx
#将寄存器 ebx 的值复制到寄存器 eax
mov eax, 5
#将立即数5 复制到寄存器 eax
mov eax, dword ptr [af996h]
#将内存地址 af996h 所指的32bit值复制到寄存器 eax
mov byte ptr [af996h], 5
#将立即数5 复制到内存地址 af996h 所指的一字节中
mov eax, dword ptr [af996-12h]
#将 af996-12 所指主存地址的 32bit 复制到 eax 寄存器中
dword ptr [af996h]
[af996h]
外面有中括号:内存地址
通常16进制表示,结尾h
前面指明此次要读或者要写的数据是多少个比特(长度)
读写内存地址读多少字节
注
若未指明主存读写长度,默认 32 bit
汇编语言中指明读写内存的数据长度
dword ptr[地址]--双字,32bit
d
double
word ptr[地址]--单字,16bit
X86里一个字长度16bit
byte ptr[地址]--字节,8bit
AT&T格式 vs Intel格式
AT&T
Unix、Linux 的常用格式
Intel
Windows的常用格式
区别

基址+变址*比例因子(可以得到数据元素)+偏移量(得到数据元素中的具体变量

指令中读写长度
没有加明长度,默认都是32bit
选择语句机器级表示
注:
Intelx86处理器中程序计数器PC通常被称为IP
程序默认顺序执行
无条件转移指令
不会管PSW的各种标志位
jmp <地址>
#PC无条件转移至<地址>
jmp 128
#<地址>可以用常数给出
jmp eax
#<地址>可以来自于寄存器
jmp [999]
#<地址>可以来自于主存
要知道程序存储的位置
jmp NEXT
#<地址>可以用“标号”锚定
NEXT:
特征——有冒号,名字可以自己取
条件转移指令
一般要和cmp指令一起使用
cmp a,b
#比较a和b两个数
a、b两个数可能来自寄存器/主存/常量
cmp eax, ebx #比较寄存器eax和ebx里的值 jg NEXT #若eax > ebx, 则跳转到NEXT:
je <地址>
#jump when equal, 若a==b则跳转
jne <地址>
#jump when not equal, 若a! =b则跳转
jg <地址>
#jump when greater than, 若a>b则跳转
jge <地址>
#jump when greater than or equal to, 若a>=b则跳转
jl <地址>
#jump when less than, 若a<b则跳转
jle <地址>
#jump when less than or equal to, 若a<=b则跳转


写汇编语言代码时,一般会以函数名作为“标号”,标注该函数指令的起始地址
在进行条件转移时,就可以从函数的起始地址进行偏移
计算出跳转到什么位置

跳转到从函数f1起始地址偏移后的位置
补充
PSW标志寄存器
记录上次运算的结果
零标志ZF
运算结果为0则ZF=1,否则ZF=0
符号标志 SF
结果的符号
运算结果为负,SF=1,否则为0
溢出标志
OF
有符号数运算是否溢出
有符号整数的溢出标志
运算结果有溢出OF=1否则为0
进位/借位标志CF
无符号数运算是否溢出
最高位有进位/借位时CF=1
AF(辅助进位标志)
D3→D4位产生了进位或借位 =0 D3→D4位无进位或借位;
ALU每次运算的标志位都自动存入PSW 程序状态字寄存器(Intel称其为“标志寄存器”)
注
硬件不区分送过来的操作数是有符号还是无符号
不区分操作数的类型
计算是硬件的事,解释是软件的事
条件转移指令根据相应标志位进行条件判断
cmp指令
比较a和b(如cmp a,b)
实质上是用 a-b
相减的结果信息会记录在程序状态字寄存器中(PSW)
据PSW的某几个标志位进行条件判断,来决定是否转移
注:
无条件转移指令jmp2,就不会管PSW的各种标志位
相减的结果信息会记录在程序状态字寄存器中(PSW)
#若a==b则跳转,ZF==1?
#若a!=b则跳转,ZF==0?
#若a>b则跳转,ZF==0&& SF==OF ?
#若a>=b则跳转,SF==OF ?
#若a<b则跳转,SF!=OF ?
#若a<=b则跳转,SF!=OF||ZF==1 ?
比较无符号数大小
① CF=0,前者大于或等于后者;
② CF=1,前者小于后者;
例如:67-255,在这个减法中,被减数是67,减数是255,结果显示最高位是1,说明减法发生了借位,此时CF=1,表示被减数是小于减数。从结果来看,并不是在0~255之间,超过了范围,说明结果是错误的。
比较有符号数大小
有符号数的大小需要组合OF、SF标志,并利用ZF标志确定相等
① 如果结果是OF=0,且SF=0(正),或者当OF=1,且SF=1(负)时,说明两个数是前者大于或等于后者。
② 如果结果是OF=0,且SF=1(负),或者当OF=1,且SF=0(正)时,说明两个数是前者小于后者。
简单记忆:相同为正,不同为负
循环语句的机器级表示
使用条件转移指令实现循环

循环结构
循环体内最后会有一条条件转移指令
判断是否跳出循环
可以用比较指令(CMP)来实现
loop指令实现循环
mov ecx,500 #用ecx作为循环计数器 Looptop: #循环的开始 做某些处理 loop Looptop
loop Looptop
#ecx--,若ecx!=0,跳转到Looptop
等价于:
dec ecx
cmp ecx,0
jne Looptop
使用loop指令要配合着使用ecx,用ecx中的值来判断
不能用其他寄存器代替
loopx
一大类指令,实现循环
x可以是nz,z……
用C语言逆推
loopnz
当ecx!=0&&ZF==0时,继续循环
nz---not zero
在LOOP指令的基础上额外判断ZF是否为0
loopz
当ecx!=0&&ZF==1时,继续循环
使用 loop 指令可能会使代码更清晰简洁
注
理论上,能用loop 指令实现的功能一定能用条件转移指令实现
函数调用的机器级表示
ebp、esp寄存器
在CPU内部只有一个ebp和一个esp
标记了当前正在执行的函数栈帧范围
ebp
指向当前函数栈帧底部4字节
esp
指向当前函数栈帧顶部4字节
发起调用、返回
函数调用指令
call<函数名>
add:
通常用函数名作为函数起始地址的<标号>
call add
调用add函数
call 指令的作用
①将IP旧值压栈保存(保存在函数的栈帧顶部)
相当于push IP
②设置IP新值,无条件转移至被调用函数的第一条指令
相当于jmp add
函数返回指令
ret
回到call指令后面一条指令继续执行
ret 指令的作用:
从函数的栈帧顶部找到 IP旧值,将其出栈并恢复IP寄存器
如何传递参数、返回值
在call指令前,将调用参数写入栈帧顶部区域
在ret指令前,将函数返回值写入 eax寄存器
函数调用栈
函数调用栈
一片内存区域
栈底保存和硬件、系统相关的其他信息
函数的栈帧(stack Frame)
保存函数大括号内定义的局部变量、保存函数调用相关的信息
main的栈帧
存储main函数的区域
当前正在执行的函数栈帧,位于栈顶
函数返回时删除对应的栈帧
通常在汇编语言之中用标号标记一个函数的开始
标记
带冒号
调用函数栈在内存中的位置
栈顶在地址变小的位置
访问栈帧数据
push、pop 指令
push 指令
push **
先让 esp 减4,再将**压入
**可以是立即数、寄存器、主存地址
pop 指令
pop X
栈顶元素出栈写入**,再让esp 加4
X可以是寄存器、主存地址
可以用减法/加法指令,即 sub/add 修改栈顶指针 esp 的值
调整当前函数的栈帧范围
sub esp, 12
#栈顶指针-12
esp-12,再写回esp
add esp, 8
#栈顶指针+8
可以用 mov 指令,结合 esp、ebp 指针访问栈帧数据
mov [esp+8], eax
#将eax的值复制到主存[esp+8]
mov [esp+4],958
#将985复制到主存[esp+4]
mov eax, [ebp+8]
#将主存[ebp+8]的值复制到eax
mov [esp],eax
#将eax的值复制到主存[esp]
如何访问栈帧内数据
对ebp进行偏移来找到函数定义的局部变量
访问当前函数的局部变量
[ebp-4]、[ebp-8]
[ebp-4]定义了访问函数内部的局部变量(C语言中最后一个出现的变量)
[ebp-8]对应C语言中倒数第二个被定义的局部变量
访问上一层函数传过来的参数
[ebp+8]、[ebp+12]...
调用add时访问上一层函数给其传递的参数只需要[edp+8],[edp+12]找到x,y两个参数
[edp+8]
当前执行函数参数列表中的第一个参数
[edp+12]
当前执行函数参数列表中的第二个参数
函数调用时,如何切换栈帧
enter指令
0地址指令,后面不需要任何操作数
在每个函数开头,需例行执行 enter 指令
存储了调用其的上一层函数栈帧基址
等价
push ebp
#保存上一层函数的栈帧基址(ebp旧值)
返回到上一层函数时可以根据记录的地址让ebp重新指回到上一层函数的基地址
mov ebp,esp
#设置当前函数的栈帧基址(ebp新值)
让ebp指向了新函数的基地址
注:
每个栈帧底部,用于保存上一层栈帧的基址
leave 指令
每个函数 ret 之前,需例行执行 leave 指令
等价
mov esp,ebp
#让esp指向当前栈帧的底部
pop ebp
#将esp所指元素出栈,写入寄存器ebp
pop出栈的同时esp+4
栈帧
在函数调用栈中,一个栈帧对应一层函数,用于存储每层函数相关的一些信息
特点
栈底在高地址方向
栈顶在低地址方向
以4字节为单位操作栈帧
gcc编译器将每个栈帧大小设置为16B 的整数倍(当前函数的栈帧除外)
C语言--->汇编语言,数据对齐
当前运行的函数可以是四字节,可以是八字节
只要这层函数需要调用下一层函数,这个函数的栈帧要凑齐至16字节的整数倍
一个栈帧包含哪些内容(自底向顶)
1||| 上一层栈帧的基地址(ebp旧值)
栈帧最底部一定是上一层栈帧基址(ebp旧值)
每个函数开头都要执行:
push ebp
mov ebp,esp
一定存在
用于恢复上一层函数的栈帧
2||| 若干个局部变量;
通常将局部变量集中存储在栈帧底部区域
C语言中越靠前定义的局部变量越靠近栈顶
不一定存在
有些函数可能不定义局部变量
3||| 未使用区;
栈帧大小为16B整数倍,因此可能产生未使用区域
一定存在
如果其他部分刚好是16B整数倍,则不会留下“零头
4||| 部分寄存器值
调用其他函数前可将某些寄存器的值入栈保存,防止中间结果被破坏
一定存在
如果这些寄存器值不是运算的中间结果,则可以不保存
5||| 若干个调用参数
通常将调用参数集中存储在栈帧顶部区域
在call指令调用之前,往栈帧顶部写入参数
便于调用函数使用[ebp-4]进行访问
参数列表中越靠前的参数越靠近栈顶
6||| IP返回地址(IP旧值)
栈帧最顶部一定是返回地址(当前函数的栈帧除外)
函数调用时,call 指令将IP寄存器值(返回地址)压栈保存
一定存在(发生调用时)
但凡调用其他函数,就必须记录返回地址
如何传递参数和返回值
调用者
保存必要的寄存器
如eax、edx、ecx
将调用参数写入当前栈帧的顶部区域
可用 push 或mov 指令实现
执行 call 指令
返回地址压入栈顶并跳转到被调用函数第一条指令
使用返回值
通过eax寄存器
恢复必要的寄存器
被调用者
保存上一层函数栈帧,设置当前函数栈帧
push ebp mov ebp,esp
或:enter指令
初始化局部变量
[ebp-4]、 [ebp-8]...
一系列处理逻辑
向上层函数传递返回值
通过eax寄存器
恢复上一层函数的栈帧
mov esp, ebp pop ebp
或:leave指令
执行 ret 指令
从栈顶找到返回地址出栈并恢复 IP 值
注
函数返回只能有一个返回值
返回值写入eax寄存器中
除了main函数,其他所有函数的汇编代码结构都一样!
4.3CISC和RISC
CISC和RISC对比

Load读某个主存单元读到某一个寄存器中,
store:从某个寄存器当中往主存里面写一个数据
乘法指令可以访问主存,一定是CISC
逻辑控制效率更高
微程序控制效率更低
CISC
一条指令完成一个复杂的基本功能
CISC指令格式种类多,增大了编译优化的复杂性,不利于编译优化
X86架构,用于笔记本和台式机
大多实现软件兼容
RISC
一条指令完成一个基本”动作“
多条指令组合完成一个复杂的基本功能
增加了编译器的设计难度和程序员的编程难度
指令执行时间差不多
有利于实现并行技术、流水线技术
ARM架构,用于手机和平板
基于的事实:20%的指令占80%的程序
不能与老机器兼容
以硬布线逻辑为主,不用或少用微程序控制
部分寄存器值
[ebp+8]、[ebp+12]...
栈帧最顶部一定是返回地址(当前函数的栈帧除外)