jmpi 0,8相当于把0赋给ip,8赋给cs,然后cs就去gdt表项中找相应的基址,那么这个基址是怎么找到的呢?这个和gdt表项的结构有关和setup.s中gdt代码段的内容有关,下面我分步骤来说一下:
1)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
首先gdt用.word 0,0,0,0
开辟了8个字节的空间,然后又从0x7ff一直到0x00c0又开辟了8个字(16个字节,128位)的空间。所以cs=8就相当于是从0x07ff开始读。
2)根据李治军老师的说法+我自己的理解,gdt开辟了8个字节的0空间后,下面又开辟了两个表项,每个表项4个字(8个字节,64位)。所以cs=8相当于选择了第一个表项的内容。第一个表项的内容显然就是:
0x00c0 | 0x9a00 |
---|---|
0x0000 | 0x07ff |
然后我们对照gdt表项的结构来读取我们的基址,gdt表项结构如下:
第二层是表项的31~
0位,第一层是表项的63~32位,这样,段基址15~
0位=0x0000,段基址23~
16=0x00(也就是0x9a00的低8位),段基址的31~
24位就是0x00(0x00c0的高8位),所以,读到的基地址就是0x00000000
3)最后,由于ip=0,所以最终会跳转到内存中的地址0处
- 写在最后
这个例子也提醒了我,读Linux源码时按小端法去读(低位字节放在低地址处)