汇编网首页登录博客注册
masmaster的学习博客
博客首页博客互动【做检测题】论坛求助

我的博客

个人首页 |  我的文章 |  我的相册 |  我的好友 |  最新访客 |  文章收藏 |  论坛提问 |  友情链接 |  给我留言  
图片载入中
文章收藏

[2010-10-05 10:15] 实模式与保护切换实例

.386p                                        
assume                cs:codeseg,ds:dataseg        
;
jump                macro selector,offsetv        ;定义一条段间转移宏指令
                db 0eah                        ;jmp操作码
                dw offsetv                ;偏移
                dw selector                ;选择子
                endm

descriptor        struc                                ;存储段描述符结构定义
limitl                dw 0                        ;段界限
basel                dw 0                        ;段基地低16位
basem                db 0                        ;段基地址中8位
attrib                dw 0                        ;段属性(含段界限的高4位)
baseh                db 0                        ;段基地址高8位
descriptor        ends

pdesc                struc                        ;GDTR伪描述符结构定义
limit                dw 0                        ;16位界限
base                dd 0                        ;32位基地址
pdesc                ends
;-----------------------------------------------------------------;
;数据段
dataseg                segment use16                ;使用16位段        
gdt                label byte                        ;全局描述符表GDT
dummy                descriptor <>                ;空描述符
;代码段描述符
code                descriptor <0ffffh,,,98h,>         
code_sel        = code - gdt                         ;代码段描述符的选择子
;源数据段描述符
datas                descriptor <0ffffh,0h,11h,92h,0>
datas_sel        = datas - gdt                        ;源数据段描述符的选择子
;目的数据段描述符
datad                descriptor <0ffffh,,,92h,>
datad_sel        = datad - gdt                        ;目的数据段描述符的选择子
;GDT长度
gdtlen                = $ - gdt
;伪描述符
vgdtr                pdesc<gdtlen-1,>
;缓冲区
buffer                db 256 dup (0)
dataseg                ends
;-----------------------------------------------------------------;
;代码段
codeseg                segment use16                ;16位代码段
start:        
                mov ax,dataseg
                mov ds,ax
;准备要加载到GDTR的伪描述符
                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
                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
;加载GDTR
                lgdt fword ptr vgdtr                

                cli                        ;关中断
                call ea20                        ;打开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,256/4                ;设置4字节为单位传输长度
                rep movsd                ;传输
;切换到实模式
                mov eax,cr0
                and eax,0fffffffeh
                mov cr0,eax
;清指令预取队列,进入实模式
                jump <seg real>,<offset real>

real:
                call da20                        ;关闭A20地址线
                sti                        ;开中断

                mov ax,dataseg                ;重置数据段
                mov ds,ax
                mov bx,offset buffer        ;指针指向数据段首地址
                mov ax,[bx]                ;
                call disphex                ;显示
                mov ah,4ch
                int 21h
;-----------------------------------------------------------------;
;Enable A20
;开启A20地址线
ea20                proc
                push ax
                in al,92h
                or al,2
                out 92h,al
                pop ax
                ret
ea20                endp

;Disable A20
;关闭A20地址线
da20                proc
                push ax
                in al,92h
                and al,0fdh
                out 92h,al
                pop ax
                ret
da20                endp

;显示16位寄存器信息
;入口地址:AX
;返回:无
disphex                proc  
                mov cx,4
d1:                push cx
                mov cl,4
                rol ax,cl
                push ax
                and ax,0fh
                cmp al,10
                jb d10
                mov dl,al
                add dl,37h
                mov ah,2
                int 21h
                jmp jx2
d10:                mov dl,al
                add dl,30h
                mov ah,2
                int 21h
jx2:                pop ax
                pop cx
                loop d1
                ret
disphex                endp
;-----------------------------------------------------------------;
codeseg                ends
end                start
评论次数(0)  |  浏览次数(821)  |  类型(汇编语言笔记) |  收藏此文  | 
 
 请输入验证码  (提示:点击验证码输入框,以获取验证码