8076|11

1972

帖子

0

TA的资源

五彩晶圆(初级)

楼主
 

ARM Cortex-M0中的“LDR”汇编伪指令疑问 [复制链接]

 
今天在看Keil编译出来的汇编代码时,看到如下的代码:
按照我百度到的关于LDR的指令说明,[pc , #40]计算得到的值应该是:0x000000D4 + 0x28 = 0x000000FC,但是编译器上显示的预算结果是0x00000100;下面的一条[pc , #44]计算得到的值应该是:0x000000D6 + 0x2C = 0x00000100,但是汇编器上显示的预算结果是0x00000104;所以我猜想是再加上4,于是我又找了其他资料,感觉更迷糊了,资料内容如下:

    如上图中的资料显示,上面第一条画红线的地方:Rt = 存储器[字对齐(PC + 4) + 零展开(#immed8 << 2)],对上汇编译器的预算结果PC再加上4的结果说得通,但是对立即数零展开(#immed8 << 2)要怎么理解,为什么要左移2?
    接下来是第二条画红线的地方:示例LDR R0 , [PC , #0x40] ; 将当前程序地址加上0x40加载到R0中,这里同样使用到了PC作为基地址,但是却没有再加上4,而且立即数0x40也不像第一处描述的那样左移2位。
    综上,现在是三处都有合理,又有矛盾的地方,也不知道我是不是漏掉什么信息或者是哪个资料有错,现在我是无法判断了,请论坛里的大神来帮忙解释一下,先行谢过

最新回复

#40 这个是移位后的,请问#immed8从哪里来,叫这个名字,说明他是一个8位的立即数,是存放在指令中的,指令中存放的是A,0x0A 0x28 => 40,A你从指令中都能看到,指令是480A。 想巩固基础,建议你看看计算机原理和汇编语言的相关教材。  详情 回复 发表于 2017-11-28 13:03
点赞 关注

回复
举报

6040

帖子

205

TA的资源

版主

沙发
 
1. 当前地址就是PC+4
2. #immed8 != #40 而是 (#immed8 << 2) == #40; 因为地址肯定是4的倍数,为了表示更广的寻址范围,所以把8位数左移了两位。 0x28 >> 2 => A, 0x2C >> 2 => B, 你从第一条指令包含A第二条指令包含B很容易能推断出来。

点评

谢谢版主的解答,第1点PC+4我应该是理解了,在执行到本条代码 LDR r0 , 时,PC值实际上已经是下一条待执行代码的值了,也就是多增加了4。 但是你关于第2点的解释,我依然是看不懂是什么意思,我也百度了下相关的  详情 回复 发表于 2017-11-28 09:50
 
 

回复

1972

帖子

0

TA的资源

五彩晶圆(初级)

板凳
 
lcofjp 发表于 2017-11-27 21:09
1. 当前地址就是PC+4
2. #immed8 != #40 而是 (#immed8 > 2 => A, 0x2C >> 2 => B, 你从第一条指令包含A第 ...

谢谢版主的解答,第1点PC+4我应该是理解了,在执行到本条代码 LDR  r0 , [pc , #40]时,PC值实际上已经是下一条待执行代码的值了,也就是多增加了4。

但是你关于第2点的解释,我依然是看不懂是什么意思,我也百度了下相关的资料,都有提到移位,但是还是理解不了,举个例子:
按照第一条红线的地方,语法是 LDR  R0 , [PC , #40],再按照备注里面的算法,方括号里的地址值=(PC + 4) + (0x28 << 2);这里取PC的值等于图中的值0x000000D4,那算出来的结果是0x00000178,而不是算出来的0x00000100

点评

#40 这个是移位后的,请问#immed8从哪里来,叫这个名字,说明他是一个8位的立即数,是存放在指令中的,指令中存放的是A,0x0A 0x28 => 40,A你从指令中都能看到,指令是480A。 想巩固基础,建议你看看计算机原理和  详情 回复 发表于 2017-11-28 13:03
 
 
 

回复

750

帖子

3

TA的资源

版主

4
 

Rn中的值其实是一个指针,所以你应该去观察(0x000000D4 + 0x28 + 由于流水线机制引入的PC值偏差)地址处的值

点评

http://blog.csdn.net/aspenstars/article/details/72900811  详情 回复 发表于 2017-11-28 10:52
谢谢版主的解答。关于PC值再加上4的这个问题我似乎清楚了,你提到的“流水线机制引入的PC值偏差”这个我刚才也有百度到资料,那资料里举了个三级流水线的例子,按照一条指令的执行流程:取指->译码->执行,当第1条指  详情 回复 发表于 2017-11-28 10:49
 
个人签名

要666

 
 

回复

1972

帖子

0

TA的资源

五彩晶圆(初级)

5
 
le062 发表于 2017-11-28 10:15
Rn中的值其实是一个指针,所以你应该去观察(0x000000D4 + 0x28 + 由于流水线机制引入的PC值偏差)地址处 ...

谢谢版主的解答。关于PC值再加上4的这个问题我似乎清楚了,你提到的“流水线机制引入的PC值偏差”这个我刚才也有百度到资料,那资料里举了个三级流水线的例子,按照一条指令的执行流程:取指->译码->执行,当第1条指令处于译码状态时,第二条指令处于取指状态,第三条指令还没有开始;当第一条指令牌执行状态时,第二条指令处于译码状态,第三条指令处于译码状态。那我不清楚的地方是PC寄存器的值在哪个阶段有变化。版主能详细说说吧,像Cortex-M0内核的又是怎么样的?

点评

不同cpu的偏差不同,所以这个值具体多少对于c开发者意义不大,对于汇编开发者,也只要用伪代码实现即可。 个人观点,没必要太关心这种技术细节。  详情 回复 发表于 2017-11-28 11:23
 
 
 

回复

1972

帖子

0

TA的资源

五彩晶圆(初级)

6
 
le062 发表于 2017-11-28 10:15
Rn中的值其实是一个指针,所以你应该去观察(0x000000D4 + 0x28 + 由于流水线机制引入的PC值偏差)地址处 ...

http://blog.csdn.net/aspenstars/article/details/72900811
 
 
 

回复

750

帖子

3

TA的资源

版主

7
 
bobde163 发表于 2017-11-28 10:49
谢谢版主的解答。关于PC值再加上4的这个问题我似乎清楚了,你提到的“流水线机制引入的PC值偏差”这个我 ...

不同cpu的偏差不同,所以这个值具体多少对于c开发者意义不大,对于汇编开发者,也只要用伪代码实现即可。
个人观点,没必要太关心这种技术细节。
引申阅读的话,用搜索引擎即可

点评

就像你说的,各个CPU都不同,那目前知道Cortex-M0是PC+4,那要是换成Coretex-M3/M4/M7这些可能具有更多级流水线的处理器,那汇编代码岂不是不能通用,而且写出来的汇编代码不是会出错,再来就是阅读汇编代码也会产生  详情 回复 发表于 2017-11-28 12:13
 
个人签名

要666

 
 

回复

1972

帖子

0

TA的资源

五彩晶圆(初级)

8
 
le062 发表于 2017-11-28 11:23
不同cpu的偏差不同,所以这个值具体多少对于c开发者意义不大,对于汇编开发者,也只要用伪代码实现即可。 ...

就像你说的,各个CPU都不同,那目前知道Cortex-M0是PC+4,那要是换成Coretex-M3/M4/M7这些可能具有更多级流水线的处理器,那汇编代码岂不是不能通用,而且写出来的汇编代码不是会出错,再来就是阅读汇编代码也会产生疑惑

点评

都是汇编代码了,还要啥自行车。不要折腾自己。  详情 回复 发表于 2017-11-28 12:18
 
 
 

回复

750

帖子

3

TA的资源

版主

9
 
bobde163 发表于 2017-11-28 12:13
就像你说的,各个CPU都不同,那目前知道Cortex-M0是PC+4,那要是换成Coretex-M3/M4/M7这些可能具有更多级 ...

都是汇编代码了,还要啥自行车。不要折腾自己。

点评

经过两天的不断查找资料,终于是明白了其中让我搞不懂的地方:一般情况下我们自己编写的汇编代码是比较容易看懂的,就好比我截图中的原汇编代码是:LDR R0 , =0x50000100,使用的是32位立即数寻址方式;但是  详情 回复 发表于 2017-11-29 15:44
 
个人签名

要666

 
 

回复

6040

帖子

205

TA的资源

版主

10
 
bobde163 发表于 2017-11-28 09:50
谢谢版主的解答,第1点PC+4我应该是理解了,在执行到本条代码 LDR  r0 , 时,PC值实际上已经是下一条待执 ...

#40 这个是移位后的,请问#immed8从哪里来,叫这个名字,说明他是一个8位的立即数,是存放在指令中的,指令中存放的是A,0x0A << 2 => 0x28 => 40,A你从指令中都能看到,指令是480A。
想巩固基础,建议你看看计算机原理和汇编语言的相关教材。

点评

我去查找了ARM指令集和Thumb指令集的相关资料,了解了其中的原由,我是被截图中的描述给迷惑,一下子转不过来,现在知道了,谢谢你的指导。  详情 回复 发表于 2017-11-29 15:47
 
 
 

回复

1972

帖子

0

TA的资源

五彩晶圆(初级)

11
 
le062 发表于 2017-11-28 12:18
都是汇编代码了,还要啥自行车。不要折腾自己。

      经过两天的不断查找资料,终于是明白了其中让我搞不懂的地方:一般情况下我们自己编写的汇编代码是比较容易看懂的,就好比我截图中的原汇编代码是:LDR  R0 , =0x50000100,使用的是32位立即数寻址方式;但是经过Keil编译之后的汇编代码却是:LDR  r0 , [pc , #40],使用的是基于PC寄存器的基址寻址方式,也就是说编译器在编译时会自动去选择合适的方式来实现相同的功能,而且从我了解到的资料中,大部分的立即数寻址方式在最终生成的代码中其实都是基于“文字池”,然后使用PC作为基址的寻址方式。
      接下来的关于我询问的“立即数为什么左移2位的”问题,我在查看Thumb指令机器码的时候明白了,这是指令规定好的,而且与ARM的32位的LDR的指令编码方式不一样,我是被我第二个截图中的内容搞晕了,截图中的描述确实是不够详细,我这种新手一下子就遇到死胡同了。
      再后来谈到PC值的计算方法,我也从资料中了解到了为什么要加4而不是前两天只知加4而不知道根本原因,加4的原因是Cortex-M0内核使用的是3级流水线结构,而且按16位数据进行取指(即PC每次加2),由于是3级流水线结构,在指令中使用到的PC值的时候实际上PC已经指向第三条指令地址了,所以要加4。后来我提出了在各个内核的处理器中汇编代码不能通用的问题,现在也解决了,原因同上上一条,我们实际在写汇编代码的时候几乎是不会用到PC作为基址的寻址方式(除非是自找难受或者是对所写程序了如指掌的大神),编译器会在编译的时候自动处理,所以不会存在由于流水线级数不同而导致的代码不通用的问题。
      最后,感谢你的解答,让我明白不少。
 
 
 

回复

1972

帖子

0

TA的资源

五彩晶圆(初级)

12
 
lcofjp 发表于 2017-11-28 13:03
#40 这个是移位后的,请问#immed8从哪里来,叫这个名字,说明他是一个8位的立即数,是存放在指令中的,指 ...

我去查找了ARM指令集和Thumb指令集的相关资料,了解了其中的原由,我是被截图中的描述给迷惑,一下子转不过来,现在知道了,谢谢你的指导。
 
 
 

回复
您需要登录后才可以回帖 登录 | 注册

随便看看
查找数据手册?

EEWorld Datasheet 技术支持

相关文章 更多>>
关闭
站长推荐上一条 1/10 下一条

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

About Us 关于我们 客户服务 联系方式 器件索引 网站地图 最新更新 手机版

站点相关: 国产芯 安防电子 汽车电子 手机便携 工业控制 家用电子 医疗电子 测试测量 网络通信 物联网

北京市海淀区中关村大街18号B座15层1530室 电话:(010)82350740 邮编:100190

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved
快速回复 返回顶部 返回列表