4.3 指令和数据的寻址方式
存储器的作用在于存储数据和指令。每个存储单元的编号即为其中存储的操作数或指令的地址。当我们提到存储器的寻址方式时,我们是指如何确定存储器中某个单元的位置。常见的寻址方式包括直接寻址、间接寻址、寄存器寻址、寄存器间接寻址、堆栈寻址等。
指令的寻址方式
指令寻址是指确定指令在内存中位置的方法,而数据寻址则是确定数据在内存中位置的方法。在执行指令时,指令寻址和数据寻址往往是交替进行的。
顺序寻址方式
指令通常在内存中顺序存放,因此在程序执行时,大部分时间是按顺序执行指令的。在这种方式下,每执行一条指令,程序计数器(PC)就自动递增,以指向下一条指令的地址。这种简单的寻址方式是程序执行的默认方式,如图4.2(a)所示。
跳跃寻址方式

当程序需要非顺序执行时,例如在循环、分支或函数调用中,将使用跳跃寻址方式。在这种方式下,PC的值将被更新为非顺序的指令地址。跳跃寻址方式可以是直接的,也可以是通过计算得到的,例如相对寻址、基址寻址或索引寻址。
图4.2分析
图4.2(a) 顺序寻址方式的示意图
在图4.2(a)中,指令顺序寻址的过程被示意化表示。程序计数器指向存储器中的下一个要执行的指令,此时是按照顺序执行的指令集。
图4.2(b) 跳跃寻址方式的示意图
而在图4.2(b)中,可以看出程序在执行到某个点后会发生跳跃。例如,在地址3的位置有一个JMP
指令,它会使PC跳到地址8的位置,从而改变了指令的执行流。
2. 跳跃寻址方式
什么是跳跃寻址?
跳跃寻址,又称为非顺序寻址,是一种允许程序跳过某些指令或跳转到程序的另一部分继续执行的寻址方式。在这种寻址方式下,程序计数器(PC)不再简单地递增,而是根据当前执行指令指定的地址进行更新。
如何实现?
跳跃寻址可以通过多种类型的跳转指令实现,包括:
- 无条件跳转指令(JMP):不论什么条件都会执行的跳转。
- 条件跳转指令:只有在特定条件满足时才执行的跳转,如比较指令后跟随的条件跳转。
- 调用指令(CALL):跳转到子程序或函数的开始,通常在子程序或函数返回后将控制权返回到调用点。
- 返回指令(RET):从子程序或函数返回到调用它们的地方。
跳跃寻址的作用
- 程序逻辑控制:允许程序根据条件进行分支或重复某段代码(循环)。
- 功能模块化:通过函数或子程序调用,实现代码的复用,简化程序结构。
- 节省空间:减少程序长度,避免重复代码,使得程序更加紧凑。
- 公共代码块:允许将特定功能的代码作为公共库来调用,避免在程序中多次编写相同的代码段。
实际应用
在实际的程序设计中,跳跃寻址的应用非常广泛。例如,在循环中,通过跳跃寻址方式,可以让程序回到循环的开始点;在条件语句中,根据条件的真假,程序可以跳转到不同的代码块执行。此外,异常处理和中断响应也依赖于跳跃寻址,以便于在事件发生时快速转移控制权。
总的来说,跳跃寻址方式是程序设计中不可或缺的部分,它使得编写复杂的程序逻辑成为可能,并且提升了代码的灵活性和效率。通过理解和恰当地应用跳跃寻址,程序员可以编写出结构清晰、逻辑严谨的程序。
结论
寻址方式是程序执行的核心部分,决定了计算机如何从存储器中获取指令和数据。理解和正确实现这些寻址方式对于高效程序执行至关重要。每种寻址方式都有其特定的应用场景和优劣,程序员和计算机架构师必须根据实际需求选择最合适的方法。
疑问:
为什么有两种不同的寻址方式 ?


