令人调试到崩溃的程序帮忙看看哪里出了问题,在线等

jianshan198977 2010-12-14 05:39:48
设某班有30名同学,现需将汇编语言课程的考试成绩通过键盘输入,存入内存中(分数在0-99之间),并能查找最高分数和最低分数,能显示总分和平均成绩(十进制显示,平均值小数点后两位),要求采用子程序灬多模块可制作一简单菜单项实现以上功能。
我编的程序如下,只编的是输入4个成绩,每个成绩以空格间隔,最后一个输入完用空格结束。
编译连接都通过,但是不出我想要的结果。不显示最大值,最小值,总数和平均数。老是系统提示无效的指令,关闭了程序。

主程序
NAME EX2
PUBLIC DATA1
EXTRN MAX_GRADE:FAR,DISPLAY_DEC:FAR ;,MIN_GRADE:FAR,SUM_AVER:FA
DATA SEGMENT PARA 'DATA'
KEY_BUF DB 2 DUP(?) ;用来输入字符的缓存
DATA1 DB 4 DUP(?) ;用在存放成绩
DATA ENDS
STACK SEGMENT PARA STACK 'STA'
DW 200 DUP(?)
STACK ENDS
CODE SEGMENT PARA 'CODE'
ASSUME CS:CODE,DS:DATA,ES:DATA,SS:STACK
MAIN PROC FAR
START:MOV DI,OFFSET DATA1
MOV BH,4
FLAG1:MOV SI,OFFSET KEY_BUF
MOV BL,0
LOP1:
MOV AH,1
INT 21H
CMP AL,' '
JZ FLAG2
MOV [SI],AL
INC SI
INC BL
JMP LOP1
FLAG2:
MOV SI,OFFSET KEY_BUF ;将输入的十进制数转换成二进制储存
MOV AX,0
TRANS:
MOV DL,10
MUL DL
MOV DH,0
MOV DL,[SI]
AND DL,0FH
ADD AL,DL
INC SI
DEC BL
JNZ TRANS
MOV [DI],AX
INC DI
DEC BH
JNZ FLAG1

CALL MAX_GRADE
CALL MIN_GRADE
CALL SUM_AVER
RET
INT 20H
MAIN ENDP
CODE ENDS
END START
NAME EX21
EXTRN DISPLAY_DEC:FAR,DATA1:BYTE
PUBLIC MAX_GRADE ;求最大值
CODE SEGMENT PARA 'CODE'
ASSUME CS:CODE
MAX_GRADE PROC FAR
PUSH AX
PUSH BX
PUSH CX
PUSH DX
MOV SI,OFFSET DATA1
MOV CX,3
MOV AL,[SI]
L1:INC SI
CMP AL,[SI]
JAE L2
MOV AL,[SI]
L2:LOOP L1
CALL DISPLAY_DEC
INCLUDE SPACE.ASM
POP DX
POP CX
POP BX
POP AX
RET
MAX_GRADE ENDP
CODE ENDS
END
子程序
NAME EX22
EXTRN DISPLAY_DEC:FAR,DATA1:BYTE
PUBLIC MIN_GRADE ;求最小值
CODE SEGMENT PARA 'CODE'
ASSUME CS:CODE
MIN_GRADE PROC FAR
PUSH AX
PUSH BX
PUSH CX
PUSH DX
MOV SI,OFFSET DATA1
MOV CX,3
MOV AL,[SI]
L1:INC SI
CMP AL,[SI]
JBE L2
MOV AL,[SI]
L2:LOOP L1
CALL DISPLAY_DEC
INCLUDE SPACE.ASM
POP DX
POP CX
POP BX
POP AX
RET
MIN_GRADE ENDP
CODE ENDS
END
子程序
NAME EX23
EXTRN DISPLAY_DEC:FAR,DATA1:BYTE
PUBLIC SUM_AVER 求总和和平均值
CODE SEGMENT PARA 'CODE'
ASSUME CS:CODE
SUM_AVER PROC FAR
PUSH AX
PUSH BX
PUSH CX
PUSH DX
MOV SI,OFFSET DATA1
MOV CX,4
MOV AX,0
MOV BX,0
L3:MOV BL,[SI]
ADC AL,BL
INC SI
LOOP L3
CALL DISPLAY_DEC
INCLUDE SPACE.ASM
MOV BL,4
DIV BL
CALL DISPLAY_DEC
CALL SPACE
PUSH AX
PUSH BX
PUSH DX
MOV DL,2EH
MOV AH,2
INT 21H
POP DX
POP BX
POP AX
MOV CX,2
LOP5:CMP AH,0
JZ EXIT
MOV AL,AH
MOV BH,10
MUL BH
DIV BL
CALL DISPLAY_DEC
LOOP LOP5
EXIT:
POP DX
POP CX
POP BX
POP AX
RET
SUM_AVER ENDP
CODE ENDS
END

