要讲清楚指令寻址方式,必须先把"寻址"这两个字拆开看。在计算机体系结构中,寻址方式指的是处理器在执行一条指令时,如何根据指令中给出的地址码字段,确定操作数实际存放位置的方法。这里的"址"可以是主存单元的地址,可以是寄存器的编号,也可以是直接内嵌在指令中的那个数值本身。软考官方教材对寻址方式的定义落脚点通常是这样一句话:寻址方式决定了指令中地址码字段与实际操作数之间的映射关系,也就是从"指令里写的那串地址"到"真正要运算的那个数"之间,究竟走了一条什么样的路径。
一条典型的机器指令由操作码字段和地址码字段两部分构成。操作码告诉处理器"做什么",比如加法、减法、取数、跳转;地址码字段则告诉处理器"对谁做",也就是操作数在哪里。问题在于,地址码字段的位数是有限的,而处理器能够访问的存储空间往往要大得多,同时程序员又希望指令能够灵活地操作寄存器、内存、立即数等不同来源的数据。这个"有限位数"与"灵活需求"之间的矛盾,正是寻址方式诞生的根本原因。
从指令周期的角度看,寻址方式的作用贯穿取指与执行两个阶段。取指阶段解决的是"下一条指令从哪里来"的问题,执行阶段解决的才是"操作数从哪里来"的问题,这两个层次合在一起,构成了完整的寻址概念。软考教材在展开寻址方式之前,往往会先交代指令的基本格式,因为寻址方式归根结底是对指令地址码字段的解释规则,脱离指令格式谈寻址方式是无源之水。考生需要理解的是,同一条指令的地址码字段,在不同的寻址方式下会被处理器做完全不同的解释:它有时是一个常数,有时是一个内存地址,有时是一个寄存器编号,有时只是需要参与加法运算的一个偏移量。这种"同一字段、多种解释"的机制,正是计算机指令系统设计灵活性的体现。
从指令周期的角度看,寻址方式的作用贯穿取指与执行两个阶段。取指阶段,处理器主要解决"下一条指令在哪里"的问题,这对应的是指令寻址,通常由程序计数器配合顺序执行或转移指令来完成;执行阶段,处理器才真正进入"操作数寻址",也就是本篇文章重点讨论的对象。软考命题人在出题时,绝大多数情况都在考操作数寻址方式,因此考生必须把注意力集中在这一层。指令寻址相对简单,核心就两个词:顺序寻址与跳跃寻址,前者靠程序计数器自动加一实现,后者靠转移类指令改写程序计数器的值实现。
理解寻址方式的底层原理,核心是抓住一个概念:有效地址。有效地址指的是操作数在主存中真正存放的那个单元的地址。不同的寻址方式,本质上是"有效地址的计算公式"不同,以及在计算过程中"要不要访问内存、访问几次内存"不同。这句话是整个寻址方式知识体系的纲,抓住了它,所有寻址方式都可以归结到同一个分析框架里。
以直接寻址为例,指令地址码字段里写的就是操作数在主存中的地址,那么有效地址就等于地址码字段本身,访问内存一次即可取出操作数。以间接寻址为例,指令地址码字段里写的是一个"地址的地址",处理器先按这个地址访问一次内存,取出真正的有效地址,再按有效地址访问第二次内存才能拿到操作数。可见,同样是找操作数,直接寻址与间接寻址在内存访问次数上差了整整一次,这就是它们速度差异的根源。
把握有效地址这个概念还有一个实际价值,那就是它能让考生在遇到基址、变址、相对寻址这类"形式地址不等于有效地址"的方式时保持清醒。所谓形式地址,指的是指令地址码字段里直接写出来的那个值;所谓有效地址,指的是经过寻址计算之后真正指向操作数的那个地址。在直接寻址里,形式地址与有效地址是同一个值,所以很多考生会形成思维定式,以为所有寻址方式里两者都相等。一旦遇到变址寻址,需要把形式地址与变址寄存器的内容相加才能得到有效地址,这种定式就会导致计算错误。因此,把"形式地址"与"有效地址"两个概念分开,是整个寻址方式学习过程中必须跨过的一道认知门槛。
从数据通路的视角看,寻址方式的实现离不开几个关键寄存器的协作。程序计数器负责指出下一条指令的地址,指令寄存器暂存刚取出的指令,存储器地址寄存器负责把地址送到地址总线,存储器数据寄存器则暂存从内存读出的数据或待写入的数据。寻址方式本质上规定了这些寄存器之间数据流动的先后顺序。立即寻址之所以最快,是因为操作数就嵌在指令里,取出指令的同时操作数也就到齐了,根本不需要地址总线的参与;寄存器寻址次之,因为操作数放在CPU内部的寄存器中,只需给出寄存器编号即可,无需访存;凡是需要访问主存的寻址方式,速度必然排在后面,而访问次数越多越慢。这条"速度排序"规律,是软考选择题最爱考的点之一。
寻址方式的分类是软考考查的主战场,教材通常将其归纳为若干种基本类型。为了便于记忆,可以按照"操作数来源"这个维度,把常见的寻址方式分为三大类:操作数直接藏在指令里或寄存器里的,属于第一类;操作数地址直接写在指令里或寄存器里的,属于第二类;操作数地址需要经过某种计算才能得到的,属于第三类。下面逐一展开。
立即寻址是最简单也最快的一种方式,它的操作数直接包含在指令中,取出指令的同时操作数就已经就位。比如一条指令的地址码字段直接写了个常数一百,那么这条指令执行时用的就是一百这个数,不需要再去内存找。立即寻址的优点是快,缺点是操作数是固化在指令里的,程序运行期间无法改变,因此只适合那些在编程时就已知的常量。软考常把立即寻址与另外两种方式放在一起做速度排序,正确答案是立即寻址最快、寄存器寻址次之、直接寻址最慢,很多考生因为记不清顺序而丢分。
寄存器寻址的操作数存放在CPU内部的通用寄存器中,指令地址码字段给出的是寄存器的编号。由于寄存器在CPU内部,访问速度远快于主存,所以寄存器寻址也很快,而且寄存器编号位数短,能够缩短指令长度。寄存器寻址在现代处理器中被大量使用,因为绝大多数运算的操作数都被加载到寄存器后再参与运算。与立即寻址相比,寄存器寻址的操作数在运行期间可以改变,灵活性更好。需要补充的是,寄存器寻址还有一个隐性优势,那就是它不需要访问主存,因此不会受到主存带宽和存取周期的制约,这对于提高指令执行的整体吞吐率很有帮助。在软考题目中,寄存器寻址常与寄存器间接寻址一同出现,考生要能准确区分:前者寄存器里装的是操作数本身,后者寄存器里装的是操作数的地址,一个是"数在寄存器",一个是"地址在寄存器",两者虽然都涉及寄存器,但访存行为完全不同。
直接寻址的指令地址码字段给出的就是操作数在主存中的有效地址,处理器按这个地址访存一次即可取出操作数。直接寻址的优点是直观,指令含义清楚;缺点是地址码字段位数限制了可寻址的范围,当主存容量很大时,指令里的地址码字段可能不够用。软考题目中直接寻址常作为速度排序里的"最慢"选项出现,但这只是相对于立即寻址和寄存器寻址而言,实际上在需要访存的寻址方式里,直接寻址只访存一次,并不算慢。
间接寻址的指令地址码字段给出的是操作数地址的地址,也就是一个指向"存放有效地址的那个存储单元"的指针。处理器需要先访存一次取出有效地址,再访存一次取出操作数,共访存两次,因此速度比直接寻址慢。间接寻址的价值在于灵活性:它允许程序在运行期间改变有效地址,而不必修改指令本身,这在实现地址表、子程序返回、链表遍历等场景中非常有用。软考命题人常利用"间接寻址访存次数多"这一点设置速度排序或访存次数判断的陷阱。
寄存器间接寻址是间接寻址的一种特例,区别在于存放有效地址的不是主存单元,而是寄存器。指令地址码字段给出寄存器编号,该寄存器里存的是操作数的有效地址,处理器先读寄存器拿到地址,再访存一次取出操作数。它只访存一次,比普通间接寻址快,又保留了运行期间可改变地址的灵活性,因此在计算机组成原理中地位很高。
变址寻址的典型形态是:把指令地址码字段给出的形式地址,与某个变址寄存器的内容相加,得到有效地址。变址寻址主要服务于数组这一类成片数据的处理,处理器只需修改变址寄存器的值,就能让同一条指令依次访问数组中的不同元素,这在循环处理中能大幅减少指令数量。软考题目常用数组遍历的例子来考变址寻址的用途。
基址寻址与
本篇完!