+ -
当前位置:首页 → 问答吧 → 杨季文中的t10-1.asm例子中数据属性更改为只读怎么不行

杨季文中的t10-1.asm例子中数据属性更改为只读怎么不行

时间:2010-11-16

来源:互联网

;程序名:T10-1.asm
;功能:演示实方式和保护方式切换

;16位偏移的段间直接转换指令的宏定义
jump macro selector,offsetv
  db 0eah ;操作码
dw offsetv ;16位偏移
dw selector ;段值或选择子
endm

;字符显示宏指令的定义
echoch macro ascii
  mov ah,2
mov dl,ascii
int 21h
endm

;存储段描述符结构类型的定义
descriptor struc
limitl dw 0 ;段界限(0--15)
basel dw 0 ;段基地址(0--15)
basem db 0 ;段基地址(16--23)
attributes dw 0 ;段属性
baseh db 0 ;段基地址(24--31)
descriptor ends

;伪描述符结构类型的定义
pdesc struc
limit dw 0 ;16界限
base dd 0 ;基地址
pdesc ends

;常量定义
atdw = 92h ;存在的可读写数据段属性值
atce = 98h ;存在的只执行代码段属性值
atdr = 90h ;data read only----------------------这是我添加的一个属性,表示数据段只读;
  .386P
;--------------------------------------------------------

;数据段
dseg segment use16 ;16位段
gdt label byte ;全局描述符表gdt
dummy descriptor <> ;空描述符
code descriptor <0ffffh,,,atce,>
code_sel =code-gdt ;代码段描述符的选择子
datas descriptor <0ffffh,0h,11h,atdr,0> ;我把源数据段改为只读,因为这里的数据没有写datas_sel =datas-gdt ;源数据段描述符的选择子
datad descriptor <0ffffh,,,atdw,>
datad_sel =datad-gdt ;目的数据段描述符的选择子
gdtlen =$-gdt
;
vgdtr pdesc <gdtlen-1,> ;伪描述符
;
bufferlen = 256 ;缓冲区字节长度
buffer db bufferlen dup(0) ;缓冲区
dseg ends

;-------------------------------------------------------------
;代码段
cseg segment use16 ; 16位段
  assume cs:cseg, ds:dseg
start:
  mov ax,dseg
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 ;代码段开始偏移为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
;加载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,bufferlen/4 ;设置4字节为单位的缓冲区长度
repz movsd ;传送
;切换回实模式
mov eax,cr0
and eax,0fffffffeh
mov cr0,eax
;清指令预取队列,进入实方式
  jump <seg real>,<offset real>
;
real: ;现在又回到实方式
  call da20 ;关闭地址线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 al,4
call toascii
echoch al
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
  add al,'0'
  cmp al,'9'
  seta dl
  movzx dx,dl
  imul dx,7
  add al,dl
  ret  
toascii endp
;
;打开地址线A20
ea20 proc
  push ax
in al,92h
or al,2
out 92h,al
pop ax
ret
ea20 endp
;
;关闭地址线A20
da20 proc
  push ax
in al,92h
and al,0fdh ;0fdh=not 20h
out 92h,al
pop ax
ret
da20 endp
;
cseg ends
  end start  
 

 
我只改了两个地方,一个是添加了一个数据段只读属性,另一个是把源数据段改为只读属性,编译可以,可是运行后就
死机了,请问这是为什么?

作者: leetow2003   发布时间: 2010-11-16

datas_sel =datas-gdt ;源数据段描述符的选择子
这里没有改

作者: leetow2003   发布时间: 2010-11-16

果然如楼主所说,我测试是重启。还望高手解惑呀!~

作者: masmaster   发布时间: 2010-11-16

热门下载

更多