最近在学习保护模式的时候构建TSS任务段的时候发现了这个问题。
首先找TSS地址构建TSS段描述符。 用windbg写入gdt表中。
用jmp来跳转的时候程序执行顺利。 jmp回来的TSS选择子是提前查看好的(即原来TR寄存器存储的值)
但是用call来调用的时候, 程序可以跳转到目标裸函数位置, 寄存器也全部更换完成。 但iretd指令执行后直接蓝屏。
查看以前的文章, 也参考了intel的官方文档。就是找不出问题所在。
跪求指导~ 感激不尽~~
偶然间看见intel对于iretd的描述如下:
我的CPU就是64位的, 不太清楚跟这个IA-32e mode是不是一个概念。 另外我是用了win7系统搭建了一个XP sp3虚拟机来进行练习的。
代码如下:(tss描述符:0000E912`FF0C0068)
char pretr[6] = {0x78, 0x56, 0x34, 0x12, 0x28, 0x00};
void _declspec(naked) test()
{
_asm
{
int 3
iretd
//jmp fword ptr ds:[pretr]
}
}
int main(int argc, char* argv[])
{
char sele[6] = {0};
*(DWORD*)sele = 0x12345678;
*(WORD*)&sele[4] = 0x0048;
DWORD cr3 = 0;
printf("cr3:");
scanf("%x",&cr3);
//12ff0c
DWORD myTSS[26] ={
0x00000000, //0 previous task link
0x0012fe00, //4 esp0
0x00000010, //8
0x00000000, //12
0x00000000, //16
0x00000000, //20
0x00000000, //24
cr3, //28 cr3
0x00401020, //32 eip
0x00000000, //36 eflags
0x00000000, //40 eax
0x00000000, //44 ecx
0x00000000, //48 edx
0x00000000, //52 ebx
0x0012fe00, //56 esp
0x00000000, //60 ebp
0x00000000, //64 esi
0x00000000, //68 edi
0x00000023, //72 es
0x00000008, //76 cs
0x00000010, //80 ss
0x00000023, //84 ds
0x00000030, //88 fs
0x00000000, //92 gs
0x00000000, //96 LDT
0x20ac0000, //100 I/O map
};
_asm
{
call fword ptr ds:[sele]
//jmp fword ptr ds:[sele]
}
return 0;
}
[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!
最后于 2018-11-21 12:07
被米九编辑
,原因: