最近我在看Linux0.01源代码,因为2.6.11和更高版本中的bootsect.s是无用的,它是开始学习Linux代码的好地方,所以我选择跟踪Linux的第一个版本。:p页
我在bootsect s.s中有一些问题,下面是bootsect.slinuxv0.01中的一些代码。
第一版汇编代码使用的是intel语法,而不是at&t。
mov ax,#0x0001 | protected mode (PE) bit
lmsw ax | This is it!
jmpi 0,8 | jmp offset 0 of segment 8 (cs) which is the second entry of the gdt.
GDT公司:
.word 0,0,0,0 | dummy
.word 0x07FF | 8Mb - limit=2047 (2048*4096=8Mb)
.word 0x0000 | base address=0
.word 0x9A00 | code read/exec
.word 0x00C0 | granularity=4096, 386
.word 0x07FF | 8Mb - limit=2047 (2048*4096=8Mb)
.word 0x0000 | base address=0
.word 0x9200 | data read/write
.word 0x00C0 | granularity=4096, 386
引导过程如下所示:
将引导加载程序代码从0x7c00移动到0x9000
跳到0x9000
设置段寄存器。
将系统代码加载到0x10000
(根据makefile,系统代码包含boot/head.s和init/main.c)
用lgdt和lidt加载临时gdt和idt
启用A20访问16MB物理内存。
将CR0 PE位设置为进入保护模式
跳转到0x000000
以下是系统的生成文件:
tools/system:
boot/head.o init/main.o \
$(ARCHIVES) $(LIBS)
$(LD) $(LDFLAGS) boot/head.o init/main.o \
$(ARCHIVES) \
$(LIBS) \
-o tools/system > System.map
看起来head.s和main.c作为系统二进制文件连接在一起,bootsect将其加载到内存中。
我的问题是,如果系统代码(哪个条目是head.s/startup_32)加载在0x10000中,那么为什么不跳到0x10000而不是跳到0x000000?
跳转到0x0是不是很奇怪,因为里面没有加载代码?是吗?
以下是下载源代码的链接:
https://docs.google.com/viewer?a=v&pid=explorer&chrome=true&srcid=0B1F0m2rUn8BYMjQ4ZDQxZTUtODI5My00MGZiLTgwZDQtM2ZiZWQ2ZWQxYzIx
最佳答案
答案如下:
| It then loads the system at 0x10000, using BIOS interrupts. Thereafter
| it disables all interrupts, moves the system down to 0x0000, ...
下面是相应的代码:
cli | no interrupts allowed !
| 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
j do_move
如果仔细观察代码,您会注意到它确实开始执行rep movsw,es=0,di=0(目标)和ds=0x1000,si=0(源),也就是说,它将数据从0x10000(=ds*0x10+si)移动到0(=es*0x10+di)。
关于linux - 关于linux v0.01 bootsect.S,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/7626861/