免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 6026 | 回复: 5
打印 上一主题 下一主题

[其它] 为何ARM7中PC=PC+8, 为何ARM9和ARM7一样,也是PC=PC+8 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2011-04-17 23:49 |只看该作者 |倒序浏览
本帖最后由 crifan 于 2011-05-01 21:14 编辑

1.ARM7PC=PC+8

此处解释为何ARM7中,CPU地址,即PC,为何有PC=PC+8这一说法:

众所周知,AMR7,是三级流水线,其细节见图:

图表 23 AMR7三级流水线

首先,对于ARM7对应的流水线的执行情况,如下面这个图所示:

ARM7

图表 24 ARM7三级流水线状态

然后对于三级流水线举例如下:

图表 25 ARM7三级流水线示例

从上图,其实很容易看出,第一条指令:

add r0, r1,$5

执行的时候,此时PC已经指向第三条指令:

cmp r2,#3

的地址了,所以,是PC=PC+8.


2.ARM9ARM7一样,也是PC=PC+8

ARM7的三条流水线,PC=PC+8,很好理解,但是AMR9中,是五级流水线,为何还是PC=PC+8,而不是

PC

=PC+(5-1)*4

=PC + 16

呢?

下面就需要好好解释一番了。

具体解释之前,先贴上ARM7ARM9的流水线的区别和联系:

图表 26 ARM7三级流水线 vs ARM9五级流水线

图表 27 ARM7三级流水线到ARM9五级流水线的映射

下面开始对为何ARM9也是PC=PC+8进行解释。

先列出ARM9的五级流水线的示例:

图表 28 ARM9的五级流水线示例

