3.2 寻址方式

在指令系统中,操作数是一个重要的组成部分,它指出了参加运算的数或数所在的单元地址。而如何找到这个操作数就称为寻址方式。寻址方式越多,则计算机的功能越强,灵活性亦越大,但指令系统也就越复杂。

寻址方式是汇编语言程序设计中最基本的内容之一,必须十分熟悉,牢固掌握。在第2章中,已介绍过89C51单片机系统的存储器分布,在学习寻址方式时,要特别注意在各种不同的存储区中,分别可以采用什么寻址方式。

89C51单片机提供了7种寻址方式,下面分别介绍。

3.2.1 立即寻址

所谓立即寻址就是操作数在指令中直接给出。通常把出现在指令中的操作数称为立即数,为了与直接寻址指令中的直接地址相区别,在立即数前面加“#”标志。例如:

        MOV  A,# 3AH

其中3AH就是立即数,该指令功能是将3AH这个数本身送入累加器A中。

3.2.2 直接寻址

在指令中直接给出操作数地址,这就是直接寻址方式。此时,指令的操作数部分就是操作数的地址。例如:

        MOV  A,3AH

其中3AH就是表示直接地址,其操作示意图如图3-1所示,该指令功能是把内部RAM地址为3AH单元中的内容68H传送给累加器A。

图3-1 直接寻址示意图

直接寻址方式可访问以下存储空间:

(1)内部RAM低128个字节单元,在指令中直接地址以单元地址的形式给出;

(2)特殊功能寄存器。

对于特殊功能寄存器,其直接地址还可以用特殊功能寄存器的符号名称来表示。

应注意,直接寻址是访问特殊功能寄存器的唯一方法。

3.2.3 寄存器寻址

寄存器寻址就是以寄存器的内容作为操作数。因此在指令的操作数位置上指定了寄存器就能得到操作数。采用寄存器寻址方式的指令都是一字节的指令,指令中以符号名称来表示寄存器。例如:

        MOV  A,R0
        MOV  R2,A

以上两条指令都是属于寄存器寻址。前一条指令是将R0寄存器的内容传送到累加器A。后一条是把累加器A中的内容传送到R2寄存器中。

由于寄存器在CPU内部,所以采用寄存器寻址可以获得较高的运算速度。能实现这种寻址方式的寄存器有:R0~R7、A、AB寄存器和数据指针DPTR。

3.2.4 寄存器间接寻址

所谓寄存器间接寻址就是以寄存器中的内容作为RAM地址,该地址中的内容才是操作数。寄存器间接寻址也需在指令中指定某个寄存器,也是以符号名称来表示寄存器的,为了区别寄存器寻址和寄存器间接寻址,用寄存器名称前加“@”标志,来表示寄存器间接寻址。例如:

        MOV  A,@R0

其操作示意图如图3-2所示。

图3-2 寄存器间接寻址示意图

这时R0 寄存器的内容 3AH 是操作数地址,内部 RAM的3AH单元的内容65H才是操作数,并把该操作数传送到累加器A中,结果(A)=65H。若是寄存器寻址指令:

                            MOV  A,R0

则执行结果(A)=3AH。对这两类指令的差别和用法,一定要区分清楚。间接寻址理解起来较为复杂,但在编程时是极为有用的一种寻址方式。

89C51单片机规定只能用寄存器R0、R1、DPTR作为间接寻址的寄存器。间接寻址可以访问的存储空间为内部RAM和外部RAM。

(1)内部RAM的低128个单元采用R0、R1作为间址寄存器。

(2)外部RAM的寄存器间接寻址有两种形式:一是采用R0、R1作为间址寄存器,可寻址256个单元;二是采用16位的DPTR作为间址寄存器,可寻址外部RAM的整个 64 KB地址空间。

对于89C52单片机,其内部RAM是256个字节,其高128个字节与特殊功能寄存器的地址是重叠的,两者由不同的寻址方式加以区分。对89C52的高128B RAM,必须采用寄存器间接寻址方式访问。

3.2.5 变址寻址

变址寻址是以DPTR或PC作为基址寄存器,以累加器A作为变址寄存器(存放地址偏移量),并以两者内容相加形成的16位地址作为操作数地址。例如:

        MOVC  A,@A+ DPTR   ;A ← ((A)+ (DPTR))
        MOVC  A,@A+ PC     ;A ← ((A)+ (PC))

第一条指令的功能是将A的内容与DPTR的内容相加形成操作数的地址(即程序存储器的 16 位地址),把该地址中的内容送入累加器 A中,如图3-3所示。第二条指令的功能是将 A的内容与PC的内容相加形成操作数的地址(ROM16 位地址),把该地址中的内容送入累加器A中。

图3-3 变址寻址示意图

这两条指令常用于访问程序存储器中的数据表格,且都为一字节指令。

3.2.6 相对寻址

相对寻址只在相对转移指令中使用,指令中给出的操作数是相对地址偏移量rel。相对寻址就是将程序计数器PC的当前值与指令中给出的偏移量rel相加,其结果作为转移地址送入PC中。此种寻址方式的操作是修改PC的值,故可用来实现程序的分支转移。

PC当前值是指正在执行指令的下条指令的地址。rel是一个带符号的8位二进制数,取值范围是-128~+127,故rel给出了相对于PC当前值的跳转范围。例如:

                                      SJMP  54H

这是无条件相对转移指令,是双字节指令,指令代码为80H、54H,其中 80H是该指令的操作码,54H是偏移量。现假设此指令所在地址为 2000H,执行此指令时,PC当前值为 2000H+02H,则转移地址为2000H+02H+54H=2056H。

故指令执行后,PC的值变为2056H,程序的执行发生了转移。其寻址方式如图3-4所示。

图3-4 相对寻址示意图

3.2.7 位寻址

89C51单片机有位处理功能,可对寻址的位单独进行操作,相应的在指令系统中有一类位操作指令,它们可以采用位寻址方式。在指令的操作数位置上直接给出位地址,这种寻址方式被称为位寻址。例如:

        MOV  C,30H

该指令的功能是把位地址30H中的值(0或1)传送到位累加器CY中。

89C51单片机内部RAM有两个区域可以位寻址:一个是位寻址区20H~2FH单元的128位,另一个是字节地址能被8整除的特殊功能寄存器的相应位。

在89C51单片机中,位地址的表示可以采用以下几种方式。

(1)直接使用位地址。对于 20H~2FH共 16 个单元的 128 位,其位地址是 00H~7FH,例如,20H单元的0~7位的位地址为00H~7H,而特殊功能寄存器的可寻址的位地址见表2-3。

(2)用单元地址加位序号表示。如25H.5表示25H单元的D5位(位地址是2DH),而PSW中的D3可表示为D0H.3,这种表示方法可以避免查表或计算,比较方便。

(3)用位名称表示。特殊功能寄存器中的可寻址位均有位名称,可以用位名称来表示该位,如可用RS0表示PSW中的D3——D0H.3。

(4)对特殊功能寄存器可直接用寄存器符号加位序号表示。如PSW中的D3,又可表示为PSW.3。

习惯上,对于特殊功能寄存器的寻址位常使用位名称表示其位地址。