试了好几次从3转到0都不行 有TSS 先用RETF转到3了 就是跳回不到0级 谁能简单写下代码!!!感激不尽
------解决方案--------------------------------------------------------
你的GDT里面要有你的一个项才可以
------解决方案--------------------------------------------------------
从3转到0,只能通过调用门,或者使用任务转换。
------解决方案--------------------------------------------------------
label_ss3:Descriptor 0,0ffffh, DA_DRWA + DA_32 + DA_DPL3
以上这句,基地址是0x00000000,段边界是0x0ffff?粒度想必是以字节为单位吧?
好吧,你进入ring3时,压入堆栈中的3特权级堆栈指针是
push dword ss3len
ss3len最多也就是20,就是说,ESP=20
你个狗才,描述符中的段边界,不是指段的长度(尽管对于代码段和数据段来说,它们的确相等),而是指偏移地址、EIP或者ESP的范围。
当ESP小于边界值,引发异常。你的边界值是0xffff,因此,有效的ESP范围是0xffffffff--0x0000ffff,20显然不在这个范围。进入ring3时,堆栈不可能正常工作。
------解决方案--------------------------------------------------------
你这代码乱糟糟的,我实在看不了。以上纯属乱猜。
------解决方案--------------------------------------------------------
建议:
将堆栈段线性基地址设为哪里都行,无所谓。但段界限要设为0xffffe,粒度设为4KB为单位,初始的堆栈指针ESP设为0。
------解决方案--------------------------------------------------------
不是不愿帮你,是我看不懂那些宏。因为我从来不用宏。
你帮我整理一下有关段描述符的宏,改成32位数的形式。比如:
- Assembly code
;创建0#描述符,它是空描述符,这是处理器的要求mov dword [bx+0x00],0x00mov dword [bx+0x04],0x00;创建#1描述符,保护模式下的代码段描述符mov dword [bx+0x08],0x7c000200mov dword [bx+0x0c],0x00409800;创建#2描述符,保护模式下的数据段描述符(文本模式下的显示缓冲区)mov dword [bx+0x10],0x8000ffffmov dword [bx+0x14],0x0040920b
------解决方案--------------------------------------------------------
看得我脑袋都晕了。
部分代码我改了,见注释部分。没有全部分析你的代码。
[code=assembly] %include "pm.inc"
org 07c00h
jmp begin
label_gdt:Descriptor 0,0,0
label_code32:Descriptor 0,0ffffh,DA_C+DA_32
label_code32d:Descriptor 0,0ffffh,DA_C+DA_32+DA_DPL3
label_data:Descriptor 0b8000h,0ffffh,DA_DRW+DA_DPL3
label_ldt:Descriptor 0,0ffffh,DA_LDT
label_ss0:Descriptor 0,ss0len, DA_DRWA + DA_32 ;将ss0len改成1
label_ss3:Descriptor 0,ss3len, DA_DRWA + DA_32 + DA_DPL3 ;同上改
label_gate:Gate selectorcode,0,0,DA_386CGate
label_gate2:Gate selectorcode,0,0,DA_386CGate+DA_DPL3
label_tss:Descriptor 0,TSSLen-1,DA_386TSS
gdtlen equ $-label_gdt
selectorcode equ label_code32-label_gdt
selectordata equ label_data - label_gdt+3
selectorldt equ label_ldt-label_gdt
selectorss0 equ label_ss0-label_gdt
selectorss3 equ label_ss3-label_gdt+3
selectorgate equ label_gate-label_gdt+3
selectorTSS equ label_tss-label_gdt
selectorgate2 equ label_gate2-label_gdt+3
selectorcode2 equ label_code32d - label_gdt+3
vggdtr dw gdtlen-1 ;这里减去1是错误的。不能减
dd 0
ldt:
label_codec32:Descriptor 0,0ffffh,DA_C + DA_32 + DA_DPL3
selectorcodec32 equ label_codec32-ldt+4+3
LABEL_TSS:
DD 0
DD ss0len
DD selectorss0
DD 0
DD 0
DD 0
DD 0
DD 0
DD 0
DD 0
DD 0
DD 0
DD 0
DD 0
DD 0
DD 0
DD 0
DD 0
DD 0
DD 0
DD 0
DD 0
DD 0
DD 0
DD 0
DW 0
DW $ - LABEL_TSS + 2 ;这里直接写成104
DB 0ffh ;这句不需要
TSSLen equ $ - LABEL_TSS
ss0:dd 0
dd 0
dd 0
dd 0
db 0
ss0len equ $-ss0-1
ss3:dd 0
dd 0
dd 0
dd 0
db 0
ss3len equ $-ss3+1
begin:
mov ax,0
mov ds,ax
mov ax,code32
mov [label_code32+2],ax
mov ax,ss0
mov [label_ss0+2],ax
mov ax,ss3
mov [label_ss3+2],ax