首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 嵌入开发 > 汇编语言 >

大家来看看,小弟我的程序不能返回DOS了!哪位大侠可以跟踪INT 21探查究竟

2012-02-02 
大家来看看,我的程序不能返回DOS了!哪位大侠可以跟踪INT 21探查究竟?程序功能:读引导山区,然后以16进制方

大家来看看,我的程序不能返回DOS了!哪位大侠可以跟踪INT 21探查究竟?
程序功能:读引导山区,然后以16进制方式显示在屏幕上。程序可以正确的读引导扇区,显示的结果也都正确,最后调用的一个子过程也正确返回。

问题在于:执行mov   ah,4c,再执行int   21指令时,失去响应,无法返回DOS,就连按下Crlt+Alt+Del也不响应。我怀疑唯一的可能是覆盖了dos的某个模块?但是内存完全是dos分配的,我又没干什么非法的勾当。

补充:编译时总提示没有堆栈段,我怕dos看不到我的堆栈段,我设置了1K大小。

代码如下:
DATAS   SEGMENT
                db             4096         dup(0)  
DATAS   ENDS

STACKS   SEGMENT
                DB   1024   DUP(0)
STACKS   ENDS
ReadSector             PROTO       NEAR
MEM_TO_HEX             PROTO       FAR
.386P
CODES   SEGMENT   USE16
ASSUME   CS:CODES,DS:DATAS,SS:STACKS
START:
MOVAX,DATAS
MOVDS,AX
MOVAX,STACKS
MOVSS,AX
MOV           SP,1024
PUSHDS
MOV           AX,01H                     ;读取逻辑扇区1
MOVCL,01H                     ;读取1个扇区长度
CALLReadSector
MOVAX,512
PUSHAX
PUSHBX
MOVAX,ES;读取缓冲区段值
MOVDS,AX;设置为DS,因为DS被MEM_TO_HEX过程默认使用
XORAX,AX
PUSHAX;压入显存的偏移地址
MOVAX,0B800H;ES被MEM_TO_HEX过程默认使用
MOVES,AX
CALLMEM_TO_HEX
POPDS
MOVAH,4CH
INT21H
;*********************************************************************
;软磁盘逻辑扇区编码方式:
;0头0道1扇区~18扇区:对应逻辑扇区号1~18
;1头0道1扇区~18扇区:对应逻辑扇区号19~36
;0头1道1扇区~18扇区:对应逻辑扇区号37~54
;1头1道1扇区~18扇区:对应逻辑扇区号55~72
;
;BIOS中断   int13H的调用规范
;子中断号ah=02h读磁盘al=要读取的扇区数
;ch=磁道号cl=起始扇区号
;dh=磁头号es:bx   缓冲区地址
;*********************************************************************
;---------------------------------        
;函数名:
ReadSectorPROCNEAR
;入口参数
;ax=逻辑扇区号cl=要读取的扇区个数es:bx   缓冲区地址
;---------------------------------
pushbp
movbp,sp
subsp,2
mov[bp-2],cl
pushbx
pushax
mov           bl,37  
divbl;商为磁道号
movch,al;填写磁道号
popax
mov           bl,19
divbl
movdh,al;商为磁头号
movcl,ah;余数为起始扇区号
moval,[bp-2];填充要读取的扇区数
mov           ah,02h                                     ;读扇区
movdl,00h;目标存储介质:软磁盘
pop           bx
int13h
addsp,2
popbp
ret
ReadSectorENDP
;*********************************************************************
;函数功能:转化指令长度的内存区块为ASCII,转储到目标内存块,目标
;                           内存块长度应该是源内存块的4倍,如果内存块的内容均为压
;                           缩BCD码,则函数恰好将其转化为ASCII码。
;入口参数:参数3:目标内存块地址,参数2:源内存块地址,参数1:源
;                           内存块大小
;       参数大小:均为2个字节,参数顺序,自右向左
;       注意:         要在16位代码段中使用本函数,子过程已经通过了作者的初步
;                           测试,欢迎大家测试并使用。


;*********************************************************************        
MEM_TO_HEX     PROC   FAR
PUSHBP
MOVBP,SP
MOVDI,[BP+06H];提取目标内存块地址
MOVSI,[BP+08H];提取源内存块地址
MOVCX,[BP+0AH];提取源内存块长度(单位:字节)
                MOV           AH,0CH                     ;设置前景背景
LCX:
MOVAL,[SI];读源缓冲区中的一个字节
MOVBH,AL;保存AL的高半字节  
MOVBL,2H;AL中的2个BCD压缩码要分两次转化
                SHR           AL,4H
LBL:
ANDAL,0FH;将AL低半字节转化成十六进制
CMPAL,09H  
JAA
ORAL,30H;转化数字(0~9)成ASCII
JMPB
A:             ADD           AL,37H                     ;转化字母(A~F)成ASCII
B:MOVES:[DI],AX;存入目标内存区(显存)  
INCDI    
INCDI;目标内存指针加2
MOVAL,BH;恢复AL的高半字节  
DECBL;循环计数器减1  
JNZLBL
INCSI;源内存指针加1  
LOOPLCX
POPBP
RET06H
MEM_TO_HEX     ENDP

CODES   ENDS
        END   START

[解决办法]
呵呵, 仔细看了下 int13h 相关的, 应该是没有设置正确的 ES:BX 造成的吧, 尤其是 ES. 缺省的 ES 指向 psp, bx 随环境有不同, 这里一般为 0. 这样 ES:BX 指向了 psp, 导致导入扇区覆盖了 psp, 引发 dos 崩溃.
....
START:
MOV AX,DATAS
MOV DS,AX
MOV ES, AX ;* 这里设置 es 指向 DATAS 段
MOV AX,STACKS
MOV SS,AX
MOV SP,1024
PUSH DS
MOV AX,01H ;读取逻辑扇区1
MOV CL,01H ;读取1个扇区长度
mov bx, offset ... ;* 这里设置 bx 指向数据段的读入缓冲区空间, 给那个命名下
CALL ReadSector
....

上面的代码在虚拟机上验证过了.

热点排行