子程序
NAME EX24
PUBLIC DISPLAY_DEC 将成绩用于十进制显示
CODE SEGMENT PARA 'CODE'
ASSUME CS:CODE
DISPLAY_DEC PROC FAR
PUSH AX
PUSH BX
PUSH CX
PUSH DX
CMP AL,0
JNZ F1
MOV DL,30H
MOV AH,2
INT 21H
POP DX
POP CX
POP BX
POP AX
RET
F1:MOV BL,10
DIV BL
MOV DH,AH
CMP AL,0
JZ F2
ADD AL,30H
MOV DL,AL
MOV AH,2
INT 21H
F2:
ADD DH,30H
MOV DL,DH
MOV AH,2
INT 21H
POP DX
POP CX
POP BX
POP AX
RET
DISPLAY_DEC ENDP
CODE ENDS
END


SPACE PROC FAR ;输出空格(单独一个ASM)
PUSH AX
PUSH DX
MOV DL,' '
MOV AH,2
INT 21H
POP DX
POP AX
RET
SPACE ENDP

大虾们帮忙看看,我是汇编新手,第一次动手编,一定要帮帮我渡过这一关
我用DEBUG调试了,都正常,不知为什么,我但不运行了所有语句。
...全文
336 34 打赏 收藏 转发到动态 举报
写回复
用AI写文章
34 条回复
切换为时间正序
请发表友善的回复…
发表回复
zara 2010-12-16
  • 打赏
  • 举报
回复
[Quote=引用 31 楼 jianshan198977 的回复:]对我想请问“第二个是程序结束时直接 ret 了,但在程序开始处并没有相应的 psp:0000 压栈,改为 int21h(ah=4ch) 的功能调用吧。”
为什么不能这样。没有压堆栈的操作就不用ret吗[/Quote]
ret 是将这时栈顶的内容作为返回地址的;如果前面没有压栈,你堆栈里会是什么呢,你要这个 ret 指令返回到哪里呢?所以,通常情况下,要求堆栈类操作得一一对应,能够匹配起来,保持平衡。
如果一定要用这样的方法,程序开始必须要这样:
main  proc  far  ; 定义为 far,以使 ret 实际为 retf 指令
push ds ;程序开始时 ds 指向 psp
mov ax, 0
push ax
...
ret ; 返回到 psp:0000 处, 那里是个 int20h 指令, 也可以实现 "结束程序返回DOS" 的功能
; ^ int20h 要求调用时 cs 指向 psp, 所以一般不能直接调用
main endp
CJBAAA 2010-12-15
  • 打赏
  • 举报
回复
debug下单步走一下吧
zara 2010-12-15
  • 打赏
  • 举报
回复
结果的错误方面,主要是 ex24 里在 DIV BL 之前,应将 AH 置 0。ex23 中在显示小数点之前,不要再调用显示空格了。
zara 2010-12-15
  • 打赏
  • 举报
回复
运行出现异常,主要有两个问题:一个是 include space.asm,这个定义是个子程,直接插入到执行序列里,最后的 ret 肯定不对,而且链接时就有重复定义的错误吧,不知道你们是怎么能生成最后的 exe 文件的;应该将其改为 call space,将 space.asm 改写为完成的源程序。第二个是程序结束时直接 ret 了,但在程序开始处并没有相应的 psp:0000 压栈,改为 int21h(ah=4ch) 的功能调用吧。
这么修改后,程序执行上没有异常,但结果好像不对?可以再仔细看看转换和排序方面了。
jianshan198977 2010-12-15
  • 打赏
  • 举报
回复
我想加一个简单的菜单项,用BIOS调用,上翻页,下翻页大家有这方面的范例吗,我想学习哈
Rain208 2010-12-15
  • 打赏
  • 举报
回复
应该在保护模式下运行吧。
你写的这个应该是在实模式下的程序
在dos系统下应该可以运行。在xp 以上系统都是运行在保护模式下了。
jianshan198977 2010-12-15
  • 打赏
  • 举报