顺序寻址方式
为什么使用:
- 默认执行流程: 大部分程序的指令是按照编写的顺序执行的。
- 简单高效: 自动递增程序计数器的方式是简单且高效的,因为它不需要任何额外的计算或内存访问来确定下一条指令的位置。
用途:
- 线性代码执行: 执行没有分支、循环或函数调用的简单程序代码。
- 顺序逻辑: 实现按顺序处理数据和算法的基本逻辑。
跳跃寻址方式
为什么使用:
- 控制流程: 程序往往需要根据逻辑条件进行决策,如条件语句和循环控制,这时候需要能够跳过某些指令或者跳转到特定的指令去执行。
- 高级结构支持: 支持函数调用、异常处理和事件响应等高级编程结构。
用途:
- 分支和循环: 允许程序根据条件重复执行指令集或跳过某些指令。
- 函数调用: 实现函数或过程的调用,其中执行流程需要跳转到代码的非连续部分。
- 事件驱动编程: 在操作系统或事件驱动的应用程序中,响应中断或事件时,需要从一部分代码跳转到中断处理程序或事件处理器。
综合来看,顺序寻址方式和跳跃寻址方式的共存,为编程语言提供了表现力,使得能够实现复杂的算法和控制流程。而且,跳跃寻址方式还可以优化程序的性能,通过跳过不必要的指令,可以缩短程序执行时间和提高效率。在现代的处理器和编程语言中,各种寻址方式的混合使用是非常普遍的,它们共同构成了程序执行的基础。
二、操作数的寻址过程
操作数寻址过程的本质是将指令中的形式地址转换为可以直接访问的有效地址。这个转换过程可能涉及简单的直接读取,也可能需要更复杂的计算或内存访问。下面是一些常用的操作数寻址方式:
1. 隐含寻址
隐含寻址方式不在指令的地址字段中直接给出操作数的地址,而是默认操作数存放在一个预定的地方,通常是某个寄存器。例如,某些单操作数指令默认使用累加寄存器AC作为操作数地址,这就是隐含寻址的典型案例。
2. 立即寻址
在立即寻址方式中,指令的地址字段直接包含了操作数的值,而不是它的地址。立即寻址对于指令的快速执行非常有利,因为它省去了对内存的访问过程。
例如,在某些指令中,一个标志位可能指示移位操作的方向,而操作数字段直接指示移动的位数。
3. 寄存器寻址
当操作数位于中央处理器的通用寄存器中而不是存放在内存中时,我们使用寄存器寻址。在这种情况下,指令中的地址字段将是寄存器的编号,而非内存地址。
4. 直接寻址
直接寻址是一种简单的寻址方式,其特点在于操作数的内存地址直接包含在指令的地址字段中。直接寻址因其简洁性而常用于各种计算机体系结构中。
示意图解析
图4.3(a)展示了直接寻址方式的过程:指令字中的形式地址D就是操作数的有效地址E,即 E=D。这意味着在执行时,操作数可以直接通过指令中给出的地址来访问。
寻址方式的选择和应用






