调用int21h 退出程序时崩溃

IT保安 2015-10-27 06:06:22
具体情况:
运行之后,啥都不干,按5正常退出
但是,如果运行之后,按1实现增加功能,再按5退出时,单步发现在运行到程序尾部的 mov ax,4c00h, int 21h的时候,崩溃了.

使用自定义的栈 或者 不使用自定义的栈 都是这样子,特来求助!
代码如下:
THEDATA segment
g_mainbuf db 20 dup (0)
g_mainUI db 'Welcome to contact record system',0dh,0ah
db '1.Add 2.Delete 3.Update 4.Query 5.Quit$'
g_inputname db 'Input Name:$'
g_inputtel db 'Input Tel:$'
g_filename db 'contact.dat',0
g_delname db 'Input Name:$'
g_cmpbuf db 20 dup (0) ;用于比较的buf
g_notfound db 'Not found!$'
;g_length db 14h ;文件指针偏移量
g_hiptr dw 0 ;文件指针 高位
g_loptr dw 0 ;文件指针 低位
g_delsuccess db 'Delete sucess!$'
g_displayname db 8 dup ('$')
g_displaytel db 12 dup ('$')
g_name db 'Name:$'
g_tel db 'Tel:$'
THEDATA ends

THESTACK segment stack
db 160 dup (0)
THESTACK ends

MAINFUNCTION segment

QUERYPROC proc
mov ax,ds
mov es,ax
mov di,0
mov al,0
mov cx,14h
mov bx,offset g_mainbuf ;存放用户输入的数据
QUERYINIT:
stosb
loop QUERYINIT ;BUF清0

QUERYWELCOME:
mov dx,offset g_inputname
mov ah,09
int 21h
mov cl,0dh ;cl 检测是否第一次就输入回车
QUERYNAME: ;DEL子程序的循环接收NAME功能
mov ah,01
int 21h
cmp al,0dh ;输入回车就跳出循环
jz ADJUSTQUERYNAME ;跳到ADJUSTTEL将输入的字串设置一下
mov cl,al
mov [bx],al
inc bx
JMP QUERYNAME

ADJUSTQUERYNAME:
mov dl,0dh ;== /r
mov ah,02
int 21h

mov dl,0ah ;== /n
int 21h

cmp cl,0dh
jz QUERYWELCOME

mov byte ptr [bx],'$' ;上一组字串补上$

;打开文件
mov al,3 ;可读可写 g 003c
mov dx,offset g_filename ;打开文件
mov ah,3dh
int 21h

mov bx,ax ; 获得文件代号
push bx

mov bx,offset g_loptr
mov word ptr [bx],0
mov bx,offset g_hiptr
mov word ptr [bx],0
QUERYSEARCH:
mov bx,offset g_loptr
mov dx,[bx]
add byte ptr [bx],14h
mov bx,offset g_hiptr
mov cx,[bx]
adc byte ptr [bx],0
pop bx
push bx
;mov cx,0
;mov dx,0
mov al,0
mov ah,42h ;定位文件指针
int 21h

jc QUERYNOTFOUND ;指针指向文件尾部,判定为没有找到p

mov cx,14h ;读定长数据
mov ax,offset g_cmpbuf ;拿比较缓冲区偏移地址,存放读自文件的数据
mov dx,ax
mov ah,3fh
int 21h ;g 005d

mov cx,0
mov ax,ds
mov es,ax
mov di,offset g_mainbuf ;源数据 == 用户输入的数据

QUERYCOUNT:
mov al,'$'
scasb
jz QUERYCOMPARE
inc cx
jmp QUERYCOUNT

QUERYCOMPARE:
mov ax,ds ;g 0088
mov es,ax
mov si,offset g_mainbuf ;用户输入的数据
mov di,offset g_cmpbuf ;读取自文件的数据
repe cmpsb
jcxz QUERYFOUND ;找到就跳转到FOUND
jmp QUERYSEARCH ;没找到就再次设置文件指针向后查找
QUERYNOTFOUND:
mov dx,offset g_notfound
mov ah,09
int 21h

mov dl,0dh ;== /r
mov ah,02
int 21h

mov dl,0ah ;== /n
int 21h
jmp QUERYEXIT

QUERYFOUND:
;显示文件数据
mov di,offset g_displayname ; 存放名字的缓冲作为目的地
mov si,offset g_cmpbuf ;读取自文件的内容,源
LOOP1:
cmp byte ptr [si],'$'
jz GETTEL
mov al,[si]
mov [di],al
inc si
inc di
jmp LOOP1

GETTEL:
inc si
mov di,offset g_displaytel
LOOP2:
cmp byte ptr [si],'$'
jz PREPAREDISPLAY
mov al,[si]
mov [di],al
inc si
inc di
jmp LOOP2

PREPAREDISPLAY:
mov dx,offset g_name
mov ah,09
int 21h

mov dx,offset g_displayname
int 21h

mov dl,0dh ;== /r
mov ah,02
int 21h

mov dl,0ah ;== /n
int 21h

mov dx,offset g_tel
mov ah,09
int 21h

mov dx,offset g_displaytel
int 21h

mov dl,0dh ;== /r
mov ah,02
int 21h

mov dl,0ah ;== /n
int 21h

QUERYEXIT:
mov ah,3eh ;关闭文件
int 21h;
pop bx
ret
QUERYPROC endp

DELPROC proc
mov ax,ds
mov es,ax
mov di,0
mov al,0
mov cx,14h
mov bx,offset g_mainbuf ;存放用户输入的数据
INIT:
stosb
loop INIT ;BUF清0
DELWELCOME:
mov dx,offset g_inputname
mov ah,09
int 21h
mov cl,0dh ;cl 检测是否第一次就输入回车
DELNAME: ;DEL子程序的循环接收NAME功能
mov ah,01
int 21h
cmp al,0dh ;输入回车就跳出循环
jz ADJUSTDELNAME ;跳到ADJUSTTEL将输入的字串设置一下
mov cl,al
mov [bx],al
inc bx
JMP DELNAME

ADJUSTDELNAME:
mov dl,0dh ;== /r
mov ah,02
int 21h

mov dl,0ah ;== /n
int 21h

cmp cl,0dh
jz DELWELCOME

mov byte ptr [bx],'$' ;上一组字串补上$

;打开文件
mov al,3 ;可读可写 g 003c
mov dx,offset g_filename ;打开文件
mov ah,3dh
int 21h

mov bx,ax ; 获得文件代号
push bx

mov bx,offset g_loptr
mov word ptr [bx],0
mov bx,offset g_hiptr
mov word ptr [bx],0
SEARCH:
mov bx,offset g_loptr
mov dx,[bx]
add byte ptr [bx],14h
mov bx,offset g_hiptr
mov cx,[bx]
adc byte ptr [bx],0
pop bx
push bx

;mov cx,0
;mov dx,0
mov al,0
mov ah,42h ;定位文件指针
int 21h

jc NOTFOUND ;指针指向文件尾部,判定为没有找到p

mov cx,14h ;读定长数据
mov ax,offset g_cmpbuf ;拿比较缓冲区偏移地址,存放读自文件的数据
mov dx,ax
mov ah,3fh
int 21h ;g 005d

mov cx,0
mov ax,ds
mov es,ax
mov di,offset g_mainbuf ;源数据 == 用户输入的数据

COUNT:
mov al,'$'
scasb
jz COMPARE
inc cx
jmp COUNT

COMPARE:
mov ax,ds
mov es,ax
mov si,offset g_mainbuf ;用户输入的数据
mov di,offset g_cmpbuf ;读取自文件的数据
repe cmpsb
jcxz FOUND ;找到就跳转到FOUND
jmp SEARCH ;没找到就再次设置文件指针向后查找
NOTFOUND:
mov dx,offset g_notfound
mov ah,09
int 21h

mov dl,0dh ;== /r
mov ah,02
int 21h

mov dl,0ah ;== /n
int 21h
jmp DELEXIT

FOUND:
;删掉文件数据
mov ax,ds
mov es,ax
mov di,0 ;g 96
mov al,0
mov cx,14h
;push bx ;文件代号入栈保存
mov bx,offset g_mainbuf ;将mainbuf清0,写入文件中,等价于清空文件数据
INITBUF:
stosb
loop INITBUF ;BUF清0
;将文件指针回溯20个字节,就可以开始反填数据

mov bx,offset g_loptr
mov dx,[bx]
sub dx,14h
mov bx,offset g_hiptr
mov cx,[bx]
sbb cx,0

pop bx ;文件代号出栈

mov al,0
mov ah,42h ;定位文件指针
int 21h

mov ah,40h ;调用40h功能准备写入文件 ;
mov dx,0
;pop cx
;inc cx ;+1因为文件中不是0下标开始算
mov cx,14h ;固定写20个字节
int 21h
mov dx,offset g_delsuccess ;打印删除成功提示
mov ah,09
int 21h

mov ah,3eh ;关闭文件
int 21h;

DELEXIT:

ret
DELPROC endp


ADDPROC proc
push bp
mov bp,sp
push cx
push di
push dx
push bx
mov di,0
mov al,0
mov cx,14h
INIT:
stosb
loop INIT

mov dx,[bp+8]
mov ah,09
int 21h
mov bx,0 ;bx当作下标使用
ADDINPUTNAME: ;ADD子程序的循环接收功能
mov ah,01
int 21h
cmp al,0dh ;输入回车就跳出循环
jz ADJUSTNAME ;跳到ADJUST 将输入的字串设置一下,以备接收下一个字串
mov [bx],al
inc bx
JMP ADDINPUTNAME

