之前学习了操作系统如何加载到内存以及加载到内存的0x90000位置,又跳转去执行0x9000:go位置的命令
这次要学习的是操作系统怎么为程序访问内存的方式做初步规划的
接下来就继续看操作系统最开始的代码,偏移量为go的这部分
即接下来cpu开始执行的是go标签这个位置的代码
go: mov ax,cs
mov ds,ax
mov es,ax
mov ss,ax
mov sp,#0xFF00
ds,es,ss寄存器的值都被赋为cs寄存器中的值
sp寄存器的值为0xff00
cs寄存器是代码段寄存器,cpu即将要执行的代码在内存中的位置就是又cs:ip这组寄存器配合指向的。cs是基地址,ip是偏移地址
之前执行了jmpi go,0x9000
,这条命令执行后cs的值被赋成0x9000,ip的值被赋成go标签
现在又把ds,es,ss中的值都赋成cs寄存器中的值,即0x9000
es扩展段寄存器
ss栈寄存器,要配合栈顶指针sp表示此刻栈顶地址。而且此时sp被赋值为0xff00,所以目前的栈顶地址就是,0x9ff00
这里涉及到实模式中的内容,段寄存器的内容左移4位(16进制表示二进制的左移4位就是左移一位),所以这里是 0x90000+0xff00
现在就可以知道图中栈顶地址的来路了
cpu访问内存的三种途径
- 访问代码cs:ip
- 访问数据ds:xx
- 访问栈ss:sp
通过之前的内容可以知道,到这里cs,ds,ss全部赋值为0x9000,指向内存地址0x90000
栈顶指针sp的值为0xff00,栈顶指向的内存地址为0x9ff00
之后的压栈和出栈地址以这个为基准
这部分就是把代码段寄存器cs、数据段寄存器ds、栈段寄存器ss和栈指针寄存器sp分别设置好了值方便后续使用
从操作系统的角度来看,这些操作系统代码做的事就是初步规划了内存,给程序如何访问代码、数据、栈制定了规则。
其中,访问代码和访问数据的规划方式是设置一个基地址;访问栈就是把栈顶指针指向一个远离代码位置的地方(就是栈的地方)
回顾
回顾一下之前的内容:
512字节编译好的二进制代码从硬盘移到内存(0x7c00),又移到0x90000
数据段寄存器ds和代码段寄存器cs被设置为0x9000,这是为了跳转代码和访问内存数据设置了一个内存地址的基地址,方便代码的编写
栈指针寄存器sp被设置为0xff00(上一步中栈段寄存器ss也被设置为0x9000),此时栈顶指针指向的内存地址被设置为0x9ff00
但是操作系统的代码不止这启动区的512字节,剩下的代码还在硬盘中。所以接下来就是学习把还在硬盘中的操作系统代码放到内存中