回复
NAME EX2
PUBLIC DATA1
EXTRN MAX_GRADE:FAR ,MIN_GRADE:FAR,SUM_AVER:FAR ,DISPLAY_DEC:FAR
DATA SEGMENT PARA 'DATA'
KEY_BUF DB 2 DUP(?)
DATA1 DB 4 DUP(?)
DATA ENDS
STACK SEGMENT PARA STACK 'STA'
DW 200 DUP(?)
STACK ENDS
CODE SEGMENT PARA 'CODE'
ASSUME CS:CODE,DS:DATA,ES:DATA,SS:STACK
MAIN PROC FAR
START:MOV DI,OFFSET DATA1
MOV BH,4
FLAG1:MOV SI,OFFSET KEY_BUF
MOV BL,0
LOP1:
MOV AH,1
INT 21H
CMP AL,' '
JZ FLAG2
MOV [SI],AL
INC SI
INC BL
JMP LOP1
FLAG2:
MOV SI,OFFSET KEY_BUF
MOV AX,0
TRANS:
MOV DL,10
MUL DL
MOV DH,0
MOV DL,[SI]
AND DL,0FH
ADD AL,DL
INC SI
DEC BL
JNZ TRANS
MOV [DI],AL
INC DI
DEC BH
JNZ FLAG1

CALL MAX_GRADE
CALL MIN_GRADE
CALL SUM_AVER
MOV AH,4CH
INT 21H

MAIN ENDP
CODE ENDS
END START


NAME EX21
EXTRN DATA1:BYTE,DISPLAY_DEC:FAR
PUBLIC MAX_GRADE
CODE SEGMENT PARA 'CODE'
ASSUME CS:CODE
MAX_GRADE PROC FAR
PUSH AX
PUSH BX
PUSH CX
PUSH DX
MOV SI,OFFSET DATA1
MOV CX,3
MOV AL,[SI]
L1:INC SI
CMP AL,[SI]
JAE L2
MOV AL,[SI]
L2:LOOP L1
CALL DISPLAY_DEC
CALL SPACE
POP DX
POP CX
POP BX
POP AX
RET
MAX_GRADE ENDP
INCLUDE SPACE.ASM
CODE ENDS
END


NAME EX22
EXTRN DATA1:BYTE,DISPLAY_DEC:FAR
PUBLIC MIN_GRADE
CODE SEGMENT PARA 'CODE'
ASSUME CS:CODE
MIN_GRADE PROC FAR
PUSH AX
PUSH BX
PUSH CX
PUSH DX
MOV SI,OFFSET DATA1
MOV CX,3
MOV AL,[SI]
L1:INC SI
CMP AL,[SI]
JBE L2
MOV AL,[SI]
L2:LOOP L1
CALL DISPLAY_DEC

CALL SPACE
POP DX
POP CX
POP BX
POP AX
RET
MIN_GRADE ENDP
INCLUDE SPACE.ASM
CODE ENDS
END


NAME EX23
EXTRN DATA1:BYTE,DISPLAY_DEC:FAR
PUBLIC SUM_AVER
CODE SEGMENT PARA 'CODE'
ASSUME CS:CODE
SUM_AVER PROC FAR
PUSH AX
PUSH BX
PUSH CX
PUSH DX
MOV SI,OFFSET DATA1
MOV CX,4
MOV AX,0
MOV BX,0
L3:MOV BL,[SI]
ADC AX,BX
INC SI
LOOP L3
CALL DISPLAY_DEC

CALL SPACE
MOV BL,4
DIV BL
CALL DISPLAY_DEC

PUSH AX
PUSH BX
PUSH DX
MOV DL,2EH
MOV AH,2
INT 21H
POP DX
POP BX
POP AX
MOV CX,2
LOP5:CMP AH,0
JZ EXIT
MOV AL,AH
MOV BH,10
MUL BH
DIV BL
CALL DISPLAY_DEC
LOOP LOP5
EXIT:
POP DX
POP CX
POP BX
POP AX
RET
SUM_AVER ENDP
INCLUDE SPACE.ASM
CODE ENDS
END


NAME EX24
PUBLIC DISPLAY_DEC
DATA SEGMENT PARA'DATA'
STR DB 5 DUP('0')
DATA ENDS
CODE SEGMENT PARA 'CODE'
ASSUME CS:CODE
DISPLAY_DEC PROC FAR
PUSH AX
PUSH BX
PUSH CX
PUSH DX
MOV SI,OFFSET STR
MOV BH,0
CMP AL,0
JNZ F1
MOV DL,30H
MOV AH,2
INT 21H
POP DX
POP CX
POP BX
POP AX
RET
F1:MOV BL,10
MOV AH,0
DIV BL
MOV DL,AH
ADD DL,30H
MOV [SI],DL
INC SI
INC BH
CMP AL,0
JZ F2
JMP F1
F2: MOV DL,[SI-1]
MOV AH,2
INT 21H
DEC SI
DEC BH
JNZ F2
POP DX
POP CX
POP BX
POP AX
RET
DISPLAY_DEC ENDP
CODE ENDS
END


