在上一节我们讲了GDT的用法,这一节我要讲讲LDT的用法,呵呵.以下是源代码:
;--------------------------------------------------------
ea20 macro ;//打开A20地址线
push ax
in al,92h
or al,00000010b
out 92h,al
pop ax
endm
;----------------------------------------------------------------------------
;关闭A20地址线
;----------------------------------------------------------------------------
da20 macro
push ax
in al,92h
and al,11111101b
out 92h,al
pop ax
endm
;----------------------------------------------------------------------------
jump macro selector,offsetv ;//跳转宏
db 0EAh
dw offsetv
dw selector
endm
;--------------------
descriptor struc ;//描述符的结构
limitl dw 0
basel dw 0
basem db 0
attributes dw 0
baseh db 0
descriptor ends
;--------------------
pdesc struc ;//伪描述府
limit dw 0
base dd 0
pdesc ends
;
atdw=92h
atce=98h
atcer=9ah
atldt=82h
TIL=04H
.386P
;---------------------------------------------------------------------------------------
gdtseg segment use16
gdt label byte
dummy descriptor <>
code descriptor <0FFFFh,,,atce,>
code_sel=code-gdt
;代码段codekseg的描述符
codek descriptor <0FFFFh,,,atce,>
codek_sel=codek-gdt
;通用描述符
normal descriptor <0FFFFh,,,atdw,>
normal_sel=normal-gdt
;局部描述表的描述符
ldtable descriptor <0FFFFh,,,atldt,>
ldt_sel=ldtable-gdt
gdtlen=$-gdt
vgdtr pdesc <gdtlen-1,>
gdtseg ends
;------------------------------------------------------------------
;局部描述表
ldtseg segment use16
ldt label byte
;数据段ldtseg的描述符
data descriptor <0FFFFh,,,atdw,>
data_sel=(data-ldt)+TIL
;代码段vcode的描述符
vcode descriptor <0FFFFh,,,atce,>
vcode_sel=(vcode-ldt)+TIL
;要显示的数据
vdata descriptor <0FFFFh,,,atdw,>
vdata_sel=(vdata-ldt)+TIL
;要显示的数据2
vdata1 descriptor <0FFFFh,,,atdw,>
vdata1_sel=(vdata1-ldt)+TIL
;
vbuf descriptor <0FFFFh,8000h,0bh,atdw,>
vbuf_sel=(vbuf-ldt)+TIL
ldtseg ends
;-----------------------------------------------------
;代码段
vdseg segment use16
yang db 'how are you',0
vdseg ends
;-----------------------------------------------------
vdseg1 segment use16
hello db 'hello',0
hellolen=$-hello
vdseg1 ends
;-----------------------------------------------------
vcseg segment use16
assume cs:vcseg
vstart: mov ax,vdata_sel
mov ds,ax
mov ax,vbuf_sel
mov es,ax
lea si,yang
xor bx,bx
mov cx,11
again: mov al,[si]
mov ah,87h
mov es:[bx],ax
add bx,2
inc si
loop again
;hello
mov ax,vdata1_sel
mov ds,ax
lea si,hello
mov cx,hellolen
again1: mov al,[si]
mov ah,0F4h
mov es:[bx],ax
add bx,2
inc si
loop again1
gojump: jump <code_sel>,<offset toreal>
vcseg ends
;-----------------------------------------------------
codekseg segment use16
assume cs:codekseg
startk: mov ax,ldt_sel
lldt ax
jump <vcode_sel>,<offset vstart>
codekseg ends
;-----------------------------------------------------
cseg segment use16
assume cs:cseg,ds:gdtseg
start: mov ax,gdtseg
mov ds,ax
mov bx,16
mul bx
add ax,offset gdt
adc dx,0
mov word ptr vgdtr.base,ax
mov word ptr vgdtr.base+2,dx
;
mov ax,cseg
mul bx
mov word ptr code.basel,ax
mov byte ptr code.basem,dl
mov byte ptr code.baseh,dh
;
mov ax,codekseg
mul bx
mov word ptr codek.basel,ax
mov byte ptr codek.basem,dl
mov byte ptr codek.baseh,dh
;
mov ax,ldtseg
mul bx
mov word ptr ldtable.basel,ax
mov byte ptr ldtable.basem,dl
mov byte ptr ldtable.baseh,dh
;
push ds
mov ax,ldtseg
mov ds,ax
assume ds:ldtseg
mov ax,vcseg
mul bx
mov word ptr vcode.basel,ax
mov byte ptr vcode.basem,dl
mov byte ptr vcode.baseh,dh
;
mov ax,vdseg
mul bx
mov word ptr vdata.basel,ax
mov byte ptr vdata.basem,dl
mov byte ptr vdata.baseh,dh
;
mov ax,vdseg1
mul bx
mov word ptr vdata1.basel,ax
mov byte ptr vdata1.basem,dl
mov byte ptr vdata1.baseh,dh
pop ds
;
assume ds:gdtseg
lgdt qword ptr vgdtr
cli
ea20 ; //
mov eax,cr0 ; // 进入保护模式
or eax,1 ; //
mov cr0,eax ;//
jump <codek_sel>,<offset startk> ; // proctect mode
toreal: mov ax,normal_sel
mov ds,ax
mov eax,cr0
and eax,0FFFFFFFEH
mov cr0,eax
jump <seg real>,<offset real>
real: da20
sti
mov ah,4ch
int 21h
cseg ends
end start
这段代码,我们可以用前面的图来表示.要用LDT,我们需要用到mov ax,gdtseg ,lldt ax这两个命令是把全局描述表送入局部描述表寄存器.在执行玩这两个命令后,我们就可以使用局部描述符中的描述表所指向的段了.呵呵.