WEB开发网
开发学院软件开发汇编语言 汇编语言编写DOS下的内存驻留程序 阅读

汇编语言编写DOS下的内存驻留程序

 2007-04-25 09:29:48 来源:WEB开发网   
核心提示: jne add ax,0100h:word ptr [0100h] ;ax= 0001h ;0100h:0010h= 0002h ; ;ax = 0003h ret mov bx,ax 而下面的子程序是不可重入的: Add proc near mov Temp,ax mov ax,DS:word

  jne
  add ax,0100h:word ptr [0100h]  ;ax=  0001h
     ;0100h:0010h= 0002h
     ;----------------------------------------
     ;ax  = 0003h
  ret
  mov bx,ax
 而下面的子程序是不可重入的:
  Add proc near
  mov Temp,ax
  mov ax,DS:word ptr [si]
  cmp ax,0
  je DonotTheValue
  add ax,Temp
  DonotTheValue:
  ret
  Temp:
  dw  0
  Add endp
 可以利用检查可重入子程序的方法检查这个子程序的不可重入性,尝试一下在" mov ax,DS:word ptr [si]"指令后再次执行该子程序,那么就会出第一次调用返回的结果不对.
  mov ds,0100h   ;ds=0100h
  mov si,0010h   ;si=0010h
  mov ax,0001h   ;ax,=0001h
  call Add
  mov Temp,ax   ;Call Add subroutine
     ;Temp=0001h
  mov ax,0100h:word ptr [0010h]  ;0100h:0010h=0002h
     ;ax=2
  push ds   ;Interrupted
  push si
  push ax
  mov ds,0200h   ;ds=0200h
  mov si,0020h   ;si=0020h
  mov ax,0003h   ;ax=0003h
  call Add
  mov Temp,ax   ;Temp=0003h
  mov ax,0200h:word ptr [0020h]  ;0200h:0020h=0004h
  cmp ax,0   ;ax=0004h
  jne    ;Not equal ,add
  add ax,Temp   ;ax=0007h
  ret    ;Return to the interrupted point
  pop ax   ;ax=0002h
  pop si   ;si=0010h
  pop ds   ;ds=0100h
  iret    ;Return to Add subroutine
  cmp ax,0   ;ax=2
  jne    ;No equal,add
  add ax,Temp   ;ax  =0002h
     ;0100h:0010h =0003h
     ;----------------------------------------
     ;ax  =0005h
  ret   
  mov bx,ax
 上面执行的结果是AX=5,实上正确的结果应该是AX=3,这是由于当Add子程序从中断子程序再一次被调用时,修改了Temp的值,当从中断返回时不能正确恢复其值.
 解决的方法是把Temp放在堆栈中,当每次Add子程序被调用时Temp的地址都不一样,因此原调用的Temp值不会被第二次在中断中调用的Add所破坏.
  Add proc near
  push bp   ;Store BP
  sub sp,2   ;distribute a byte space in the stack
  mov bp,sp   ;SS:BP point to the stack head
  temp equ SS:word ptr [BP+0]  ;Explain the pointer to SS:BP
  mov Temp,ax
  mov ax,DS:word ptr [si]
  cmp ax,0
  je DonotAddTheValue
  add ax,Temp
  DonotAddTheValue:
  add sp,2   ;Release the dsitributed space in the stack
  pop bp   ;Restore BP
  ret
  Add endp
 对于DOS来说,DOS的内存数据就象Temp变量,它被分配在数据区,而不在堆栈上,因此DOS从总体上是不可重入的.从最后的一个例子看来.重入性跟堆栈有很大的关系.可重入代码允许在任何时候被中断,其所有的变量都存放在该代码的私有堆栈中.DOS是一个单任务的操作系统,在执行INT 21H的代码时是不允许中断DOS,并再次调用INT 21H的.每个时该最多有一个进程在调用DOS的代码.
 对DOS的重入性,以及相应所作的处理总结如下:
  >当通过INT 21H调用DOS时,DOS会使三个内部栈之一:I/O栈,磁盘栈和辅助栈.功能00H到处0CH使用I/O栈,除了不致命错误处理程 序以外使用磁盘栈,致命错误处理程序使用辅助栈.在这种栈切换模式下,如果前台处在INT 22H中,而TSR调用了使用相同栈的DOS功能, 就会使前台程序保存栈中的数据被TSR的数据覆盖掉;但如果调用不同栈的DOS功能,那将是安全的.INT 21H中的几个功能调即33H,50H,  51H,62H,和64H由于非常简单,使用用户栈,因此在任何情况下都是可重入的.避免这种不可重入的简单方法是当前台程序正处在INT 21H 中时,不要调用INT 21H.或者如果前台程序正在处理INT 21H时,只允许调用不同栈的INT 21H功能.
  >DOS数据区中有一个InDOS标志,也探源为DOS安全标志,表示当前访问DOS功能是来否安全.由于DOS不可重入,它指示当前是 否处于DOS中,激活TSR和代码可检查该标志(34H),如果DOS忙,则不能激活使用INT 21H 调用的TSR.
  >当前台程序执行能设置错误状态的DOS功能时,DOS会把扩展错误信息存放起来,正常情况下,前台程序可以读取扩展错误信息; 如果在前台程序读取信息之前激活TSR,且TSR也执行能报告错误信息的DOS功能,则后来的错误信息会覆盖原来的错误信息,前台程序就 会得不到正确的错误信息.因此必须在激活TSR之前保存(59H)这些错误信息,并在退出以前把它们恢复(5D0AH)成原来的值.

Tags:汇编语言 编写 DOS

编辑录入:爽爽 [复制链接] [打 印]
赞助商链接