4)调整内存布局

储存信息

代码继续执行到setup.s

1
2
3
4
5
6
7
start:
mov ax,#0x9000 ; this is done in bootsect already, but...
mov ds,ax
mov ah,#0x03 ; read cursor pos
xor bh,bh
int 0x10 ; save it in known place, con_init fetches
mov [0],dx ; it from 0x90000.

int 0x10是触发 BIOS 提供的中断服务,具体来说是调用显示服务相关的中断处理程序,而 ah 寄存器被赋值为 0x03 表示显示服务里具体的读取光标位置功能这一个子服务。

这个 int 0x10 中断程序执行完毕并返回时,将会在 dx 寄存器里存储好光标的位置,具体说来其高八位 dh 存储了行号,低八位 dl 存储了列号。

这里说明一下:计算机在加电自检后会自动初始化到文字模式,在这种模式下,一屏幕可以显示 25 行,每行 80 个字符,也就是 80 列。

那下一步 mov [0],dx 就是把这个光标位置存储在 [0] 这个内存地址处。注意,前面我们说过,这个内存地址仅仅是偏移地址,还需要加上 ds 这个寄存器里存储的段基址,最终的内存地址是在 0x90000 处,这里存放着光标的位置,以便之后在初始化控制台的时候用到。

接下来都一样,储存各种信息:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
比如获取内存信息。
; Get memory size (extended mem, kB)
mov ah,#0x88
int 0x15
mov [2],ax
获取显卡显示模式。
; Get video-card data:
mov ah,#0x0f
int 0x10
mov [4],bx ; bh = display page
mov [6],ax ; al = video mode, ah = window width
检查显示方式并取参数
; check for EGA/VGA and some config parameters
mov ah,#0x12
mov bl,#0x10
int 0x10
mov [8],ax
mov [10],bx
mov [12],cx
获取第一块硬盘的信息。
; Get hd0 data
mov ax,#0x0000
mov ds,ax
lds si,[4*0x41]
mov ax,#INITSEG
mov es,ax
mov di,#0x0080
mov cx,#0x10
rep
movsb
获取第二块硬盘的信息。
; Get hd1 data
mov ax,#0x0000
mov ds,ax
lds si,[4*0x46]
mov ax,#INITSEG
mov es,ax
mov di,#0x0090
mov cx,#0x10
rep
movsb

最终这些信息就存在了内存中固定的地方,可以当作全局变量:

调整内存布局

后续不再使用BIOS的中断,所以关闭中断。cli就是关闭中断

1
cli         ; no interrupts allowed ;

继续向下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
; first we move the system to it's rightful place
mov ax,#0x0000
cld ; 'direction'=0, movs moves forward
do_move:
mov es,ax ; destination segment
add ax,#0x1000
cmp ax,#0x9000
jz end_move
mov ds,ax ; source segment
sub di,di
sub si,si
mov cx,#0x8000
rep movsw
jmp do_move
; then we load the segment descriptors
end_move:
...

同前面的原理一样,也是做了个内存复制操作,最终的结果是,把内存地址 0x10000 处开始往后一直到 0x90000 的内容,统统复制到内存的最开始的 0 位置

此时完成了整个操作系统的搬运和调整:

  • 栈顶地址仍然是 0x9FF00 没有改变。
  • 0x90000 开始往上的位置,原来是 bootsect 和 setup 程序的代码,而此时 bootsect 的代码现在已经被一些临时存放的数据,如内存、硬盘、显卡等信息,覆盖了一部分。
  • 内存最开始的 0 到 0x80000 这 512K 被 system 模块给占用了,之前讲过,这个 system 模块就是除了 bootsect 和 setup 之外的全部程序(head.s 作为开头,main.c 和其他文件紧随其后)链接在一起的结果,可以理解为操作系统的全部代码。

启动区运行完成后,就不会再次运行,所以使用的内存就被临时变量和system覆盖,重复利用这部分内存。


4)调整内存布局
https://carl-5535.github.io/2024/07/24/Linux0.11/4)调整内存布局/
作者
Carl Chen
发布于
2024年7月24日
许可协议