📄 program-kernel-boot-comment.html
字号:
<!doctype html public "-//w3c//dtd html 4.0 transitional//en">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=gb2312">
<meta name="Author" content="Edward Fu">
<meta name="GENERATOR" content="Mozilla/4.05 [zh-CN] (X11; I; Linux 2.1.127 i686) [Netscape]">
<title>Freesoft Linux FAQ -- 内核原代码boot.s部分的注释</title>
</head>
<body>
|
<br>| boot.s
<br>|
<br>| boot.s is loaded at 0x7c00 by the bios-startup routines, and moves
itself
<br>| out of the way to address 0x90000, and jumps there.
<br>|
<br>| It then loads the system at 0x10000, using BIOS interrupts. Thereafter
<br>| it disables all interrupts, moves the system down to 0x0000, changes
<br>| to protected mode, and calls the start of system. System then must
<br>| RE-initialize the protected mode in it's own tables, and enable
<br>| interrupts as needed.
<br>|
<br>| NOTE! currently system is at most 8*65536 bytes long. This should
be no
<br>| problem, even in the future. I want to keep it simple. This 512 kB
<br>| kernel size should be enough - in fact more would mean we'd have
to move
<br>| not just these start-up routines, but also do something about the
cache-
<br>| memory (block IO devices). The area left over in the lower 640 kB
is meant
<br>| for these. No other memory is assumed to be "physical", ie all memory
<br>| over 1Mb is demand-paging. All addresses under 1Mb are guaranteed
to match
<br>| their physical addresses.
<br>|
<br>| NOTE1 abouve is no longer valid in it's entirety. cache-memory is
allocated
<br>| above the 1Mb mark as well as below. Otherwise it is mainly correct.
<br>|
<br>| NOTE 2! The boot disk type must be set at compile-time, by setting
<br>| the following equ. Having the boot-up procedure hunt for the right
<br>| disk type is severe brain-damage.
<br>| The loader has been made as simple as possible (had to, to get it
<br>| in 512 bytes with the code to move to protected mode), and continuos
<br>| read errors will result in a unbreakable loop. Reboot by hand. It
<br>| loads pretty fast by getting whole sectors at a time whenever possible.
<br>| 1.44Mb disks: sectors = 18
<br>| 1.2Mb disks:
<br>| sectors = 15
<br>| 720kB disks:
<br>| sectors = 9
<p>.globl begtext, begdata, begbss, endtext, enddata, endbss
<br>.text
<br>begtext:
<br>.data
<br>begdata:
<br>.bss
<br>begbss:
<br>.text
<p>BOOTSEG = 0x07c0
<br>INITSEG = 0x9000
<br>SYSSEG = 0x1000
| system loaded at 0x10000 (65536).
<br>ENDSEG = SYSSEG + SYSSIZE | SYSSIZE在Makefile中定义的
^_^
<p>entry start
<br>start:
<br> mov
ax,#BOOTSEG | 现在应仍处在REAL MODE下.
<br> mov
ds,ax | 移动自身从BOOTSEG:0000到INITSEG:0000
<br> mov
ax,#INITSEG | 共512字节.
<br> mov
es,ax | 那么BOOT.S处在0x90000-0x90200.
<br> mov
cx,#256
<br> sub
si,si
<br> sub
di,di
<br> rep
<br> movw
<br> jmpi go,INITSEG
<br>go: mov ax,cs
<br> mov
ds,ax | 将DS,ES,SS均设为0x9000,所有数据都以
<br> mov
es,ax | 0x9000为段偏移.
<br> mov
ss,ax | 堆栈偏移0x9000
<br> mov
sp,#0x400 | 栈顶指针0x9000:0x0400,堆栈空间512bytes??
<br> mov
ah,#0x03 | read cursor pos
<br> xor
bh,bh
<br> int
0x10
<br> mov
cx,#24
<br> mov
bx,#0x0007 | page 0, attribute 7 (normal)
<br> mov
bp,#msg1 | 显示Loading System
...
<br> mov
ax,#0x1301 | write string, move cursor
<br> int
0x10
<p>| ok, we've written the message, now
<br>| we want to load the system (at 0x10000)
<p> mov
ax,#SYSSEG
<br> mov
es,ax | segment
of 0x010000
<br> call read_it
| 读内核到0x10000
<br> call kill_motor
| 杀了软驱!? ^_^
<p>| if the read went well we get current cursor position ans save it for
<br>| posterity.
<p> mov
ah,#0x03 | read cursor pos
<br> xor
bh,bh
<br> int
0x10
| save it in known place, con_init fetches
<br> mov
[510],dx | it from 0x90510.
<p>| now we want to move to protected mode ...
<p> cli
| no interrupts allowed !
<p>| first we move the system to it's rightful place
<p> mov
ax,#0x0000
<br> cld
| 'direction'=0, movs moves forward
<br>do_move:
<br> mov
es,ax | destination
segment
<br> add
ax,#0x1000
<br> cmp
ax,#0x9000
<br> jz
end_move
<br> mov
ds,ax | source
segment
<br> sub
di,di | 置零,地址为0x1000:0000
<br> sub
si,si | 置零,地址为0x9000:0000
<br> mov
cx,#0x8000 | cx的作用是计数器
<br> rep
<br> movsw
<br> j
do_move | 将位于低端0x1000:0000的内核移到内存
<br>
| 高端0x9000:0000,覆盖了boot.S !?
<p>| then we load the segment descriptors
<p>end_move:
<p> mov
ax,cs | right,
forgot this at first. didn't work :-)
<br> mov
ds,ax
<br> lidt idt_48
| idt_48和gdt_48都是一个3个word长的数据结构
<br> lgdt gdt_48
| 第一个字说明(Global || Interrupt) Descriptor
<br>
| Table有多长,因为每个Table是四个字长,所以
<br>
| 可以得出整个DescriptorTable的entries.(见下)
<br>
| 后两个字指出DT的具体位置.
<br>
| idt_48是0,0,0;应表示没有中断描述符entries.
<br>
| gdt_48有256个入口,第一个是个空入口,然后
<br>
| 定义了一个code段和一个data段.基址都是
<br>
| 0x00000000, !?那里是什么东西???
<br>
| *** 0x00000000 != 0x0000:0000 ***
<p>| that was painless, now we enable A20
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -