引导中的模拟 :: 梦想风暴
来源: BlogBus 原始链接: http://www.blogbus.com:80/blogbus/blog/diary.php?diaryid=202366 存档链接: https://web.archive.org/web/20041110185533id_/http://www.blogbus.com:80/blogbus/blog/diary.php?diaryid=202366
梦想风暴 一个小程序员的信口开河 <<<好了伤疤忘了疼 | 主页 | 成功、自信、快乐>>> 引导中的模拟 2004-06-01 Linux的引导代码(Linux源码目录下的arch/i386/boot/setup.S)中有这样一段:
NOTE: For high loaded big kernels we need a
jmpi 0x100000,__KERNEL_CS
but we yet haven't reloaded the CS register, so the default size
of the target offset still is 16 bit.
However, using an operand prefix (0x66), the CPU will properly
take our 48 bit far pointer. (INTeL 80386 Programmer's Reference
Manual, Mixing 16-bit and 32-bit code, page 16-6)
.byte 0x66, 0xea # prefix + jmpi-opcode code32:.long 0x1000 # will be set to 0x100000
for big kernels
.word __KERNEL_CS 它出现在刚刚进入保护模式之后,从注释可以看出,这是一段模拟代码,模拟的是 jmpi 0x100000,__KERNEL_CS 认可手法容易,认可动机难。 顺藤摸瓜,根据注释,我找到了《INTEL 80386 Programmer's Reference Manual》。第16章讲的是如何将16位代码同32位代码混和起来。我从16.2节我得到了一些有用的信息: 80386有这样两个指令前缀,正是它们的存在,才使得在一个段中混和32位和16位操作成为了可能。它们是: operand-size前缀 66H address-size前缀 67H 这两个前缀可以反转缺省的大小,就是16位变成32位,32位变成16位,从而为混合创造条件。看一下手册中提到的这个MOV mem, reg(这是常见INTEL汇编格式,而前面Linux用的是AT&T汇编格式)的例子: 在32位段内: 1 通常是从32位寄存器中移动32位到内存的32位有效地址中 2 如果使用operand-size前缀,就是从16位寄存器中移动16位到内存的32位有效地址中 3 如果使用address-size前缀,就是从32位寄存器中移动32位到内存的16位有效地址中 4 如果同时使用address-size前缀和operand-size前缀,就是从16位寄存器中移动16位到内存的16位有效地址中 在16位段内: 1 通常是从16位寄存器中移动16位到内存的32位有效地址中 2 如果使用operand-size前缀,就是从32位寄存器中移动32位到内存的16位有效地址中 3 如果使用address-size前缀,就是从16位寄存器中移动16位到内存的32位有效地址中 4 如果同时使用address-size前缀和operand-size前缀,就是从32位寄存器中移动32位到内存的32位有效地址中 好像一段绕口令,回头来看前面的问题。 虽然经过一系列的努力,代码已经进入到保护模式之中,但刚刚打下的天下哪是那样太平,CS就是一个实模式残留下来的余孽,因为刚刚进入到保护模式社会,还没来得及对它进行保护模式改造。当大家已经进入保护模式的康庄大道,它还默守着实模式的陈规。既然已经进入了保护模式社会,把还处于实模式社会的CS请进来就成了当务之急,毕竟在Intel的世界中,CS还是个举足轻重的家伙。 我们需要的是32位的地址模式,而CS只能给我们16位。这时,混和16位与32位的方法就有了用武之地。 一个简单的跳转就可以重新加载CS的内容,套用上面证据,为16位的代码加上66H,16位就成了32位,于是CS得到了浴火重生的机会。 直接把jmp指令写在程序里,还在16位下的CS只能带给CPU得到的只能是一个16位的操作,于是就有了这种模拟的写法。 dreamhead 发表于 2004-06-01 09:20 引用Trackback(0) | 编辑 Comments 发表评论 最近更新 成为开发者 当Java遭遇OUT参数 新的开始 身体最重要 Hello Velocity之后 Hello Velocity 对象的生命 高手的煽动 XML与堆栈 Meta的乐趣