为了方便不同平台的演示,这次我们添加一个新的平台, 是ARM versatilepb 平台的arm926ej-s处理器, 这是一款比较老的ARM处理器 CPU是A9系列的ARM926EJ-S, ARMv5TE架构; 我们来看看这个CPU起始的地址,并且考虑如何给我们的Alice OS初始化一个临时的栈~
Versatilepb & ARM926EJ-S
我们仿照vexpress-a9建一个新的平台,并用类似的方式看看启动之后的LR地址:
1 | # Another shell: |
可以发现,这次的LR (R14)是0x10008了, 说明启动是从0x10000开始执行的,
所以我们现在知道, vexpress-a9是从0x60010000开始执行, 而versatilepb是从0x00010000开始执行的
接下来让我们给他们都给一个初始的栈吧
Init Stack
我们在汇编里面声明一段空间,并把它当做我们的内核栈:
1 | .global entry |
我们在代码段的最下面声明一个4K大小的空间,并将它连接到”.stack”段里面:
1 | .bss : { *(.bss COMMON) } |
我们可以看一下,r0到r5里面的值都是多少:
- r0是我们计算出来并赋值给sp的栈;
- r1是直接加载
.L_stack_start
这个tag得到的地址; - r2是从linker script中取得的
kernel_stack_start
这个symbol地址; - r3是赋值之后的sp;
- r4是push一次之后的sp;
- r5是程序一开始的PC;
1 | alice@MacAlice ‹ 521074d ●● › : ~/Codes/alice-os |
我们计算栈的方式是这样: 假设启动这部分代码最长不超过4K大小, 那我空4K出来将当前PC后12位清零, 加上两个4K页就是我的栈底。
但是我们直接Load Symbol会发现, 无论是tag还是从linker script取出来的 地址都是0x80002000。这是由于我们linker一开始给的其实地址是80002000, 导致我们的栈变成了这样。
但是至少我们了解了,代码开始往后2个页就是栈底,所以我们使用 0x60012000作为栈底是没有问题的!
通过 x 命令我们也看到了,push一次之后,栈里确实存了我们要的数据。
那么接下来,我们就考虑如何更优雅并且正确的设置栈,尽快从汇编跳到C代码吧!