关于linux v0.01 bootsect.S
最近在看linux 0.01的源码,由于2.6.11及以上版本的bootsect.S没什么用,是开始学习linux代码的好地方,所以我选择追踪linux的第一个版本。 :P
我在 bootsect.S 有一些问题。以下是 bootsect.S linux v 0.01 中的一些代码。
PS 第一个版本的汇编代码使用 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
enable A20 访问16mb 物理内存。
设置 cr0 PE 位进入保护模式
跳转到 0x000000
以下是系统的 Makefile:
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 是不是很奇怪?
Recently I'm looking at the linux 0.01 source code, since the bootsect.S in 2.6.11 and upper version is useless and it is a good place to start learning linux code, therefore I choose to trace the first version of linux. :P
I have some question in bootsect.S. The following is some of the code in bootsect.S linux v 0.01.
P.S the first version assembly code is using intel syntax instead of 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
The booting process seems to be like the following:
move the bootloader code from 0x7c00 to 0x9000
jumps to 0x9000
set the segment registers.
load the system code to 0x10000
(the system code contains boot/head.S and init/main.c according to the Makefile)load temporary gdt and idt with lgdt and lidt
enable A20 to access the 16mb physical memory.
set cr0 PE bit to go to protected mode
jump to 0x000000
the following is the Makefile for system:
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
It seems like that the head.S and main.c is link together as the system binary which the bootsect loads into memory.
My question is if the system code(which entry is head.S/startup_32 ) is loaded in 0x10000 than why not jumps to 0x10000 instead jumps to 0x000000?
Isn't it weird to jump to 0x0 since there is no code loaded inside there??
the following is the link to download the source code:
https://docs.google.com/viewer?a=v&pid=explorer&chrome=true&srcid=0B1F0m2rUn8BYMjQ4ZDQxZTUtODI5My00MGZiLTgwZDQtM2ZiZWQ2ZWQxYzIx
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
答案如下:
这是与之相关的代码:
如果您仔细观察代码,您会发现它确实开始使用 ES=0,DI=0(目标)和 DS=0x1000,SI= 执行 REP MOVSW 0(源),也就是说,它将内容从 0x10000(=DS*0x10+SI) 移动到 0(=ES*0x10+DI)。
Here's the answer:
and here's the code that goes with it:
If you look closely at the code, you'll notice that it indeed starts doing REP MOVSW with ES=0,DI=0 (destination) and DS=0x1000,SI=0 (source), that is, it moves stuff from 0x10000(=DS*0x10+SI) to 0(=ES*0x10+DI).