.model large
.586p
;******************
jump macro selecter,offsetv ;16位偏移的段间直接转移指令的宏定义
db 0eah
dw offsetv
dw selecter
endm
;******************
h_line macro x,y,re,col ;写屏幕上任一行像素点
local flg1,flg2,cag
;call page0
mov bx,x
flg1: push bx
mov eax,y
mov ecx,640
mul ecx
add eax,ebx
mov ecx,10000h
div ecx
mov di,dx
push di
mov dx,ax
push dx
cmp dx,pg
jnz cag
jmp flg2
cag: mov pg,dx
mov ah,4fh
mov al,05h
mov bh,00h
mov bl,00h
pop dx
push dx
int 10h
flg2: pop dx
mov al,col
pop di
stosb
pop bx
inc bx
cmp bx,x+re
jb flg1
endm
;****************
;*****************
descriptor struc ;存储段描述符结构
limitl dw 0 ;段界限
basel dw 0 ;段基(0--15)
basem db 0 ;段基(16--23)
attributes dw 0 ;属性
baseh db 0 ;段基(24--31)
descriptor ends
;*****************
echoch macro ascii ;显示字符
mov ah,2
mov dl,ascii
int 21h
endm
;****************
pdesc struc ;伪描述符结构
limit dw 0
base dd 0
pdesc ends
;*****************
atdw=92h
atdc=98h
;*****************
dseg segment use16
gdt label byte
dummy descriptor<>
code descriptor<0ffffh,,,atdc,>
code_sel =code-gdt
datas descriptor<0ffffh,0h,11h,atdw,0>
datas_sel =datas-gdt
datad descriptor<0ffffh,,,atdw,>
datad_sel =datas-gdt
gdtlen =$-gdt
;
vgdtr pdesc<gdtlen-1>
;
bufferlen =256
buffer db bufferlen dup(0)
pg dw 0
dseg ends
;*******************
cseg segment use16
assume cs:cseg,ds:dseg
start:
mov ax,dseg
mov ds,ax
mov bx,16
mul bx ;计算并设置GDT基地址
add ax,offset gdt ;界限已定义
adc dx,0
mov word ptr vgdtr.base,ax
mov word ptr vgdtr.base+2,dx
mov ax,cs
mul bx
mov code.basel,ax ;代码段开始偏移量为0
mov code.basem,dl ;界限已定义
mov code.baseh,dh
;设计目标数据段描述符
mov ax,ds
mul bx ;计算并设置数据段基地址
add ax,offset buffer
adc dx,0
mov datad.basel,ax
mov datad.basem,dl
mov datad.baseh,dh
lgdt fword ptr vgdtr ;装入描述符
cli
call enableA20 ;打开地址线A20
;切换到保护方式
mov eax,cr0
or eax,1
mov cr0,eax
;清指令预取队列,真正进入保护方式
jump <code_sel>,<offset virtual>
;
virtual:
mov ax,datas_sel
mov ds,ax ;加载源数据段描述符
mov ax,datad_sel
mov es,ax ;加载目标数据段描述符
cld
xor si,si ;设置初始指针
xor di,di
mov cx,bufferlen/4 ;设置4字节为单位的缓冲区长度
rep movsd ;传送.repz movsd 系统无法识别
;;*********************************
push a
mov ax,500
mov es,ax
mov bx,0
mov dl,0
mov dh,0
mov ch,0
mov cl,2
mov al,1
mov ah,2
int 0x13
popa
; pusha
; ;mov ax,dseg
; ;mov ds,ax
; mov ax,4f02h
; mov bx,118h
; int 10h
; mov eax,0a0000h
; mov es,ax
;
; h_line 20,20,100,0fh
; La:
; mov ah,10h
; int 16h
; cmp al,1bh
; jz kk1
; jmp La
; kk1:
; popa
;
;;*************************************
;返回实方式
mov eax,cr0
and eax,0fffffffeh
mov cr0,eax
;清指令预取队列,进入实方式
jump <seg real>,<offset real>
real:
call disableA20 ;关闭地址线A20
sti ;开中断
;
mov ax,dseg ;重置数据段寄存器
mov ds,ax
mov si,offset buffer
cld ;显示缓冲区内容
mov bp,bufferlen/16
nextline:
mov cx,16
nextch:
lodsb
push ax
shr ax,4
call toascii
pop ax
call toascii
echoch al
echoch ' '
loop nextch
echoch 0dh
echoch 0ah
dec bp
jnz nextline
;
mov ax,4c00h
int 21h
;*****************
toascii proc
and al,0fh
mov al,30h
cmp al,3ah
jb kk
add al,07h
kk:
toascii endp
;******************
enableA20 proc
push ax
in al,92h
or al,02h
out 92h,al
pop ax
ret
enableA20 endp
;***************
disableA20 proc
push ax
in al,92h
and al,0fdh
out 92h,al
pop ax
ret
disableA20 endp
;******************
cseg ends
end start