03.做好最最基础的准备工作

03.做好最最基础的准备工作

上回说到,操作系统的代码最开头的 512 字节的数据,从硬盘的启动区先是被移动到了内存 0x7c00 处,然后又立刻被移动到 0x90000 处,并且跳转到此处往后再稍稍偏移 go 这个标签所代表的偏移地址处。

图片

接下来,就继续把目光放在 go 这个标签的位置,跟着 CPU 的步伐往后看。

1
2
3
4
5
6
go: 
    mov ax,cs    
    mov ds,ax    
    mov es,ax    
    mov ss,ax    
    mov sp,#0xFF00

全都是 mov 操作,那好办了。

这段代码的直接意思很容易理解,就是把 cs 寄存器的值分别复制给 dses 和 ss 寄存器,然后又把 0xFF00 给了 sp 寄存器。

回顾下 CPU 寄存器图。

图片

cs 寄存器表示代码段寄存器,CPU 当前正在执行的代码在内存中的位置,就是由 cs:ip 这组寄存器配合指向的,其中 cs 是基址,ip 是偏移地址。

由于之前执行过一个段间跳转指令,还记得不?

1
jmpi go,0x9000

所以现在 cs 寄存器里的值就是 0x9000,ip 寄存器里的值是 go 这个标签的偏移地址。那这三个 mov 指令就分别给 ds、es 和 ss 寄存器赋值为了 0x9000。

ds 为数据段寄存器,之前我们说过了,当时它被复制为 0x07c0,是因为之前的代码在 0x7c00 处,现在代码已经被挪到了 0x90000 处,所以现在自然又改赋值为 0x9000 了。

es 是扩展段寄存器,仅仅是个扩展,不是主角,先不用理它。

ss 为栈段寄存器,后面要配合栈基址寄存器 sp 来表示此时的栈顶地址。

而此时 sp 寄存器被赋值为了 0xFF00 了,所以目前的栈顶地址就是 ss:sp 所指向的地址 0x9FF00 处。

图片

其实到这里,操作系统的一些最最最最基础的准备工作,就做好了。都做了些啥事呢?

  • 第一,代码从硬盘移到内存,又从内存挪了个地方,放在了 0x90000 处。

  • 第二数据段寄存器 ds 和代码段寄存器 cs 此时都被设置为了 0x9000,也就为跳转代码和访问内存数据,奠定了同一个内存的基址地址,方便了跳转和内存访问,因为仅仅需要指定偏移地址即可了。

  • 第三,栈顶地址被设置为了 0x9FF00,具体表现为栈段寄存器 ss 为 0x9000,栈基址寄存器 sp 为 0xFF00。栈是向下发展的,这个栈顶地址 0x9FF00 要远远大于此时代码所在的位置 0x90000,所以栈向下发展就很难撞见代码所在的位置,也就比较安全。这也是为什么给栈顶地址设置为这个值的原因,其实只需要离代码的位置远远的即可。

做好这些基础工作后,接下来就又该折腾了其他事了。

总结拔高一下,这一部分其实就是把代码段寄存器 cs数据段寄存器 ds栈段寄存器 ss 和栈基址寄存器 sp 分别设置好了值,方便后续使用。

再拔高一下,其实操作系统在做的事情,就是给如何访问代码,如何访问数据,如何访问栈进行了一下内存的初步规划。其中访问代码和访问数据的规划方式就是设置了一个基址而已,访问栈就是把栈顶指针指向了一个远离代码位置的地方而已。

图片

updatedupdated2024-05-102024-05-10