主存储器寻址是所有计算机系统中都普遍采用的一类寻址方式,其寻址种类也最为复杂。主存储器寻址的指令格式主要有:
  OPC M
  OPC M, M
  OPC M, M, M
  主存储器寻址的基本类型有直接寻址方式、间接寻址方式和变址寻址等三种。对于后两种寻址方式,还有一些特殊的寻址方式。我们仍然假设有效地址为EA,在指令的地址码字段中给出的地址为A,变址寄存器为X,地址的增量为d。对于各种主存储器寻址方式,分别叙述如下:
  1.直接寻址方式
  直接寻址方式是在指令中直接给出参加运算的操作数或存放运算结果的主存地址,即在指令中直接给出有效地址。
  有效地址:EA = A
  在早期生产的计算机及目前的某些专用计算机中用得比较多。随着主存储器容量的不断扩大及虚拟存储器的普及,这种寻址方式暴露出了许多弱点。
  首先,它需要很长的地址码,特别在二地址及三地址指令中,这一矛盾更为突出。通常的小型及微型计算机,表示一个主存地址要二进制30位左右,因此,有限长度的指令无法容纳如此长的地址码。
  其次,为了实现程序循环及高效处理数组运算等,程序设计中修改数据的地址是必不可少的。采用直接寻址方式编写的程序,如果要修改数据地址就必须修改程序中的指令本身,采用这种方法编写的程序没有再入性,这是现代程序设计思想所不能接受的。
  另外,目前使用的操作系统多为多任务或多用户系统,采用直接寻址方式编写的程序会给操作系统的作业调度带来极大的不便,因为,多任务及多用户操作系统要求程序能够在主存中浮动,所以,必需要有其它寻址方式来支持。
  2.间接寻址方式
  间接寻址方式在指令中给出的是操作数地址的地址,或者是目的地址的地址,必须先访问一次主存储器才能得到有效地址。
  有效地址:EA=(A)或EA=@A
  3.变址寻址方式
  采用变址寻址方式时,需要设置一个或多个变址寄存器。变址寄存器的长度由主存储器的寻址空间决定,例如,主存储器的寻址空间为4GB,则变址寄存器的长度需要32位。也可以把某一个或几个通用寄存器兼作变址寄存器来使用。变址寄存器的主要作用是用来存放数组的基地址。
  有效地址:EA = A +(X)
  在指令中给出变址寄存器的编号(如果只有一个变址寄存器,可以隐含)和地址的偏移量。
  当指令在执行时,用一个硬件加法器,把变址寄存器中给出的基地址与指令中给出的地址偏移量作算术加法,相加的结果就是有效地址。
  间接寻址方式与变址寻址方式的设计目标都是为了解决操作数地址的修改问题。它们都能做到,在程序设计过程中能够对操作数的地址进行修改,而不必去修改程序中的指令本身。例如,对于数组运算,通常要用一个循环程序对数组中的各个元素进行操作,如果数组的各个元素存放在一个连续的内存空间中,在不允许修改程序的前提下,必须通过修改操作数的地址才能连续访问到数组中的数据。
  原则上,在一台计算机系统中,只需要设置间接寻址方式与变址寻址方式中的任何一种即可。例如,在IBM公司生产的大中型计算机系统中,只有变址寻址方式,没有间接寻址方式。在许多小型及微型计算机系统中,只有间接寻址方式,没有变址寻址方式。也有一些计算机系统,间接寻址方式和变址寻址方式两种都有。
  那么,就会提出这样一个问题:在一台计算机系统中,如何选择间接寻址方式与变址寻址方式?他们各有什么优点与缺点?下面,我们通过一个简单的例子,分析这两种寻址方式的特点。
  例3.1:一个由N个元素组成的数组,已经存放在主存储器的连续存储单元中,现要把它搬到主存储器的另一个连续的存储单元中,源数组的起始地址为AS,目标数组的起始地址是AD,不必考虑可能出现的存储单元的重叠问题。为了编程简单,采用一般的两地址指令编写程序。
  首先,用间接寻址方式编写程序如下:
  START:MOVE ASR, ASI ;保存源数组的起始地址,为了程序有在入性
     MOVE ADR, ADI ;保存目标数组的起始地址
     MOVE NUM, CNT ;保存数据的个数
  LOOP: MOVE @ASI, @ADI ;用间接寻址方式传送数据
     INC ASI ;源数组的地址增量
     INC ADI ;目标数组的地址增量
     DEC CNT ;个数减1
     BGT LOOP ;测试N个数据是否传送完
     HALT ;停机
  ASR: AS ;源数组的起始地址
  ADR: AD ;目标数组的起始地址
  NUM: N ;需要传送的数据个数
  ASI: 0 ;当前正在传送的源数组地址
  ADI: 0 ;当前正在传送的源数组地址
  CNT: 0 ;剩余数据的个数
  为了程序具有再入性,前3条指令是必须的,数据存放单元要分别重复设置一份也是必须的。
然后,用变址寻址方式编写程序如下:
  START:MOVE AS, X ;把数组的起始地址送入变址寄存器
     MOVE NUM, CNT ;保存数据个数,为了程序具有再入性
  LOOP: MOVE (X), AD-AS(X) ;AD-AS为地址偏移量,在汇编时计算
     INC X ;增量变址寄存器
     DEC CNT ;个数减1
     BGT LOOP ;测试N个数据是否传送完成
     HALT ;停机
  NUM: N ;需要传送的数据个数
  CNT: 0 ;剩余数据的个数
  比较以上两个程序,可以很明显地看出,采用变址寻址方式编写的程序简单、易读。对程序员来说,两种寻址方式的主要差别如下:
  间接寻址方式:间接地址在主存储器中,没有偏移量。
  变址寻址方式:基地址在变址寄存器中,带有偏移量。
  由此产生的两种寻址方式的优点与缺点是:
  (1) 实现的难易程度。间接寻址方式实现起来很容易,只需要增加一条从主存储器的数据寄存器到地址寄存器的数据通路即可。实现变址寻址方式需要增加较多的硬件,需要一个硬件的加法器,一个或多个变址寄存器(也可以与通用寄存器合用)。
  (2) 指令的执行速度。采用间接寻址方式编写的程序,执行速度很慢。读写一个操作数至少需要访问两次主存储器,第一次访问主存储器读取有效地址,第二次访问主存储器才是读或写操作数。
  执行上述程序中的MOVE @AS, @AD这条指令,至少需要访问主存储器5次,其中,第一次访问主存储器,读取指令本身,第二、第三次访问主存储器读到源操作数,再经过两次访问主存储器操作,才能把数据送入主存储器的目标地址单元中。
  采用变址寻址方式编写的程序,执行速度比较快。有效地址通过硬件加法器直接产生,不需要访问主存储器。如执行上述程序中的MOVE (X), AD-AS(X) 这条指令,只需要访问主存储器3次。
  (3)对数组运算的支持。变址寻址方式比较好,间接寻址方式较差,这是因为变址寻址方式可以带有偏移量。基地址加偏移量能够很有效地表示向量、矩阵等数据。