ADJUSTNAME: ;ADJUSTNAME的作用,将上一组字串补上$ 并换行
;inc bx
mov byte ptr [bx],'$' ;上一组字串补上$
mov dl,0dh ;== /r
mov ah,02
int 21h

mov dl,0ah ;== /n
int 21h

mov dx,[bp+6] ;提示输入电话
mov ah,09
int 21h

inc bx ;bx自增1,准备接受tel
ADDINPUTTEL: ;ADD子程序的循环接收功能
mov ah,01
int 21h
cmp al,0dh ;输入回车就跳出循环
jz ADJUSTTEL ;跳到ADJUSTTEL将输入的字串设置一下
mov [bx],al
inc bx
JMP ADDINPUTTEL

ADJUSTTEL:
;inc bx
mov byte ptr [bx],'$' ;上一组字串补上$
mov dl,0dh ;== /r
mov ah,02
int 21h

mov dl,0ah ;== /n
int 21h

mov al,3 ;可读可写 ;g a9
mov dx,offset g_filename ;打开文件
mov ah,3dh
int 21h
jc CREATENEWFILE ;如果cf=1,文件不存在 则创建文件
push ax ;成功,将文件代码压栈
jmp NEXT

CREATENEWFILE:
mov cx,20h ;指定创建的文件属性,
mov ah,3ch
int 21h
push ax ;成功,将文件代码压栈
NEXT:
mov ah,42h ;g 005d
mov al,2 ;移动文件指针到尾部
mov cx,0
mov dx,0
pop bx ;拿到文件代号
int 21h

mov ah,40h ;调用40h功能准备写入文件 ;
mov dx,0
mov cx,14h ;固定写20个字节
int 21h

mov ah,3eh ;关闭文件 g d6
int 21h;

pop bx
pop dx
pop di
pop cx
mov sp,bp
pop bp
ret 6
ADDPROC endp

MAINUI proc

@strWelcome = +4
push bp
mov bp,sp

push dx
push bx
WELCOME:
mov dx,[bp+@strWelcome]
mov ah,09
int 21h

mov dl,0dh ;== /r
mov ah,02
int 21h

mov dl,0ah ;== /n
int 21h
mov bl,0dh ;bl初始为0d,防止第一次就输入回车,可供selectfun标号用,让程序返回到UI
INPUT: ;循环接受输入
mov ah,01
int 21h
cmp al,0dh ;输入回车就跳出循环
jz SELECTFUN
mov bl,al ;输入项由bl保存,
JMP INPUT


SELECTFUN:

mov dl,0dh ;== /r
mov ah,02
int 21h

mov dl,0ah ;== /n
int 21h

cmp bl,0dh
jz WELCOME

cmp bl,'1' ;比较操作,确定分支
jnz ELSEIF_BEGIN1 ;增加子程序
IF_BEGIN:
mov ax,offset g_inputname
push ax
mov ax,offset g_inputtel
push ax
mov ax,offset g_filename
push ax ;g 02cb
call ADDPROC
jmp WELCOME
IF_END:
ELSEIF_BEGIN1:
cmp bl,'2'
jnz ELSEIF_BEGIN2
call DELPROC
jmp WELCOME
ELSEIF_END1:
ELSEIF_BEGIN2:
cmp bl,'3'
jnz ELSEIF_BEGIN3
CALL DELPROC
CALL ADDPROC
jmp WELCOME
ELSEIF_END2:
ELSEIF_BEGIN3:
cmp bl,'4'
jnz ELSEIF_BEGIN4
CALL QUERYPROC
JMP WELCOME
ELSEIF_END3:
ELSEIF_BEGIN4:
cmp bl,'5' ;g02f2
jnz ELSE_BEGIN ;quit
SAFEEXIT:
pop bx
pop dx
mov sp,bp
pop bp
ret 2
ELSEIF_END4:
ELSE_BEGIN:
jmp WELCOME
ELSE_END:

MAINUI endp

start:
mov ax,THESTACK
mov ss,ax
mov ax,THEDATA
mov ds,ax
mov si,0
mov ax,offset g_mainUI
push ax
call MAINUI

mov ax,4c00h
int 21h

MAINFUNCTION ends
end start


...全文
309 1 打赏 收藏 转发到动态 举报
写回复
用AI写文章
1 条回复
切换为时间正序
请发表友善的回复…
发表回复
IT保安 2015-10-27
  • 打赏
  • 举报
回复
找到问题了,改代码把一句关键的给删了,mov ax,ds mov es,ax,

21,458

社区成员

发帖
与我相关
我的任务
社区描述
汇编语言(Assembly Language)是任何一种用于电子计算机、微处理器、微控制器或其他可编程器件的低级语言,亦称为符号语言。
社区管理员
  • 汇编语言
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