注册 登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

【藏宝阁】

酒逢知己饮,诗向会人吟。相识满天下,知心能几人。

 
 
 

日志

 
 

存储器间接寻址-指针  

2014-03-06 13:30:33|  分类: 工控知识 |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |
存储器间接寻址
     在指令中直接给出操作数(常数),称为立即寻址。在指令中给出操作数的地址(例如M5.2),称为直接寻址。
     间接寻址在指令中给出的不是操作数的值或操作数的地址,而是给出一个被称为地址指针的存储单元的地址,地址指针里存放的是真正的操作数的地址。
     地址指针就像收音机调台的指针,改变指针的位置,指针指向不同的电台。改变地址指针中的地址值,地址指针“指向”不同的地址。
     再 打一个比喻,邮递员的摩托车就好像一个地址指针。邮递员根据信封上的地址,将摩托车开到用户A的家门口,这个时候指针(摩托车)指向了这个地址,把信送给 用户A,就好像将数据写入这个地址。送下一封信的时候,相当于修改了地址指针中的值,摩托车开到下一个用户的门口,地址指针指向了另外一个地址。
     我们入住酒店的时候,在前台办完入住手续,酒店就会给我们一个房卡,房卡上面有房号,旅客根据房号使用宾馆的房间,每天每间房间可能住不同的旅客。在这里房卡就是指针,房间就是存储单元,旅客就是存储单元中存放的数据。
     为 什么需要间接寻址?间接寻址用来在程序运行期间,通过改变指针中地址的值,动态地修改指令中的地址。间接寻址常用于循环程序和查表程序。例如循环程序用来 累加一片连续的存储区中的数值,每次循环累加一个数值。累加后修改地址指针的值,使它指向下一个存储单元,为下一次循环的累加运算做好准备。没有间接寻 址,就不能编写循环程序。

 在执行循环程序时,除了需要修改地址以外,可能还需要设置存储区的起始地址。是否能用一条指令同时做这两件事呢?寄存器间接寻址就能解决这一问题。
 寄存器间接寻址的地址为地址偏移量和地址寄存器中的地址指针值之和。
 例 如宾馆的服务员要给客人送餐时,可以直接按房间号来送,相当于存储器间接寻址。也可以指定一个起始的房间号(地址偏移量,例如房间号200),此外再给出 要送餐的房间号与起始房间号的差值(例如1,3,6,地址寄存器中的地址值)。实际的房间号是起始房间号加上房间号的差值,例如200+3。改变地址偏移 量,可以对另一楼层的房间送餐。
 间接寻址因为可以分别改变地址偏移量或地址寄存器中的地址值,使用起来非常灵活方便,使用得当可以显著地简化程序。
 1.区域内间接寻址
 下面是区域内间接寻址的例子:
 L      P#5.0                      //将间接寻址的指针装入累加器1
 LAR1                               //将累加器1的内容送AR1
 L      MW[AR1, P#3.0]    //将MW8装入累加器1
 方括号内为操作数的地址,它等于AR1中的地址值P#5.0加上逗号后面的地址偏移量, P#5.0+P#3.0=P#8.0,即操作数为MW8。
 2.区域之间的间接寻址
 下面是区域间的间接寻址的例子:
 L      P#M 6.0                    //将M6.0的双字地址装入累加器1
 LAR1                                 //将累加器1的内容送到AR1
 L      W [AR1, P#20.0]      //将MW26的内容传送到累加器1 
 因为地址指针P#M6.0已经包含有区域信息(M区),第3条指令“L  W[AR1, P#20.0]”没有必要再使用地址标识符M。

一、(位间接寻址)
 1、在使用指针时:一般多是先赋值(初始化地址寄存器),后使用;
 2、尽量使用常数指针加地址区域标示符来进行间接寻址,这样更容易理解;
 3、在寻址时,可以结合循环次数、寻址幅度来改变寻址区域范围;
 下面举一个例子参考:(统计每个周期,Q5.5~Q15.5这个地址范围内,88个位状态为1的个数,即设备运行个数)
 
 //╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬
       L     0
       T     MW   100                    //将上个周期的累计值清零
       LAR1  P#5.5                       //指针寻址的起始地址(利用指针常数,初始化地址寄存器1)
       L     88                          //将其修改成0-65535可以实现全地址范围内寻址
 NEXT: T     LW   100                    //但是必须考虑其循环耗费的时间
       A     Q [AR1,P#0.0]               //修改Q为I、M、L可实现不同存储器间的寻址
       JCN   M001
       L     MW   100
       +     1                                   //扫描到有状态1存在,累计个数自加1功能
       T     MW   100                    //设备运行累计个数
 M001: +AR1  P#0.1                       //位地址向前推进一位
       L     LW   100
       LOOP  NEXT                        //循环次数减至0时,离开循环,程序往下执行
 //╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬
 
 需注意:+AR1  P#0.1    指令的含义,其实就是下面四条语句的集成、和浓缩!
                 TAR1             //将地址寄存器1的内容传送至累加器1
                 L     P#0.1     //将累加器1的内容移至累加器2,并将指针常数 P#0.1装载到累加器1
                 +D                 //累加器1的内容加上累加器2的内容并暂存在累加器1中
                 LAR1            //将累加器1的内容装载到地址寄存器1中
 
 从上面的例子和指令分解我们不难发现,地址寄存器可以直接赋值,并可以结合累加器进行灵活的地址运算!

二、(字节、字、双字间接寻址)
  1、在使用指针对字节、字、双字间接寻址时,大多是处理数据类型有规律的场合;
  2、需注意字节、字、双字寻址指针和地址偏移量的关系;字节寻址时,指针偏移一个字节;字寻址时,指针偏移2个字节,双字寻址时,指针偏移4个字节;
  3、尽量使用一个地址寄存器寻址,避免同时使用2个地址寄存器进行寻址,尽量做到干净利落;
  4、要充分利用临时存储区(L),结合循环把某些运算在临时存储区完成,提高指针寻址的执行效率;
  下面举一个例子参考:(DB11、DB12结构相同,里面各自存放了200个REAL类型的数据,比较DB11、DB12两个数据块对应地址里面的值,如果相等写到相同结构的DB13相对应的地址里面存储。)
 
 //╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬
       LAR1  P#0.0
       L     200                         //循环200次
 NEXT: T     LW   100
       OPN   DB    13                    //打开数据快DB13
       L     0.000000e+000
       T     DBD [AR1,P#0.0]             //将DB13当前的地址清零
     
      OPN   DB    11                    //打开数据快DB11
       L     DBD [AR1,P#0.0]             //读取DB11当前的数据
       T     LD   102                    //★暂存到临时存储器 LD102里面
   
       OPN   DB    12                    //打开数据快DB12
       L     DBD [AR1,P#0.0]             //读取DB12当前的数据
       T     LD   106                    //★暂存到临时存储器 LD106里面
 
       L     LD   102                    //★比较DB11、DB12对应的地址里面的数据
       L     LD   106
       ==R                               //是否相等
       JCN   M001
       OPN   DB    13
       L     LD   102
       T     DBD [AR1,P#0.0]             //相同的数据写到DB13对应的地址里面
 M001: +AR1  P#4.0                       //地址寄存器1的地址向前推进4个字节
       L     LW   100
       LOOP  NEXT
 //╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬
 
 通过上面的例子,我们不难发现:合理、巧妙使用L区内存,可以只使用一个地址寄存器,提高指针寻址的执行效率!


把数据需要连续存储到DB13,程序修改如下:
        LAR1  P#0.0
  LAR2  P#0.0
        L     200                         //循环200次
  NEXT: T     LW   100
        OPN   DB    13                    //打开数据快DB13
        L     0.000000e+000
        T     DBD [AR1,P#0.0]             //将DB13当前的地址清零
      
       OPN   DB    11                    //打开数据快DB11
        L     DBD [AR1,P#0.0]             //读取DB11当前的数据
        T     LD   102                    //★暂存到临时存储器 LD102里面
    
        OPN   DB    12                    //打开数据快DB12
        L     DBD [AR1,P#0.0]             //读取DB12当前的数据
        T     LD   106                    //★暂存到临时存储器 LD106里面
  
        L     LD   102                    //★比较DB11、DB12对应的地址里面的数据
        L     LD   106
        ==R                               //是否相等
        JCN   M001
        OPN   DB    13
        L     LD   102
        T     DBD [AR2,P#0.0]             //相同的数据写到DB13对应的地址里面
     +AR2  P#4.0
 M001: +AR1  P#4.0                       //地址寄存器1的地址向前推进4个字节
        L     LW   100
        LOOP  NEXT
  评论这张
 
阅读(520)| 评论(0)
推荐 转载

历史上的今天

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2017