You also want an ePaper? Increase the reach of your titles
YUMPU automatically turns print PDFs into web optimized ePapers that Google loves.
而对应地,CopyCode2Ram的最后一行:<br />
33d009ac: e8bd8070 pop {r4, r5, r6, pc}<br />
就是把之前push的值,给pop出来,还给对应的寄存器,其中最后一个是将开始push的lr的值,<br />
pop出来给赋给PC,因为实现了函数的返回。<br />
另外,我们注意到,在CopyCode2Ram的倒数第二行是:<br />
33d009a8: e3a00000 mov r0, #0 ; 0x0<br />
是把0赋值给r0寄存器,这个就是我们所谓返回值的传递,是通过r0寄存器的。<br />
此处的返回值是0,也对应着C语言的源码中的“return 0”.<br />
对于使用哪个寄存器来传递返回值:<br />
当然你也可以用其他暂时空闲没有用到的寄存器来传递返回值,但是这些处理方式,本身是根据<br />
ARM的APCS的寄存器的使用的约定而设计的,你最好不要随便改变使用方式,最好还是按照其<br />
约定的来处理,这样程序更加符合规范。<br />
3.6. 关于为何不直接用 mov 指令,而非要用 adr 伪指令<br />
在分析uboot的start.S中,看到一些指令,比如:<br />
adr r0, _start<br />
觉得好像可以直接用mov指令实现即可,为啥还要这么麻烦地,去用ldr去实现?<br />
关于此处的代码,为何要用adr指令:<br />
adr r0, _start<br />
(<br />
注:其被编译器编译后,会被翻译成:<br />
sub r0, pc, #172<br />
)<br />
而不直接用mov指令直接将_start的值赋值给r0,类似于这样:<br />
mov r0, _start<br />
呢?<br />
其原因主要是,<br />
sub r0, pc, #172<br />
这样的代码,所处理的值,都是相对于PC的偏移量来说的,这样的代码中,没有绝对的物理地<br />
址值,都是相对的值,利用产生位置无关代码。因为如果用mov指令:<br />
mov r0, _start<br />
那么就会被编译成这样的代码:<br />
mov r0, 0x33d00000<br />
如果用了上面这样的代码:<br />
mov r0, 0x33d00000<br />
那么,如果整个代码,即要执行的程序的指令,被移动到其他位置,那么<br />
mov r0, 0x33d00000<br />
这行指令,执行的功能,就是跳转到绝对的物理地址,而不是跳转到相对的_start的位置了,<br />
就不能实现我们想要的功能了,这样包含了绝对物理地址的代码,也就不是位置无关的代码了。<br />
于此相对,这行指令:<br />
sub r0, pc, #172