Kernel 2.4.0 之 head.S 为何用两次 jmp 刷新 EIP 寄存器(3)

CPU内部正在执行当前指令的同时,EIP指向的是下一条指令。回忆上文所讲内容,开始进入head.S时EIP=0x100000。下面按照CPU取指令->执行指令的过程来分步讲解。

当CPU取指令并执行 movl %eax,%cr0 时,EIP指向 jmp 1f ,即EIP=0x100039。注意当movl指令执行完后,分页机制开启了,下一次取指令时EIP不能只进行分段变换,还要进行分页变换。对照着页目录和页表,EIP=0x100039这个虚拟地址经过分段+分页变换后的结果是物理地址0x100039,这是下一次取指令的地方。

从上面可以看到,页表和页目录的设置非常巧妙,0x100039这个虚拟地址不管是只经过分段变换还是经过分段+分页变换,得到的物理地址是一样的,并且从数值上讲虚拟地址=线性地址=物理地址。你可以自己拿笔算算。

接下来,CPU取指令并执行 jmp 1f ,同时EIP继续自增指向 movl $1f,%eax ,即EIP=0x10003b。仔细看机器码,jmp 1f 这条语句被汇编成了eb00,eb表示相对跳转,相对偏移量为00。jmp相对跳转指令将相对偏移量00加到EIP上得到跳转的目的地址0x10003b,EIP数值上不变(EIP=0x10003b),所以这个jmp没什么作用。EIP经过分段+分页后得到物理地址0x10003b,这是下一次取指令的地方。

接下来,CPU取指令并执行 movl $1f,%eax ,EIP指向 jmp *%eax,EIP=0x100040。语句中1f是个地址标号,代表一个绝对地址,一开始汇编后它的值为0x42,链接后加上0xC0100000变成0xC0100042,把0xC0100042这个数置入eax寄存器。movl指令执行后eax=0xC0100042。EIP虚拟地址化成物理地址是0x100040,这是下一次取指令的地方。

接下来,CPU取指令并执行 jmp *%eax,EIP指向 lss stack_start,%esp ,EIP=0x100042。jmp指令的机器码是ff,代表绝对跳转,将eax中目的地址的值直接覆写到EIP。从此EIP=0xC0100042。

接下来,CPU要去EIP处取指令,它把EIP=0xC0100042经过分段+分页变换,根据页表和页目录的设置,得到物理地址0x100042,取得指令 lss stack_start,%esp 开始执行,同时EIP自动增加指令长度的数值变为EIP=0xC0100049。页表和页目录表都设置的非常巧妙,虚拟地址X将映射到物理地址X,虚拟地址3G+X也将映射到的物理地址X,这里不展开讲。

从此之后EIP将从0xC0100049开始逐渐递增,经过分段+分页映射到物理地址,虚拟地址和物理地址之间差了3G,内核的内存管理初见雏形。

回想上面第一个jmp,它的没有任何作用,不产生任何影响,可以删掉。 如果也把第二个jmp删掉会如何呢?那就可以预见,EIP将会继续保持从0x1000xx这样的模式递增,不会变成0xC01000xx这样。因为页目录和页表都设置的非常巧妙,0x1000xx和0xC01000xx会换算成同一个物理地址,所以这两种虚拟地址等效,可以互相替代。即使一直按照0x1000xx的格式取指令也不会出现任何问题,因为这和用0xC01000xx取到的指令是完全一样的,毕竟两者都能换算成同样的物理地址。所以这个地方不跳转也是可以的,即第二个jmp也可以删掉。 所以即使把两个jmp全删了,都不会产生影响。在后面的代码中,自然会有别的代码替它们完成将EIP置成0xC01000xx的任务。

内核在执行到head.S line 252时会执行下面的指令:

ljmp $(__KERNEL_CS),$1f 1: movl $(__KERNEL_DS),%eax

ljmp后面跟上两个操作数,这是绝对跳转的写法,并且是远跳转,CS和EIP都将被覆写。在汇编器汇编时,1f这个标号不是相对偏移,而是绝对地址,既然是绝对地址,那必然会被链接器修改,它原先是0x172,在链接时被改成了0xc0100172。再者,_KERNELCS=0x10,所以这个指令相当于 ljmp $0x10,$0xc0100172 。这条指令将0x10置入CS,将0xC0100172置入EIP,这样EIP在这里变成了0xC01000xx这种格式。即使之前两次都不跳转,EIP迟早会变成0xC01000xx这个样子。又如果前面真的发生了跳转,EIP在那时已经被置成0xC01000xx这个样子,那么到了此处EIP还是免不了被重新覆盖一次,反正这个地方CS和EIP必须被重新赋一次值,不管以前EIP是什么样子。

注:我将两个jmp都删了然后重新编译内核,系统启动完全正常。

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/54af4a66bd5ed00cc37642fae3cbd739.html