图2-15 寄存器寻址示意图
(2) 直接寻址
直接寻址指令的指令码中含有操作数地址。该地址通常可以是8位二进制数。常处于指令码中的第二或第三字节。机器执行它们时便可根据直接地址找到所需要的操作数。
在MCS-51单片机中,可以用于直接寻址的存储空间主要有片内RAM的低128字节和特殊功能寄存器SFR(8052片内RAM的高128字节只能被间接寻址)。在这类寻址方式的指令中,直接地址通常采用direct(或addr11或addr16)表示。例如,8位数传送指令MOV A, direct中的源操作数就是采用直接寻址的,其操作码为E5 direct。但在这条指令的实际使用中或将它的汇编成机器码时,direct必须采用实际操作数的物理地址。例如,若用3AH代替上述指令中的direct,则指令变为
MOV A, 3AH ;A←(3AH)
该指令的操作码位E5H,处在指令的第一字节,3AH为直接寻址地址,处在指令的第2字节(见附录中的指令表)。指令的含义是把3AH中的内容88H送入累加器A中,如图2-16所示。
直接寻址指令颇多,使用时特别容易混淆。为此,特提出以下三点注意事项: 1) 指令助记符中的direct是操作数所在存储单元的物理地址,也可以使用SFR的名称符号。但提倡使用后者,因为这可以增强所编程序的可读性。不过,在汇编时仍应将它翻译成物理地址才能为机器所识别和执行。例如,如下两条指令: MOV A, SP ;A←SP MOV A, 81H ;A←(81H)
- 31 -
图2-16 直接寻址示意图
它们的形式虽然不同,但汇编后的指令码是完全一样的,均为E581H。在注释中,SP中的内容,81H加圆括号后表示81H中的内容。
2) 在MCS-51指令系统中,累加器有A、ACC和E0H等三种表示形式,分属于两种不同的寻址方法,但指令的执行效果是完全相同的。例如: INC A INC ACC INC 0E0H 其中:第一条指令是寄存器寻址,指令码为04H;第二条和第三条指令是直接寻址,指令码为05E0H,第三条指令中的物理地址E0H前面要加@凡以字母A-F开头的十六进制数均需加前导@。第三条指令的执行效果相同,都是使累加器A中的内容加1。
3) 在指令系统中,字节地址和位地址是有区别的,前者用direct表示,后者用bit表示。但在实际程序中,两者都要用十六进制数表示,因此使用中也容易混淆。例如:
MOV A, 20H ;A←(20H) MOV C, 20H ;Cy←(20H)
在第一条指令中,由于目标寄存器是累加器A,因此指令中的20H是字节地址direct,汇编时应汇编成E520H。第二条指令中由于目标寄存器是进位标志位C(即PSW.7),故它的20H属于位地址bit,相应20H中的内容是指20H单元中的最低位D0,汇编后的指令码为A220H。显然,两条指令的含义和执行效果是完全不同的。 (3) 立即寻址
立即寻址指令的特点是指令码中直接含有所需寻址的操作数。该操作数称为立即数,可以是二进制8位,也可以是二进制16位,常处在指令码的第二和第三字节位置上。
在指令的汇编形式中,立即数通常使用#data或#data16表示,其中#是它区别于direct(或bit)的惟一标志,读者使用时务必不要疏忽。例如:
- 32 -
MOV A, #3AH ;A←3AH MOV A, 3AH ;A←(3AH)
其中:第一条指令的源操作数是立即型寻址,3AH作为一个二进制数传送到累加器A中,指令码为743AH; 第二条指令的源操作数是直接寻址,3AH是作为地址看待的,指令的含义是把3AH中的内容送人累加器A。指令码为E53AH。
对于16位立即数指令,汇编时它的高8位应放在前面(即指令的第二字节位置),低位放在后面(即指令的第二字节位置)。例如,如下指令的指令码为901828H: MOV DPTR, #1828H ;DPTR←1828H (4) 寄存器间址
寄存器间址指令的特点是指令码中含有操作数地址的寄存器号。计算机执行这类指令时,它首先根据指令码中寄存器号找到所需要的操作数地址,再由操作数地址找到操作数,并完成相应操作。因此,寄存器间址实际上是—种二次寻找橾作数地址的寻址方式。
在汇编形式的指令中,间址寄存器采用@Ri或@DPTR表示。其中,R1或者是R0,或者是R1(即:i的取值为0或1),@是它区别于寄存器寻址的标记。例如: MOV A, R0 ;A←R0 MOV A, @R0 ;A←(R0)
其中:第—条指令是寄存器寻址,R0中为操作数,指令码为E8H;第二条指令是寄存器间址,R0中为操作数地址,不是操作数,指令码为E6H。两条指令的含义是截然不同的;第一条指令执行后累加器A中为3AH;第二条指令执行后累加器A中为操作数65H,如图2-17所示。
图2-17 寄存器间址寻址示意图
使用寄存器间址指令时,应注意如下两点: 1) 寄存器间址指令可以拓宽单片机寻址范围,
- 33 -
其中,@Ri用于对片内RAM的寻址(8052的地址范围为00H-7FH,8031/8051的地址范围为00H-7FH),也可以对片外RAM寻址范围可以覆盖片外ROM/RAM的全部64KB区域。
2) 寄存器间址指令不同于寻址特殊功能寄存器SFR。例如,如下程序是不能访问SP的:
MOV R0, #81H MOV A, @R0 (5) 变址寻址
MCS-51变址寻址指令具有以下3个特点:
1)指令操作码内隐含有作为基地址寄存器用的数据指针DPTR或程序计数器PC,其中DPTR或PC中应预先存放有操作数的基地址。 2)指令操作码内也隐含有累加器A,累加器A中应预先存放有被寻址操作数地址对基地址的偏移量,该地址偏移量应是一个00H-FFH范围内的无符号数。 3)在执行变址寻址指令时,单片机先把基地址(在DPTR或PC内)和地址偏移量(累加器A中)相加,以形成操作数地址。 MCS-51单片机有如下两条变址寻址指令: MOVC A, @A+PC ;A←(A+PC) MOVC A, @A+DPTR ;A←(A+DPTR)
第—条变址寻址指令是单字节指令,机器码为83H,该指令执行时先使PC中当前值(机器码83H所在ROM单元地址)加1,即取出指令码83H,然后把这个加1后的PC中的内容与累加器A中的地址偏移量相加,从而取出操作数传送到累加器A中。第二条指令执行过程和第一条指令类似,现举例加以说明。
[例] 已知片外ROM的0302H单元中有一常数X,现欲把它取到累加器A,请编写相应程序,并进行必要的分析。
解:根据变址寻址特点,基地址显然应取0300H,地址偏移量为02H,相应程序为:
MOV DPTR, #0300H ;DPTR←0300H MOV A, #02H ;A←02H MOVC A, @A+DPTR ;A←X
其中:第一条和第二条传送指令是为第三条变址寻址指令准备条件的。在第三条指令执行时,单片机先把DPTR中的0300H和累加器A中的02H相加后得到0302H,然后到片外ROM中取出操作数X送到累加器A。因此,累加器A具有双重作用,在指令执行前用来存放地址偏移量02H,指令执行后的内容为目的操作数X,指令执行过程如图2-18所示。
- 34 -
图2-18 变址寻址示意图
应当指出两点:一是变址寻址指令的变址寻址区是程序存储器ROM,而不是数据存储器RAM;二是变址寻址是单字节两周期指令,CPU执行这条指令前应预先在DPTR和累加器A中为该指令的执行准备条件。 (6) 相对寻址
相对寻址在相对转移指令中使用,相对转移指令的指令码中含有相对地址偏移量,相对地址偏移量是一个带符号的8位二进制补码。其取值范围为-128~+127。 MCS-51单片机有两类相对转移指令:一类是双字节相对转移指令,又称为短转移指令,另一类是三字节相对转移指令,又称长转移指令。不论是哪一类指令,单片机执行时总是把程序计数器PC中的当前值(即:从程序存储器中取出转移指令后的PC值)和指令码中的相对地址偏移量rel相加,以形成下一条要执行指令的地址。例如,现有如下双字节相对转移指令
2000H 8054H SJMP rel ;PC←PC+2+rel
其中:80H是该指令的操作码,放在2000H单元中,54H是相对地址偏移量(相当于rel ),放在2001H单元。在执行这条指令时,单片机先从2000H和2001H单元取出指令码(程序计数器PC被加1两次从而变为2002H),然后把程序计数器PC中的内容和54H相加,以形成目标地址2056H,重新送回PC。这样,当单片机再根据PC取指令执行时,程序就转到2056H处执行,指令的执行过程如图2-19所示。相对转移指令特别有用,能生成浮动代码,深受用户青睐。
在使用中应注意以下两点:
1)在相对转移指令的执行中,当前PC值是指相对转移指令从程序存储器中取出来后的PC值,该值和地址偏移量相加便可形成目标转移地址,地址偏移量是一个带符号的二进制数。
2)在程序中,相对地址偏移量常常用符号(由英文字母构成)表示,以便为程序的设计提供方便。但在上机操作前,指令码中的rel (相当于前述指令中的54H)是需要计算的。
- 35 -