花费了无数时间,可是仍然在原地打转。
Assembling: protect.asm
protect.asm(49) : error A2024:
protect.asm(53) : error A2008: : in directive
Jump16(2): Macro Called From
protect.asm(53): Main Line Code
protect.asm(53) : error A2206:
Jump16(3): Macro Called From
protect.asm(53): Main Line Code
错误如上,一个错误是 lgdt Qword PTR GDTPTR(49行),还有一个 Jump16 <code_sel><OFFSET begin>(53行)
代码如下
由于进入了保护模式,所以不能mov ax,msg来打印了,所以那一句注释掉了。可是那两句一个是加载伪GDT,另一个是直接写入的段间跳转,怎么会不对呢?更何况那两句是直接从书上抄来的。下午要试一试全用书上的会不会还是这样错。可惜了我反反复复看80x86和自己动手两本书这么多天才写出的……
不过救剩最后一层窗户纸了!捅破它!
14:48
太开心了……书上的例程也是一样的错误……这说明是编译器的问题,不是我的问题啦!哈哈,开心,那么只要……呃……还是得解决怎么编译啊。
15:30
解决一个问题!lgdt要加载fword,因为伪GDTR是48位的!呵呵,原来就没有注意它是48位的,就是看见书上用了qword,自己就用了。刚刚在网上看到了解释:
lgdt 和 lidt 是系统服务的特权指令, 只能在 ring0层运行,masm32的编译器也识别这条指令, 所以在正常的 exe 文件中这条指令是不能成功编译的,会有如下错误提示:
error A2085: instruction or register not accepted in current CPU mode
(其他的编译器应该没有这个问题)
你可以按照驱动程序的格式(即加上DriverEntry ...)作为启动地址,这类代码就能正确的编译,
这类代码一共4个, 即 sgdt, sidt, lgdt, lidt.
前面两个在用户模式是可以正常编译的,而且对长度的要求并不严格,如下格式都可以正常编译,而且产生的代码完全相同.
sgdt qword ptr [esp + gdt]
sgdt fword ptr [esp + gdt]
sidt qword ptr [esp + idt]
sidt fword ptr [esp + idt]
但对于 lgdt, lidt 则只能使用 fword
lgdt fword ptr [esp + gdt]
lidt fword ptr [esp + idt]
另外在 IDA 中分析这些代码, 给出的都是错误结果, 全部用 qword 来解释.
例如 lgdt fword ptr [esp + gdt]
在 IDA 中 一定被反编译成
lgdt qword ptr [esp + gdt]
或
gdt = qword
lgdt [esp + gdt]
对前面不经过思考就胡乱答题,表示谦意.