今天在廖常初老师的博客上看见了戏说寄存器间接寻址,转过来,共同学习!!
在执行循环程序时,除了需要修改地址以外,还需要设置存储区的起始地址。是否能用一条指令同时做这两件事呢?寄存器间接寻址就能解决这一问题。
寄存器间接寻址的地址为地址偏移量和地址寄存器中的地址指针值之和。
例如宾馆的服务员要给客人送餐时,可以直接按房间号来送,相当于存储器间接寻址。也可以指定一个起始的房间号(地址偏移量,例如房间号200),此外再给出要送餐的房间号与起始房间号的差值(例如1,3,6,地址寄存器中的地址值)。实际的房间号是起始房间号加上房间号的差值,例如200+3。改变地址偏移量,可以对另一楼层的房间送餐。
间接寻址因为可以分别改变地址偏移量或地址寄存器中的地址值,使用起来非常灵活方便,使用得当可以显著地简化程序。
三菱的FX的变址寻址就是一种寄存器间接寻址。FX系列有16个变址寄存器V0~V7和Z0~Z7,它们用来改变编程元件的元件号,例如当V2的值为12时,数据寄存器的元件号D6V2相当于D18(12+6 = 18)。
S7-300/400的寄存器间接寻址可以对位、字节、字和双字寻址,还可以包含存储区的信息,功能非常强大。S7-300/400有两个地址寄存器AR1和AR2,操作数的地址等于地址寄存器中的地址值加上地址偏移量。下面是寄存器间接寻址的32位指针格式:
x000 0rrr 0000 0bbb bbbb bbbb bbbb b***
其中第0~2位(***,最低位为第0位)为被寻址地址中位的编号(0~7),第3~18位(16个b)为被寻址地址的字节的编号。第24~26位(rrr)为被寻址地址的区域标识号,例如M区为2#011。
看懂了下面的程序,就算掌握了S7-300/400的寄存器间接寻址了。
1.区域内间接寻址
指针的最高位(第31位)x为0时为区域内的间接寻址,此时区域标示号rrr也为0,地址指针的格式与存储器间接寻址的相同。下面是区域内间接寻址的例子:
L P#5.0 //将间接寻址的指针装入累加器1
LAR1 //将累加器1的内容送AR1
A M[AR1, P#2.3] //AR1中的P#5.0加偏移量P#2.3,对M7.3进行操作
= Q[AR1, P#0.2] //逻辑运算的结果送Q5.2,P#5.0+P#0.2=P#5.2
L MW[AR1, P#19.0] //将MW24装入累加器1
方括号内为操作数的地址,它等于AR1中的地址值P#5.0加上逗号后面的地址偏移量,例如第3条指令中操作数的地址为P#5.0+P#2.3=P#7.3,即操作数为M7.3。
2.区域之间的间接寻址
指针的最高位(第31位)x = 1时为区域间的间接寻址,下面是区域间的间接寻址的例子:
L P#M 6.0 //将M6.0的双字地址装入累加器1
LAR1 //将累加器1的内容送到AR1
L W [AR1,P#20.0] //将MW26的内容传送到累加器1
P#M6.0对应的二进制数为2#1000 0011 0000 0000 0000 0000 0011 0000。因为地址指针P#M6.0已经包含有区域信息(rrr=2#011表示M区),第3条指令“L W[AR1, P#50.0]”没有必要再使用地址标识符M。
用地址指针读写字、字节或双字时,指针中小数点右边的位编号必须为0,否则将会出错。