stuman 发表于 2014-04-29 18:07

如何跳入保护模式

; 初始化 32 位代码段描述符
        xor        eax, eax
        mov        ax, cs
        shl        eax, 4
        add        eax, LABEL_SEG_CODE32
        mov        word , ax
        shr        eax, 16
        mov        byte , al
        mov        byte , ah
以上是对某个全局代码段描述符中基地址的设置,其中LABEL_SEG_CODE32是进入保护模式后执行代码处的标号,跳入保护模式的命令为:jmp        dword SelectorCode32:0
其中选择符SelectorCode32对应于描述符LABEL_DESC_CODE32。

我对以上代码进行了修改,在对描述符LABEL_DESC_CODE32基地址的设置时没有加上标号LABEL_SEG_CODE32,即没有add        eax, LABEL_SEG_CODE32这段代码,然后jmp        dword SelectorCode32:LABEL_SEG_CODE32。为什么不对呢?我感觉逻辑上没什么错误呀,是不是语法上有错误?我使用的是nasm

l4rmbr 发表于 2014-04-29 18:41

回复 1# stuman


Hi, stuman,jmp      dword SelectorCode32:0
jmp      dword SelectorCode32:LABEL_SEG_CODE32为什么不对呢?我感觉逻辑上没什么错误呀,是不是语法上有错误?我使用的是nasm

不对是指?
事实上如果LABEL_SEG_CODE32不是0的话,你怎么能寄望他们的行为一样呢。

你用的是nasm, 那语法没错,有错编译应该也不会过吧。

stuman 发表于 2014-04-29 18:49

我说的“不对”是指使用jmp      dword SelectorCode32:LABEL_SEG_CODE32。代码运行时会出错。
我看其他书上有使用类似jmp      dword SelectorCode32:LABEL_SEG_CODE32的代码,所以我想修改这里的代码,想看看这种方式下怎么写才是正确的。当然那部分代码我没仔细看,所以我只好发帖提问了。
保护模式下,物理地址为描述符中段地址加eip中值,所以我觉得这两种方法应该都正确呀,因为最终物理地址都是一样的

l4rmbr 发表于 2014-04-29 18:50

本帖最后由 l4rmbr 于 2014-04-29 18:59 编辑

回复 3# stuman

LABEL_SEG_CODE32的值是? 运行出错信息是?


网上找到这么一段,你可以对照下,看你的情况跟这有什么不同:The most common form of mixed-size instruction is the one used when writing a 32-bit OS: having done your setup in 16-bit mode, such as loading the kernel, you then have to boot it by switching into protected mode and jumping to the 32-bit kernel start address. In a fully 32-bit OS, this tends to be the only mixed-size instruction you need, since everything before it can be done in pure 16-bit code, and everything after it can be pure 32-bit.

This jump must specify a 48-bit far address, since the target segment is a 32-bit one. However, it must be assembled in a 16-bit segment, so just coding, for example,

      jmp   0x1234:0x56789ABC       ; wrong!
will not work, since the offset part of the address will be truncated to 0x9ABC and the jump will be an ordinary 16-bit far one.

The Linux kernel setup code gets round the inability of as86 to generate the required instruction by coding it manually, using DB instructions. NASM can go one better than that, by actually generating the right instruction itself. Here's how to do it right:

      jmp   dword 0x1234:0x56789ABC         ; right
The DWORD prefix (strictly speaking, it should come after the colon, since it is declaring the offset field to be a doubleword; but NASM will accept either form, since both are unambiguous) forces the offset part to be treated as far, in the assumption that you are deliberately writing a jump from a 16-bit segment to a 32-bit one.

stuman 发表于 2014-04-29 19:04

LABEL_SEG_CODE32是保护模式下运行代码的最开始处标号,我是在虚拟机上运行的,出错信息没什么用
感谢楼上贴的英文,不过和我的问题无关
页: [1]
查看完整版本: 如何跳入保护模式