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
;--------------------
call16 macro selector,offsetv
db 9Ah
dw offsetv
dw selector
endm
;----------------------
descriptor struc ;//描述符的结构
limitl dw 0
basel dw 0
basem db 0
attributes dw 0
baseh db 0
descriptor ends
;-----------------------------------------------------------------------------
gate struc
offsetl dw 0
selector dw 0
dcount db 0
gtype db 0
offseth dw 0
gate ends
;--------------------
pdesc struc ;//伪描述府
limit dw 0
base dd 0
pdesc ends
;
atdw=92h
atce=98h
atcer=9ah
atldt=82h ;局部描述符表段类型值
TIL=04H
at386tss=89h
at386cgate=8ch ;386调用门类型值
dpl1 = 20h
dpl2 = 40h
dpl3 = 60h
rpl1 = 01h
rpl2 = 02h
rpl3 = 03h ;;;;;;;;;;;;;
.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
;
tss descriptor <0FFFFh,,,at386tss,>
tss_sel=tss-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+dpl3,>
vcode_sel=(vcode-ldt)+TIL+rpl3
;要显示的数据
vdata descriptor <0FFFFh,,,atdw+dpl3,>
vdata_sel=(vdata-ldt)+TIL+rpl3
;要显示的数据2
vdata1 descriptor <0FFFFh,,,atdw+dpl3,>
vdata1_sel=(vdata1-ldt)+TIL+rpl3
;
vbuf descriptor <0FFFFh,8000h,0bh,atdw+dpl3,>
vbuf_sel=(vbuf-ldt)+TIL+rpl3
;
stack0t descriptor <0FFFFh,,,atdw,>
stack0t_sel=(stack0t-ldt)+TIL
;
stack3t descriptor <0FFFFh,,,atdw+dpl3,>
stack3t_sel=(stack3t-ldt)+TIL+rpl3
tovbuf gate <tojump,codek_sel,0,at386cgate+dpl3,0> ;;;;;;;;;;;;;;;;;;;
tovbuf_sel=(tovbuf-ldt)+TIL
ldtseg ends
;----------------------------------------------------
tssseg segment use16
dd 0 ;back
dw stack0len,0 ;0级堆栈指针
dw stack0t_sel,0 ;初始化
dw 0,0 ;1级堆栈指针
dw 0,0 ;初始化
dd ? ;2级堆栈指针
dw ?,0 ;未初始化
dd 0 ;cr3
dd ? ;eip
dd ? ;eflags
dd ? ;eax
dd ? ;ecx
dd ? ;edx
dd ? ;ebx
dd ? ;esp
dd ? ;ebp
dd ? ;esi
dd ? ;edi
dw ?,0 ;es
dw ?,0 ;cs
dw ?,0 ;ss
dw ?,0 ;ds
dw ?,0 ;fs
dw ?,0 ;gs
dw ldt_sel,0 ;ldt
dw 0
dw $+2 ;指向I/O许可位图
db 0FFh ;I/o许可位图结束标志
tssseg ends
;
stack0 segment
stack0len=512
db stack0len dup (0)
stack0 ends
;
stack3 segment
stack3len=512
db stack3len dup (0)
stack3 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
call16 tovbuf_sel,0
vcseg ends
;---------------------------------
codekseg segment use16 ;这段代码实现了从0级到3级的转换。很关键的呀!!!!
assume cs:codekseg ;
startk: mov ax,tss_sel
ltr ax
mov ax,ldt_sel
lldt ax
mov ax,stack0t_sel ;
mov ss,ax ;
mov esp,stack0len ;建立0级堆栈
push word ptr stack3t_sel ;压如3级堆栈的指针。
push word ptr stack3len
push word ptr vcode_sel ;压入入口地址
push offset vstart
retf ;实现0级到3级的转变
tojump: jump <code_sel>,<offset toreal>
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
;
mov ax,tssseg
mul bx
mov word ptr tss.basel,ax
mov byte ptr tss.basem,dl
mov byte ptr tss.baseh,dh
;
push ds
assume ds:ldtseg
mov ax,ldtseg
mov ds,ax
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
;
mov ax,vcseg
mul bx
mov word ptr vcode.basel,ax ;;;;;;;;;;;;;;;;
mov byte ptr vcode.basem,dl ;;;;;;;;;;;;;;;;
mov byte ptr vcode.baseh,dh ;;;;;;;;;;;;;;;;
;
pop ds
assume ds:gdtseg
lgdt qword ptr vgdtr
cli
mov eax,cr0
or ax,1
mov cr0,eax
jump <codek_sel>,<offset startk>
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