做好访问内存的最基础准备工作
前文提要
前文讲了操作系统512字节的数据先从硬盘的启动区移动到了内存0x7c00处,然后又立刻被移动到 0x90000 处,并且跳转到 0x90000 加上 go 这个标签所代表的偏移量。
本节问题:
- 操作系统是怎么为程序访问内存的方式做初步规划的?
go标签之后
go: mov ax,cs
mov ds,ax
mov es,ax
mov ss,ax
mov sp,#0xFF00
代码解释:
这段代码是在 x86 汇编语言中编写的,它的作用是将代码段寄存器 (CS) 的值复制到数据段寄存器 (DS)、扩展段寄存器 (ES) 和堆栈段寄存器 (SS) 中。这样做的原因是为了让数据段、扩展段和堆栈段都指向代码段,以便在代码段中读取和修改数据。
最后一行将堆栈指针设置为 0xFF00,这意味着堆栈从这个地址开始进行操作。
问题一:操作系统最开始这几行代码要完成什么事情?
要回答这个问题,需要先解决以下问题:
(一)这些寄存器的作用是什么?
- cs寄存器 ——> 代码段寄存器
graph LR
cs("cs寄存器") --> code_segment("代码段寄存器")
eg:cs:ip配合指向的位置 ——> CPU 即将要执行的代码在内存中的位置
graph LR
cs("cs:ip配合指向的位置")-->cpu
cpu("CPU即将要执行的代码在内存中的位置")-->memory
jmpi go,0x9000
相当于
cs = 0x9000
ip = go
cs寄存器 ——> 0x9000 ip寄存器 ——> go标签的偏移地址
- ds寄存器 ——> 数据段寄存器 ——> 访问内存数据是的基地址
| 寄存器 | 位置 | 值 |
|---|---|---|
| ds | 0x7c00 | 0x07c0 |
| ds | 0x90000 | 0x9000 |
-
es寄存器 ——> 扩展段寄存器 ——> 在计算机系统中存储和管理地址空间
-
ss寄存器 ——> 栈段寄存器 ——> 配合栈指针寄存器 sp 来表示此时的栈顶地址
(二)CPU访问内存的三种途径
- 访问代码的 cs:ip
- 访问数据的 ds:XXX
- 访问栈的 ss:sp
小结:mov这一部分的代码是为了给各个寄存器设置值,方便后续使用
站在操作系统的角度,问题一中,操作系统所做的事就是初步规划内存,制定“规则”,方便程序执行 访问代码、访问数据、访问栈 制定规则。
其中:
访问代码和访问数据 ——> 规划方式 ——> 设置一个基址 访问栈 ——> 栈顶指针 ——> 指向一个远离代码位置的地方
总结
栈顶地址被设置为了 0x9FF00,具体表现为栈段寄存器 ss 为 0x9000,栈指针寄存器 sp 为 0xFF00。
最后
笔记整理:千石
内容来源:极客时间《Linux源码趣读》学习笔记 Day 3
支持:点赞、评论、收藏