Zhougy.vc 发表于 2008-6-11 00:16:20

关于相对PC值

请教马老师什么是相对PC值?我不明白跳转指令的确切意义。比如您书中写的:

(4)不相等跳转
BRNE k                -64≤k≤63
说明:条件相对跳转,测试零标志位Z,如果Z位被清零,则相对PC值跳转k个字。这条指令相当于指令BRBC 1,k
1、文中的K是一个常量(数字),还是一个标号?
2、如果是一个常量,那么岂不是要知道当前PC值到目的PC值得差。
3、如果是一个标号,那是不是限制我当前点到目的点的代码长度。

machao 发表于 2008-6-11 10:06:02

先明白以下几个基本的概念:

该指令的机器码为:1111 01kk kkkk k000.其中7个k(二进制)就是汇编指令BRNE k中的k所代表的相对跳转偏移量.7位二进制k的范围-64≤k≤63.

因此最原始(或最贴近机器码)的汇编应该如此表示: BRNE 25 (假定相对跳转偏移量为25).也就是说,k必须是个数字(-64≤k≤63)

而现在是使用软件将汇编指令"翻译"成机器代码的,这个"翻译"软件就是汇编系统.在汇编系统平台中,为了方便程序员编写程序,将汇编指令的限制适当放宽了,如允许这样写:LDS Rd,30+50

而原始的 LDS 指令里面不能有加法表达式的.汇编系统如何能允许这样写呢?

汇编系统实际上是先将 30+50 计算好, 然后整理指令为 LDS Rd,80, 然后再将其"翻译"机器码.

能够理解这点的话,下面就能理解了.

1、文中的k是一个常量(数字),还是一个标号?
=====>原始汇编中应该为数字常量,但在汇编系统中扩展了,可以(通常也是)用标号代替.

2、如果是一个常量,那么岂不是要知道当前PC值到目的PC值得差。
=====>采用人工编译的话,就得你搬手指计算出数值了.这样肯定不方便.现在使用软件汇编系统,不需要了,用标号代替吧.

3、如果是一个标号,那是不是限制我当前点到目的点的代码长度。
使用了标号,汇编系统在"翻译"的过程中,会帮你计算从跳转指令到标号处指令之间的偏移量(字数).如果超出范围,编译系统将给出错误提示,告示程序员超出范围,修改代码.如果在范围内,就会将该计算出的数字代替跳转指令中的标号,然后生成相应的机器码.

Zhougy.vc 发表于 2008-6-11 22:27:25

非常感谢您!马老师。我明白了

lxx_sea_sky 发表于 2008-6-14 10:26:19

请问马老师:程序获取PC值有哪些办法?

===============================================
以前发的贴,但没能得到答案。
目的:实现单片机用的断言assert(),即断言失败时,获取出错程序的PC值,直接显示或串口输出,配合AVR Studio 的仿真能力(汇编窗口)定位出错程序。
目前办法:assert()写成函数,调用时程序自动压栈PC,再通过SP指针读取PC。
各位大虾若有更快捷的办法,敬请赐教!
声明:本人,新手,不会AVR汇编,不知道汇编能不能行,若行的话,能否贴上。

附上简陋的代码,算是抛砖引玉。
#ifdef DEBUG

    #define MY_ASSERT(condition)    backup_SP = SP;\
                                    my_assert(condition)

    volatile unsigned int backup_SP;

    void my_assert(unsigned char condition)
    {
      unsigned int backup_PC;

      if(!condition)
      {
            backup_PC = *(unsigned char *)(backup_SP - 1);
            backup_PC <<= 8;
            backup_PC += *(unsigned char *)(backup_SP);
            //...
            //添加出错输出
            //...
            while(1);
      }
      return;
    }

#else

    #define MY_ASSERT(condition)                //空定义

#endif

machao 发表于 2008-6-14 12:39:39

程序计数寄存器PC是个重要的寄存器,一旦破坏,系统肯定崩溃了.因此汇编指令不可以直接对PC操作的,因此要获得PC的值只能通过间接的方法.

通过中断,到堆栈中获得PC的地址是常用的方法,不过得到的不是当前的PC,是响应中断时的PC.

我不明白3楼具体想做什么,好象要设计调试系统.不过,真的像3楼的声明:"本人,新手,不会AVR汇编"那样,那么还是先放一放,等有一定的基础后再做思考.
页: [1]
查看完整版本: 关于相对PC值