.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
- [somniumchase] 我一运行就说没有数字 01/01 11:44
- [游客] 为什么啊 08/07 15:36
- [游客] 如果想快一些 就改下面这里 dx值改成1H delay: push ax 04/19 02:53
- [lshhjx] 注释在程序中很重要,楼主不知道吗? 12/08 13:40
- [biaggi] 看不明白,在下還須學習 11/06 08:11
- [游客] 我运行的时候直接显示Unkown filename跳出了- -请问怎么改 06/16 21:44
- [游客] 勿庸置疑,注释是好习惯。与人方便自己方便。 04/12 10:33
- [游客] 老实说,看着真心累呀! 04/07 18:37
- [游客] 很无语,初学者就多看书,不要动不动要别人注释,基础打好了,再自己注释,这样比别人帮你注释好得多 12/17 19:43
- [dgkepu] 初学者:不懂,希望有多点注释带着学习学习! 12/07 20:52
- [游客] windows 7是一个64Bit操作系统,它不兼容DOS,无法识别16Bit系统。重装系统wind 02/28 21:05
- [游客] windows 7是一个64Bit操作系统,它不兼容DOS,无法识别16Bit系统。重装系统wind 02/28 21:05
- [466987333] 你好,高手,我想请教一个问题。 我用的是win7操作系统,32位的,里面没有找masm目录,是不是 12/12 17:30
- [lanfioncc] 那个太高级了。。。我还有点看不懂。。不过谢谢!!! 11/27 11:23
- [yc2010] 实验16中的 table: dw sub1,sub2,sub3,sub4 可不可以改成呢? 09/11 09:08
- [yc2010] mov bl,ah mov bh,0 add bx,bx ----------->这里为 09/07 21:03
- [yc2010] 为什么要add bx,bx呢? 09/07 20:55
- [yc2010] 那是不是像table[bx],ds[bx]....等(内存单元)都是表示一个字节呢? 09/06 21:10
- [masmaster] 杨季文的《80X86汇编语言程序设计教程》 09/01 12:52
- [游客] to masmaster shl左移4位,那al传进来的4,5,6位背景色不就没了. 为什 09/01 11:00