不同寻址方式的选择依赖于指令的类型、数据的位置以及执行效率等因素。隐含寻址和立即寻址通常用于快速执行和节省内存访问时间的场合。寄存器寻址则适用于频繁使用的变量,以减少对内存的访问并加速执行。直接寻址则提供了一种简单明了的方式来访问内存中的数据。
在现代计算机中,这些寻址方式的结合使用使得指令集既可以简单高效,又具有灵活性和强大的功能。每种寻址方式都有其适应的场景,程序员需要根据具体的应用需求和系统特性,选择最合适的寻址方式来设计指令集和编写程序。理解并正确应用这些寻址方式,对于优化程序性能和内存使用是非常关键的。
5. 间接寻址
间接寻址是一个两步过程的寻址方式,在第一步中,形式地址指向操作数地址的指示器,而在第二步中,指示器中的内容被用作操作数的有效地址。
比喻解释
想象一下,你在图书馆寻找一本书。直接寻址就像你知道书的确切位置并直接前往那个位置。而间接寻址就好比你首先需要询问图书管理员,管理员给你一个书架号,你随后去那个书架找到你的书。这样的间接方法允许更多的灵活性和抽象层次。
逻辑表示
用逻辑表示,一次间接寻址可以表示为 S=(E)=((D)),而二次间接寻址可以表示为 S=((E))=(((D)))。
6. 相对寻址方式
相对寻址通过形式地址与程序计数器的当前值相加来形成操作数的有效地址,允许代码在内存中的任何位置执行而不需要修改指令地址。这种寻址方式为程序的移动性和模块化提供了可能。
优势
相对寻址的主要优势在于它支持代码的可重定位性,即程序可以不受其物理位置影响地执行。
7. 变址和基值寻址方式
变址寻址和基值寻址方式通过将指令中的形式地址与变址寄存器或基值寄存器的内容相加来得到操作数的有效地址。它们广泛应用于循环和结构化编程中,允许在不修改指令本身的情况下动态调整地址。
区别
虽然变址和基值寻址在地址计算方法上相同,但在使用上有所不同。在基值寻址中,基值寄存器提供基数,指令提供偏移量;而在变址寻址中,变址寄存器通常提供变动量,指令提供基数。
8. 复合寻址方式
复合寻址方式结合了间接寻址和相对或变址寻址,它可以先进行间接寻址来找到一个中间地址,然后在此基础上应用相对或变址逻辑来确定最终的操作数地址。
类型
- 变址间接式:先计算形式地址和变址寄存器内容的和,然后进行间接寻址。
- 间接变址式:先进行间接寻址以获得一个中间地址,然后加上变址寄存器的内容。
这种灵活的寻址方式可以处理更复杂的数据结构和地址计算,提高程序的灵活性和处理能力。
9. 块寻址方式
块寻址经常应用于数据块的传输,如输入输出操作和内存中的数据块移动。这种方式涉及指定数据块的起始地址和长度,有时还包括终止条件,提高了大量数据处理的效率。
应用
块寻址方式的应用减少了单个数据传输的开销,尤其在需要移动大量数据时,这种方式显著提高了传输效率。
10. 段寻址方式
概念和结构
段寻址是Intel 8086和8088处理器的特色之一,它们通过20位地址来访问存储器,从而提供1MB的直接寻址能力。这种处理器设计与其内部16位的算术逻辑单元(ALU)和寄存器体系结构紧密相关,限制了单次寻址的最大范围是64KB。
实现机制
在段寻址中,1MB的内存被划分为多个64KB的段。每个段可以通过段寄存器来访问,它们在物理上表示存储器的基地址。寻址过程中,CPU中的段寄存器内容(段基址)会左移4位,然后加上16位的偏移地址来形成最终的20位物理地址。
寻址过程
- 段基址:由段寄存器提供,代表了64KB内存块的开始地址。
- 偏移量:通常由其他寄存器提供,指示在所选内存段内的具体位置。
- 物理地址计算:段基址左移4位(相当于乘以16),与偏移量相加,得到20位的物理地址。
示例图解
如图4.6所示,在段寻址模式下,内存地址的确定是基值寻址的实质表现:段基址和偏移地址共同工作,精确定位到内存的一个具体单元。
段寻址的优势
段寻址方式有如下几点优势:
- 内存分割:通过划分内存段,段寻址有助于内存的组织和管理。
- 有效扩展:尽管CPU的寄存器是16位的,但段寻址机制有效扩展了物理地址空间至20位。
- 模块化编程:程序可以按段进行组织,提高了代码的可读性和模块化。
- 保护和隔离:每个内存段可以具有不同的访问权限,从而提高了程序运行的安全性。
结论
段寻址是基值寻址的一种特殊形式,它适用于16位处理器体系结构,而且成功地在保持兼容性的同时扩展了地址空间。这种寻址方式对于操作系统和应用程序而言,意味着更高的灵活性和更有效的内存利用,也是许多高级编程技术的基础,如内存分页和保护模式等。了解和掌握段寻址方式,对于那些依然在使用这类处理器的系统来说,仍然极具价值。
总结
操作数的各种寻址方式提供了不同的策略来适应程序设计中的各种需求,从最简单的直接寻址到复杂的复合寻址。了解这些寻址方式的原理和应用,对程序员来说至关重要,因为这影响着程序的组织、优化和最终执行效率。每种寻址方式都有其独特的用途,合理利用这些方法,可以显著提升程序设计和系统性能。
三、寻址方式举例
1. PDP/11系列机寻址方式
PDP/11系列机采用的是一个多样化的寻址模式,提供了多种方式来计算或确定操作数的有效地址。
指令格式
PDP/11的指令格式分为单操作数和双操作数指令,其操作数地址部分均由6位构成,分别代表寻址方式和寄存器号。
寄存器应用
在PDP/11的8个可编程寄存器中,R0至R5可作为通用寄存器,而R6和R7有特定的用途——分别作为堆栈指针(SP)和程序计数器(PC)。
寻址特征
PDP/11提供了8种寻址方式,通过3位寻址特征位来指定。这些方式包括直接寻址、寄存器寻址、自增寻址、自减寻址、变址寻址、寄存器间接寻址、自增间接寻址和自减间接寻址等。
汇编符号
汇编语言使用汇编符号来表示操作码和地址,使得编写程序比直接使用机器语言更为方便。每种寻址方式和寻址特征在汇编语言中都有对应的符号表示。
寻址方式表
PDP/11系列机的寻址方式举例如下:
- 寄存器型(Register mode):操作数直接在寄存器中。
- 自增型(Autoincrement mode):使用寄存器值作为地址,然后寄存器自增。
- 直接型(Direct mode):操作数地址由寄存器加指令中的位移量形成。
- 变址型(Indexed mode):类似于直接型,但增加了变址寄存器的内容。
这些寻址方式为程序员提供了强大的工具来执行复杂的数据操作和流程控制,特别是在处理数组、循环结构和条件分支时。
结论
PDP/11系列机的寻址方式表现出了早期计算机架构的复杂性和灵活性。通过这些机器的寻址方式,我们可以理解现代计算机架构如何发展出更为高效和直观的寻址策略。尽管如此,汇编语言的依赖于特定机器的特性,意味着它并不具有跨平台的通用性,这限制了其在不同计算机架构之间的可移植性。而了解这些寻址方式不仅有助于我们理解早期计算机如何工作,也为现代计算机编程和体系结构的学习提供了宝贵的历史背景。
1) 指令格式与寻址方式特点分析
MOV S,D 指令
- 指令格式:单字长二地址指令,即两个操作数都在指令中直接给出。
- 寻址方式:RR型,意味着两个操作数都来自于寄存器,这种指令不需要访问内存,因此执行速度很快。
STA S,M 指令
- 指令格式:双字长二地址指令,源操作数来自寄存器,目的操作数位于存储器中。
- 寻址方式:RS型,S操作数可以通过基址寻址或变址寻址获取,而目标寄存器R直接在指令中指定。
LDA M,D 指令
- 指令格式:双字长二地址指令,源操作数是一个存储器地址,目标操作数是一个寄存器。
- 寻址方式:RS型,目标操作数D是寄存器中的直接寻址,而源操作数M是20位的存储器直接寻址。
(2) 操作时间分析
- 最短时间操作:
MOV S,D
指令将花费最少的时间执行,因为它是寄存器到寄存器的操作,不需要存储器访问或地址计算。 - 最长时间操作:
STA S,M
指令可能花费最长时间,因为它不仅需要存储器访问,还涉及到额外的地址计算。 - 相等时间操作:
STA S,M
指令的执行时间通常不会等于LDA M,D
,因为即便LDA
指令涉及存储器访问,但没有额外的地址计算开销。
(3) 十六进制指令字分析
① (F0F1)H (3CD2)H
- 指令分析:这是一个
LDA
指令,格式和编码都正确。 - 操作含义:从主存地址
3CD2
中读取数据到寄存器15
。
② (2856)H
- 指令分析:这是一个
MOV
指令,格式和编码都正确。 - 操作含义:将寄存器
5
的内容移动到寄存器6
。
③ (6FD6)H
- 指令分析:由于没有给出相应的寻址特征位和操作码对照表,无法判断此指令的正确性。假定
28D6
H是正确的MOV指令代码,则此指令可能存在编码错误。
④ (1C2)H
- 指令分析:同样,由于缺少完整的操作码对照表,我们无法判断此指令的正确性。如果
28C2
H是正确的MOV指令代码,那么可能需要将(1C2)H
改正为(28C2)H
。
在进行这类分析时,理解指令格式和寻址方式对于预测执行时间和指令解码至关重要。正确的分析依赖于对特定计算机架构和指令集的深入理解。