02.07.2013 Views

Uboot中start.S源码的指令级的详尽解析

Uboot中start.S源码的指令级的详尽解析

Uboot中start.S源码的指令级的详尽解析

SHOW MORE
SHOW LESS

You also want an ePaper? Increase the reach of your titles

YUMPU automatically turns print PDFs into web optimized ePapers that Google loves.

3.5.1.1. 什么叫做上下文 context<br />

保存现场,也叫保存上下文。<br />

上下文,英文叫做context,就是上面的文章,和下面的文章,即与你此刻,当前CPU运行有关<br />

系的内容,即那些你用到寄存器。所以,和上面的现场,是一个意思。<br />

保存寄存器的值,一般用的是push指令,将对应的某些寄存器的值,一个个放到堆栈中,把对<br />

应的值压入到堆栈里面,即所谓的压栈。<br />

然后待被调用的子函数执行完毕的时候,再调用pop,把堆栈中的一个个的值,赋值给对应的那<br />

些你刚开始压栈时用到的寄存器,把对应的值从堆栈中弹出去,即所谓的出栈。<br />

其中保存的寄存器中,也包括lr的值(因为用bl指令进行跳转的话,那么之前的pc的值是存在<br />

lr中的),然后在子程序执行完毕的时候,再把堆栈中的lr的值pop出来,赋值给pc,这样就<br />

实现了子函数的正确的返回。<br />

3.5.2. 传递参数<br />

C语言进行函数调用的时候,常常会传递给被调用的函数一些参数,对于这些C语言级别的参数,<br />

被编译器翻译成汇编语言的时候,就要找个地方存放一下,并且让被调用的函数能够访问,否则<br />

就没发实现传递参数了。对于找个地方放一下,分两种情况。<br />

一种情况是,本身传递的参数就很少,就可以通过寄存器传送参数。<br />

因为在前面的保存现场的动作中,已经保存好了对应的寄存器的值,那么此时,这些寄存器就是<br />

空闲的,可以供我们使用的了,那就可以放参数,而参数少的情况下,就足够存放参数了,比如<br />

参数有2个,那么就用r0和r1存放即可。(关于参数1和参数2,具体哪个放在r0,哪个放在r1,<br />

就是和APCS中的“在函数调用之间传递/返回参数”相关了,APCS中会有详细的约定。感兴趣<br />

的自己去研究。)<br />

但是如果参数太多,寄存器不够用,那么就得把多余的参数堆栈中了。<br />

即,可以用堆栈来传递所有的或寄存器放不下的那些多余的参数。<br />

3.5.3. 举例分析 C 语言函数调用是如何使用堆栈的<br />

对于上面的解释的堆栈的作用显得有些抽象,此处再用例子来简单说明一下,就容易明白了:<br />

用:<br />

arm-inux-objdump –d u-boot > dump_u-boot.txt<br />

可以得到dump_u-boot.txt文件。该文件就是中,包含了u-boot中的程序的可执行的汇编代<br />

码,<br />

其中我们可以看到C语言的函数的源代码,到底对应着那些汇编代码。<br />

下面贴出两个函数的汇编代码,<br />

一个是clock_init,<br />

另一个是与clock_init在同一C源文件中的,另外一个函数CopyCode2Ram:<br />

33d0091c :<br />

33d0091c: e92d4070 push {r4, r5, r6, lr}

Hooray! Your file is uploaded and ready to be published.

Saved successfully!

Ooh no, something went wrong!