80X86 call特权转移
试了好几次从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位数的形式。比如:
;创建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
mov ax,ldt
mov [label_ldt+2],ax
mov ax,code32d
mov [label_code32d+2],ax
mov ax,codec32
mov [label_codec32+2],ax
xor eax, eax
mov ax, ds
shl eax, 4
add eax, label_tss
mov word [label_tss + 2], ax
shr eax, 16
mov byte [label_tss + 4], al
mov byte [label_tss + 7], ah
mov ax,label_gdt ;mov eax,label_gdt
mov [vggdtr+2],ax ;mov [vggdtr+0x02],eax
;幸亏逻辑段地址为0,否则这样写完蛋了
lgdt [vggdtr]
cli
in al,92h
or al,2
out 92h,al
mov eax,cr0
or eax,1
mov cr0,eax
jmp selectorcode:0
real:
[bits 32]
mov ax,0b800h
mov ds,ax
mov bx,80*10*2+4
mov ax,0c63h
mov [bx],ax
in al,92h
and al,0fdh
out 92h,al
jmp $
;-----------------------------------
[bits 32]
code32d:
mov ax,0
mov ax,1
mov ax,2
jmp $
;-----------------------------------
code32:
mov ax,selectorss0
mov ss,ax
mov sp,ss0len
mov ax,selectordata
mov ds,ax
mov ax,0c61h
mov bx,80*10*2
mov [bx],ax
mov ax,selectorldt
lldt ax
mov ax, selectorTSS
ltr ax
push dword selectorss3
push dword ss3len
push dword selectorcodec32
push dword 0
retf
code32m:
mov eax,cr0
and eax,0fffffffeh
mov cr0,eax
jmp 0:real
[bits 32]
codec32:
mov ax,selectordata
mov ds,ax
mov ax,0c62h
mov bx,80*10*2+2
mov [bx],ax
call selectorgate2:0 ;出错 这句是关键跳到3级selectrocode2可以跳到0级selectorcode好像就 ;不行了 不知道哪错了
jmp $
times 510-($-$$) db 0
dw 0xaa55
[/code]