SPACE PROC
PUSH AX
PUSH DX
MOV DL,' '
MOV AH,2
INT 21H
POP DX
POP AX
RET
SPACE ENDP

成功的代码
ylyy2002 2010-12-15
  • 打赏
  • 举报
回复
好久没碰汇编了。看一下是挺令人崩溃的。不过,lz加油啊!
jianshan198977 2010-12-15
  • 打赏
  • 举报
回复
[Quote=引用 27 楼 zara 的回复:]
运行出现异常,主要有两个问题:一个是 include space.asm,这个定义是个子程,直接插入到执行序列里,最后的 ret 肯定不对,而且链接时就有重复定义的错误吧,不知道你们是怎么能生成最后的 exe 文件的;应该将其改为 call space,将 space.asm 改写为完成的源程序。第二个是程序结束时直接 ret 了,但在程序开始处并没有相应的 psp:0000 压栈,改为 int2……
[/Quote]
谢谢指导呀,非常感谢
我重新改了编译连接成功了,运行出结果了。
运行:12 56 99 89 99 12 233 58.25
出来前四个数的最大值最小值了,还有总数和平均值。
对我想请问“第二个是程序结束时直接 ret 了,但在程序开始处并没有相应的 psp:0000 压栈,改为 int21h(ah=4ch) 的功能调用吧。”
为什么不能这样。
没有压堆栈的操作就不用ret吗

bajin911 2010-12-15
  • 打赏
  • 举报
回复
读不太懂
__________________ 2010-12-15
  • 打赏
  • 举报
回复
上网下载一个dos工具箱之类的。
用它启动到dos操作系统。
这样就可以用int之类的中断了
这就是实模式。dos就是实模式操作系统。
znxllyuan 2010-12-14
  • 打赏
  • 举报
回复
[Quote=引用 22 楼 masmaster 的回复:]
引用 21 楼 znxllyuan 的回复:
完蛋 我也遇见了

16 位 MS-DOS 子系统

D:MYDOCU~1\noname1.exe
NTVDM CPU遇到无效的指令
CS:CD09 IP:D055 OP:F0 37 05 10 02 选择“关闭”终止应用程序

关闭(C) 忽略(I)

你那程序在全屏下运行应该没事吧!
[/Quote]
我再查查 显示号码没问题 显示英文就乱了
masmaster 2010-12-14
  • 打赏
  • 举报
回复
[Quote=引用 21 楼 znxllyuan 的回复:]
完蛋 我也遇见了

16 位 MS-DOS 子系统

D:MYDOCU~1\noname1.exe
NTVDM CPU遇到无效的指令
CS:CD09 IP:D055 OP:F0 37 05 10 02 选择“关闭”终止应用程序

关闭(C) 忽略(I)
[/Quote]
你那程序在全屏下运行应该没事吧!
znxllyuan 2010-12-14
  • 打赏
  • 举报
回复
完蛋 我也遇见了

16 位 MS-DOS 子系统

D:MYDOCU~1\noname1.exe
NTVDM CPU遇到无效的指令
CS:CD09 IP:D055 OP:F0 37 05 10 02 选择“关闭”终止应用程序

关闭(C) 忽略(I)
jianshan198977 2010-12-14
  • 打赏
  • 举报
回复
怎么进,我是小白
masmaster 2010-12-14
  • 打赏
  • 举报
回复
[Quote=引用 17 楼 jianshan198977 的回复:]
什是么实模式
我不太懂
[/Quote]
就是说, 如果要是16位dos程序, 最好在实模式下运行,即纯的dos模式下。 因为如果在保护模式下运行16位dos程序, 也许会发生楼主所说的现象! 我也是瞎猜的! 既然编译没问题, debug又没问题(debug下没问题不代表运行没问题)。
jianshan198977 2010-12-14
  • 打赏
  • 举报
回复
怎么进入实模式下我不太会
jianshan198977 2010-12-14
  • 打赏
  • 举报
回复
什是么实模式
我不太懂
masmaster 2010-12-14
  • 打赏
  • 举报
回复
在实模式下运行试一试
jianshan198977 2010-12-14
  • 打赏
  • 举报
回复
一般出现这个,是哪里经常出错误
加载更多回复(14)

21,459

社区成员

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

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