在计算机组成原理的知识体系里,一条机器指令由两个基本部分组成:操作码字段和地址码字段。操作码指明这条指令要执行什么操作,比如加法、减法、传送、跳转;地址码则指明操作的对象在哪里。而寻址方式,通俗地讲,就是指令通过怎样的规则,把地址码字段里给出的那个数值,转换成操作数真正存放位置的机制。教材的标准表述是:寻址方式是指令系统中规定如何获取操作数有效地址的方法,它决定了形式地址如何转化为有效地址。
这里必须先厘清三组容易混淆的概念。第一组是形式地址与有效地址。形式地址就是指令的地址码字段里直接写出来的那个数字,也叫地址码;有效地址是经过寻址方式转换后,真正指向操作数存储单元的地址。在立即数寻址中,形式地址本身就是操作数,不存在有效地址;在直接寻址中,形式地址就等于有效地址;而在间接寻址、变址寻址、基址寻址、相对寻址中,形式地址必须经过一次或多次运算,才能得到有效地址。第二组是指令寻址与数据寻址。指令寻址解决的是下一条要执行指令的地址如何确定的问题,分为顺序寻址和跳跃寻址两种;数据寻址解决的是本条指令的操作数地址如何确定的问题,也就是我们通常讨论的寻址方式。软考题目里说的"寻址方式",绝大多数情况下指的是数据寻址。第三组是操作数在什么位置。操作数可以存放在指令本身、CPU内部的寄存器、主存单元、堆栈,甚至通过输入输出端口获取,寻址方式的种类正是围绕操作数可能存放的这些位置展开的。
理解寻址方式,还要抓住指令系统的设计逻辑。计算机设计者之所以要设计出这么多种寻址方式,根本目的有三个:一是扩大寻址范围,让有限长度的地址码字段能够访问到更大的地址空间;二是缩短指令字长,减少指令占用的存储空间;三是支持程序设计的灵活性,为循环、数组、子程序调用、程序重定位等高级语言的编译实现提供硬件支撑。这三个目的贯穿了每一种寻址方式的设计动机,也是命题人反复设问的逻辑起点。
还有一个必须提前建立的整体认识,就是寻址方式的分类维度。按照操作数所处位置的不同,寻址方式可以划分为几个大的家族:操作数在指令内部的,是立即数寻址;操作数在CPU寄存器内部的,是寄存器寻址和寄存器间接寻址;操作数在主存中的,则涵盖直接寻址、间接寻址、变址寻址、基址寻址、相对寻址等。按照地址转换的复杂程度,又可以分为不转换的立即数寻址、直接转换的直接寻址、以及需要一次或多次算术运算的变址寻址、基址寻址和相对寻址。这两条分类线索交叉起来,就能把零散的寻址方式组织成一张清晰的知识地图,避免在复习时出现张冠李戴、顾此失彼的情况。命题人在设计综合题时,也往往沿着这两条线索出题,要求考生既会归类,又会计算。
要理解寻址方式的原理,必须先看清一条指令的物理结构。一条典型的指令由操作码字段、寻址方式字段和地址码字段三部分构成。操作码字段占据指令的高位若干位,其位数决定了这台机器最多能支持多少条不同的指令;寻址方式字段用于指明本条指令采用哪种寻址方式,在变长指令格式中可能不存在单独字段,而是通过操作码隐式约定;地址码字段存放形式地址,它的位数直接限制了直接寻址的最大范围。
根据地址码字段的个数,指令可以分为零地址指令、一地址指令、二地址指令、三地址指令和四地址指令。零地址指令没有显式的地址码,操作数隐含在特定的位置,比如堆栈操作指令,操作数隐含在栈顶,还有空操作指令。一地址指令只有一个地址码,对于双目运算,另一个操作数隐含在累加器中。二地址指令是最常见的形式,两个地址码分别指向源操作数和目的操作数,运算结果存入其中一个操作数地址。三地址指令把两个源操作数和结果地址都显式给出,指令字长较长,但表达能力强,常用于RISC架构。四地址指令则额外给出了下一条指令的地址,现已很少使用。
寻址方式要解决的核心问题,可以概括为一句话:给定形式地址,如何求出操作数的有效地址,进而读出操作数。在这个框架下,每一种寻址方式的差异,本质上是"形式地址与有效地址之间是什么关系"的差异。如果是恒等关系,就是直接寻址;如果形式地址是操作数本身,就是立即数寻址;如果形式地址指向的存储单元里存放的才是有效地址,就是间接寻址;如果有效地址等于形式地址加上某个寄存器的内容,就属于寄存器变址或基址的范畴。
还有一个必须明确的维度是"访问内存的次数"。不同寻址方式在获取操作数时,对主存的访问次数不同,这直接决定了指令的执行速度。立即数寻址不需要访问主存取操作数;寄存器寻址操作数在寄存器中,也不需要访问主存;直接寻址需要访问主存一次取出操作数;一次间接寻址需要访问主存两次,第一次取出有效地址,第二次取出操作数;两次间接寻址则需要访问主存三次。命题人非常喜欢就"访问内存次数"这个点设题,因为它能把抽象的寻址方式落实为可计算的执行开销。
如果把各种寻址方式统一到一个数学模型里,有效地址的求取可以归纳为一条通用规则:有效地址等于形式地址与相关寄存器内容的一次或多次算术组合。立即数寻址是特例,操作数直接等于形式地址;直接寻址是形式地址直接作为有效地址;间接寻址是有效地址等于形式地址所指向存储单元的内容;寄存器间接寻址是有效地址等于寄存器内容;变址寻址是有效地址等于变址寄存器的内容加上形式地址;基址寻址是有效地址等于基址寄存器的内容加上形式地址;相对寻址是有效地址等于程序计数器的内容加上形式地址。从形式上看,变址寻址、基址寻址、相对寻址的运算公式惊人地相似,都是"寄存器加形式地址",这正是命题人设置迷惑选项的温床,必须结合三者的设计目的加以区分。
立即数寻址是操作数直接包含在指令中的寻址方式,形式地址字段里存放的就是操作数本身。它的突出优点是速度快,因为操作数随指令一起被取出,取指之后操作数已经就绪,完全不需要再访问主存。它的缺点也很明显:由于操作数受限于地址码字段的位数,能表示的立即数范围很小,只能用于表示较小的常量。立即数寻址的典型应用场景是给寄存器赋初值、给累加器加一个小常数、设置循环的初始步长等。软考题目中,判断一条指令是否属于立即数寻址,关键看操作数是不是直接写在指令里,凡是"操作数在指令中"的表述,指的都是立即数寻址。
直接寻址是最简单直观的一种方式,地址码字段直接给出操作数的有效地址,取指后直接用这个地址访问主存就能拿到操作数。它的优点是简单、速度快,访问主存一次即可;缺点是寻址范围受地址码字段位数的严格限制,地址码字段只有八位,就只能访问二百五十六个存储单元,无法访问大容量的内存空间。
间接寻址则是在直接寻址的基础上加了一层间接关系,地址码字段给出的是一个存储单元的地址,这个存储单元里存放的内容才是操作数的有效地址。间接寻址最大的价值在于扩大了寻址范围,因为用来存放有效地址的存储单元可以是整个机器字长,比如机器字长三十二位,那么间接寻址就能访问整个四吉字节的地址空间,远远突破地址码字段八位、十六位的限制。间接寻址的代价是速度变慢,一次间接寻址要访问主存两次。它还可以实现地址的间接传递,为子程序返回、指针、链表的硬件实现提供便利。命题人在考查间接寻址时,最常见的问法就是"操作数的有效地址存放在哪里"以及"需要访问几次内存"。
值得补充说明的是,间接寻址还支持多级间接,即第一次间接得到的仍然是一个地址而不是操作数,需要再次间接才能得到真正的操作数。多级间接寻址用地址单元最高位作为间址标志位,当标志位为一表示继续间接,当标志位为零表示已经得到有效地址。这种设计进一步拓展了寻址的灵活性,但每多一级间接,就要多访问一次主存,执行速度也随之下降。软考题目一般只考查一次间接寻址,考生掌握一次间接寻址的访问次数即可,但理解多级间接的原理有助于加深对间接寻址机制的整体把握。
寄存器寻址的操作数存放在CPU内部的通用寄存器中,地址码字段给出的是寄存器编号。由于寄存器数量通常很少,用三五位就能编码完毕,所以地址码字段可以很短,指令字长因此大大缩短。同时操作数在寄存器中,不需要访问主存,速度快。寄存器寻址是现代计算机最常用、最高效的
本篇完!