然后我们以下面uboot中的start.S的最开始的汇编代码为例来进行解释:


  1. 00000000 <_start>:
  2.    0:   ea000014   b   58 <reset>
  3.    4:   e59ff014   ldr pc, [pc, #20] ; 20 <_undefined_instruction>
  4.    8:   e59ff014   ldr pc, [pc, #20] ; 24 <_software_interrupt>
  5.    c:   e59ff014   ldr pc, [pc, #20] ; 28 <_prefetch_abort>
  6.   10:   e59ff014   ldr pc, [pc, #20] ; 2c <_data_abort>
  7.   14:   e59ff014   ldr pc, [pc, #20] ; 30 <_not_used>
  8.   18:   e59ff014   ldr pc, [pc, #20] ; 34 <_irq>
  9.   1c:   e59ff014   ldr pc, [pc, #20] ; 38 <_fiq>

  10. 00000020 <_undefined_instruction>:
  11.   20:   00000120   .word  0x00000120
复制代码

下面对每一个指令周期,CPU做了哪些事情,分别详细进行阐述:

在看下面具体解释之前,有一句话要牢记,那就是:

PC不是指向你正在运行的指令,而是

PC始终指向你要取的指令的地址

认识清楚了这个前提,后面的举例讲解,就容易懂了。

指令周期Cycle1

1取指

PC总是指向将要读取的指令的地址(即我们常说的,指向下一条指令的地址),而当前PC=4

所以去取物理地址为4对对应的指令“ldr pc, [pc, #20]”,其对应二进制代码为e59ff014

此处取指完之后,自动更新PC的值,即PC=PC+4(单个指令占4字节,所以加4=4+4=8

指令周期Cycle2

1译指:翻译指令e59ff014

2)同时再去取指

PC总是指向将要读取的指令的地址(即我们常说的,指向下一条指令的地址),而当前PC=8

所以去物理地址为8所对应的指令“ldr pc, [pc, #20] 其对应二进制代码为e59ff014

此处取指完之后,自动更新PC的值,即PC=PC+4=8+4=12=0xc

指令周期Cycle3

1执行(指令):执行“e59ff014,即“ldr pc,[pc, #20]”所对表达的含义,即

PC

= PC + 20

= 12 + 20

= 32

= 0x20

此处,只是计算出待会要赋值给PC的值是0x20,这个0x20还只是放在执行单元中内部的缓冲中。

2译指:翻译e59ff014

3取指

此步骤由于是和上面(1)中的执行同步做的,所以,未受到影响,继续取指,而取指的那一时刻,PC为上一Cycle更新后的值,即PC=0xc,所以是去取物理地址为0xc所对应的指令 ldr pc, [pc, #20],对应二进制为e59ff014

其实,分析到这里,大家就可以看出:

Cycle3的时候,PC的值,刚好已经在Cycle1Cycle2,分别加了4,所以Cycle3的时候,PC=PC+8,而同样道理,对于任何一条指令的,都是在Cycle3,指令的Execute执行阶段,如果用到PC的值,那么PC那一时刻,就是PC=PC+8

所以,此处虽然是五级流水线,但是却不是PC=PC+16,而是PC=PC+8

进一步地,我们发现,其实PC=PC+NN,是和指令的执行阶段所处于流水线的深度有关,即此处指令的执行Execute阶段,是五级流水线中的第三个,而这个第三阶段的Execute和指令的第一个阶段的Fetch取指,相差的值是 3 -1 =2,即两个CPUCycle,而每个Cycle都会导致PC=+PC+4,所以,指令到了Execute阶段,才会发现,此时PC已经变成PC=PC+8了。

回过头来反观ARM7的三级流水线,也是同样的道理,指令的Execute执行阶段,是处于指令的第三个阶段,同理,在指令计算数据的时候,如果用到PC,就会发现此时PC=PC+8

同理,假如ARM9的五级流水线,把指令的Execute执行阶段,设计在了第四个阶段,那么就是PC=PC+(第4阶段-1*4个字节 = PC= PC+12了。


【总结】

ARM7的三级流水线,PC=PC+8

ARM9的五级流水线,也是PC=PC+8

根本的原因是,两者的流水线设计中,指令的Execute执行阶段,都是处于流水线的第三级,

所以使得PC=PC+8

类似地,可以推导出:

假设,Execute阶段处于流水线中的第E阶段,每条指令是T个字节,那么

PC

= PC + N*T

= PC + (E - 1) * T

此处ARM7ARM9

Execute阶段都是第3阶段-> E=3

每条指令是4个字节-> T=4

所以:

PC

=PC + N* T

=PC + (3 -1 ) * 4

= PC + 8

【关于直接改变PC的值,会导致流水线清空的解释】

PC的值直接赋值为0x20。而PC值更改,直接导致流水线的清空,即导致下一个cycle中的,对应的流水线中的其他几个步骤,包括接下来的同一个Cycle中的取指的工作被取消。在PC跳转到0x20的位置之后,流水线重新计算,重新一步步地按照流水线的逻辑,去一点点执行。当然要保证当前指令的执行完成,即执行之后,还有两个cycle,分别做的MemoryWrite,会继续执行完成。

【相关资料】

ARM流水线和program counter(PC)的增量

http://hi.baidu.com/istry/blog/item/f823e1438de0a71972f05d0f.html

最后附上ARM9的五级流水线的内置执行结构的细节:

图表 29 ARM9五级流水线的执行机构的细节

cycle123-5.jpg (111.2 KB, 下载次数: 78)

cycle123-5.jpg

论坛徽章:
22
丑牛
日期:2014-08-15 14:32:0015-16赛季CBA联赛之同曦
日期:2017-12-14 15:28:14黑曼巴
日期:2017-08-10 08:14:342017金鸡报晓
日期:2017-02-08 10:39:42黑曼巴
日期:2016-11-15 15:48:38CU十四周年纪念徽章
日期:2016-11-09 13:19:1015-16赛季CBA联赛之同曦
日期:2016-04-08 18:00:03平安夜徽章
日期:2015-12-26 00:06:30程序设计版块每日发帖之星
日期:2015-12-03 06:20:002015七夕节徽章
日期:2015-08-21 11:06:17IT运维版块每日发帖之星
日期:2015-08-09 06:20:002015亚冠之吉达阿赫利
日期:2015-07-03 08:39:42
2 [报告]
发表于 2011-04-18 08:43 |只看该作者
呵呵,講的很好啊,我覺得有必要把PC=PC+8這前後兩個PC都解釋下

论坛徽章:
0
3 [报告]
发表于 2011-04-20 19:01 |只看该作者
楼主的写得很好,
但我觉得这个PC=PC+8 会让人混淆, 按我的理解, 应该为 PC=当前执行指令的地址+8 才能准确表示出这一机制,
我虽然理解这一机制,但不能理解为什么 "PC"+8, 而不是"当前执行指令的地址"+8, 难道“当前执行指令的地址” = “PC” 么?

论坛徽章:
0
4 [报告]
发表于 2011-04-21 16:35 |只看该作者
回复 3# alvininha


    “但我觉得这个PC=PC+8 会让人混淆, 按我的理解, 应该为 PC=当前执行指令的地址+8 才能准确表示出这一机制,”
同意。

“我虽然理解这一机制,但不能理解为什么 "PC"+8, 而不是"当前执行指令的地址"+8, 难道“当前执行指令的地址” = “PC” 么?”
之所以有PC=PC+8的说法,我的感觉,好像是为了解释,为何那些地址无关的指令,比如adr等指令,被翻译成真正的汇编,用PC+某个偏移量来表示要跳转到对应的地址,其中那个偏移量,和我们所期望的值,少了8,所以才会有PC=PC+8.
而这句话的真正的含义,如你所说,是“PC=当前执行指令的地址+8”,实际上用:
http://blog.csdn.net/hamilton1/archive/2011/02/18/6192722.aspx
中的解释,更加清晰:“PC(excute)=PC(fetch)+8"。

当前正在执行的指令,其之前取值时候的PC的值,就是PC(fetch)
而当前指令执行的计算中,如果用到PC,而此刻PC的值是PC(excute)
两者的关系就是PC(execute)=PC(fetch) + 8

对于我们程序员来说,一般情况下,写C语言,不需要关心这些细节。
写汇编的话,貌似一般也用不到,只是用到adr等指令,其会被编译器自动翻译成正确的值。
我们要做的事情,就是在看汇编的adr等指令被编译成对应的汇编的时候,知道为何PC加上那个偏移量,和原以为的值,相差一个8,即可。

【总结】
搞懂PC=PC+8背后的逻辑,说白了,只是为了看懂汇编代码。
实际编程候总,貌似很少用得到,很少需要编程者关心此细节。

论坛徽章:
0
5 [报告]
发表于 2011-04-21 16:55 |只看该作者
多添一句,之前就看过的,在这里又看到的:
http://stackoverflow.com/questio ... our-of-ldr-pc-value
在ARM7的三级流水线(取指,译指,执行)和ARM9的五级流水线(取指,译指,执行,存储,写回)中:
PC,  总是指向当前正在被取指的指令的地址,
PC-4,总是指向当前正在被译指的指令的地址,
PC-8,总是指向当前的那条指令,即我们一般说的,正在被执行的指令的地址。

论坛徽章:
0
6 [报告]
发表于 2011-05-01 21:15 |只看该作者
本帖最后由 crifan 于 2011-05-01 21:16 编辑

系统字数限制,无法发表在原帖子里面,只好贴在这里了:

------------------------------------------------------------------------

【用图来说明PC=PC+8个过程】

对于上面的文字的分析过程,可能看起来不是太容易理解,所以,下面这里通过图表来表示具体的流程,就更容易看懂了。其中,下图,是以ARM9的五级流水线的内部架构图为基础,而编辑的出来用于说明为何ARM9的五级流水线,也是PC=PC+8:

图表 31 ARM9的五级流水线中为何PC=PC+8


对于上图中的,第一个指令在执行的时候,是使用到了PC的值,其实,我们可以看到,

对于指令在执行中,不论是否用到PC的值,PC都会按照既定逻辑,没一个cycle,自动增加4的,套用《非诚勿扰2》中的经典对白,即为:

你(指令执行的时候)用,

或者不用,

PC就在那里,

自动增4.

所以,经过两个cycle的增4,就到了指令执行的时候,此时PC已经增加了8了,即使你指令执行的时候,没有用到PC的值,其也还是已经加了8了。而一般来说,大多数的指令,肯定也都是没有用到PC的,但是其实任何指令执行的那一时刻,也已经是PC=PC+8,而多数指令没有用到,所以很多人没有注意到这点罢了。

【PC(execute)=PC(fetch)+ 8】

对于PC=PC+8中的两个PC,其实含义不完全一样.其更准确的表达,应该是这样:

PC(execute)=PC(fetch)+ 8

其中:

PC(fetch):当前正在执行的指令,就是之前取该指令时候的PC的值

PC(execute):当前指令执行的计算中,如果用到PC,则此时PC的值。

【不同阶段的PC值的关系】

对应地,在ARM7的三级流水线(取指,译指,执行)和ARM9的五级流水线(取指,译指,执行,存储,写回)中,可以这么说:

PC
总是指向当前正在被取指的指令的地址,

PC-4,总是指向当前正在被译指的指令的地址,

PC-8,总是指向当前的那条指令,即我们一般说的,正在被执行的指令的地址。

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

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP