汇编语言求最大值最小值和求和,编译没错但是数不对

c1z1h1 2016-03-11 09:14:30
刚刚接触汇编语言,老师留了作业但是不讲让自己想。要求是一个求一组数中的最大值最小值和总和,老师已经给了大部分的代码,剩下的自己补全。基本上刚拿到这个完全看不懂什么意思,完后试着画了流程图差不多明白了运算的原理是循环的比大小,但是打出来后,第一次是提示CMP AL,MAX以及后面的行有错,上网查了查试着修改后可以运行但是数不对。。目前处于崩溃中。。发到这里求大神帮看。完后。。呃基本上知道的不多请大神们耐心加见谅。。万分感谢!
上程序:

;-------------------------------------------------------------
; 编写一个求最大值、最小值、总和的程序
; 数据在数据段内直接初始化
; 将计算的结果在屏幕上显示出来
;-------------------------------------------------------------

.MODEL SMALL
;-------------------------------------------------------------
; 数据段的定义
;-------------------------------------------------------------
.DATA

; 数组直接在数据段内初始化
ARRY DW 150,263,370,472,580,666,776,860,944,70
DW 59,959,875,771,678,583,460,371,527,179
ARRY_LEN EQU ($-ARRY)/2 ; 避免了计算数据个数的麻烦

; 定义显示数据
STR_MAX DB 13,10,"MAX="
D_MAX DB 4 DUP("0"),13,10

STR_MIN DB "MIN="
D_MIN DB 4 DUP("0"),13,10

STR_SUM DB "SUM="
D_SUM DB 4 DUP("0"),13,10
STR_LEN EQU $-STR_MAX

; 定义变量
MAX DW 0 ; 最大值
MIN DW 0 ; 最小值
SUM DW 0 ; 总和


;-------------------------------------------------------------
; 代码段的定义
;-------------------------------------------------------------
.CODE

; 函数:将WORD变量中的数值转换成4位ASCII字符
; 入口:(AX)=数据,(DX)=4位ASCII字符的首地址
; 运行结果:首地址开始的四个字节内分别是:千位、百位、十位、个位
NUM_STR PROC
mov si,DX
;求个位数
MOV AX,AX
SUB DX,DX
MOV BX,10
DIV BX ; (AX)=D100×10+D10
; (DX)=D1
PUSH DX ; 保存个位数
;求十位数
SUB DX,DX
DIV BX ; (AX)=D100
; (DX)=D10
PUSH DX ; 保存十位数
SUB DX,DX
MOV BX,10
DIV BX ; (DX)=D100,(AX)=千位及以上
PUSH DX ; 保存百位数
PUSH AX ; 保存千位

; 数字转换成字符
exit: pop ax
add al,'0'
mov [si],al
inc si
pop ax
add al,'0'
mov [si],al
inc si
pop ax
add al,'0'
mov [si],al
inc si
pop ax
add al,'0'
mov [si],al
RET
NUM_STR ENDP

; 启动函数
START PROC
MOV AX,@DATA
MOV DS,AX
-------------------------------------分割线!下面这段就是自己补的部分,不过差不多全是在模仿别人写过的-----------------------------------
;以下循环程序 求MAX、MIN、SUM
MOV BX, OFFSET ARRY
MOV CX, ARRY_LEN
LOP:
MOV AL,[BX]
CMP AL,byte ptr MAX
JC NEXT1
MOV byte ptr MAX,AL
NEXT1:
CMP AL,byte ptr MIN
JNC NEXT2
MOV byte ptr MIN,AL
NEXT2:
ADD byte ptr SUM,AL
INC BX
LOOP LOP
------------------------------------------------------------------------------------------------------------------------------------------------------------------------
;以下程序处理MAX的显示
MOV AX,MAX
LEA DX,D_MAX
CALL NUM_STR

;以下程序处理MIN的显示
MOV AX,MIN
LEA DX,D_MIN
CALL NUM_STR

;以下程序处理SUM的显示
MOV AX,SUM
LEA DX,D_SUM
CALL NUM_STR

;调用系统中断,在控制台显示STR_MAX,STR_MIN,STR_SUM
LEA DX,STR_MAX
MOV BX,0
MOV CX,STR_LEN
MOV AH,40H
INT 21H

;程序结束
MOV AX,4C00H
INT 21H
START ENDP

END START

求帮助啊已经盯着看一天了
...全文
565 8 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
8 条回复
切换为时间正序
请发表友善的回复…
发表回复
fornetuse123 2016-03-13
  • 打赏
  • 举报
回复
引用 6 楼 c1z1h1 的回复:
@fornetuse123 大神我看了你的回复,这个程序前半段是老师直接给的,所以就没深究。。我上网查了一下说.DATA和DATA segment是一个意思只是写法不同是吗。。完后循环程序那块,我明白用JA和JB的意思,但是为什么不用JC和JNC看借位呢?完后NEXT2这步为啥有两个INC BX。。最后就是修改运行后发现最大值最小值都正确,总和应该是10613,显示的却是 :613,这是为什么啊问题较多见谅哈
我也是刚开始学习的菜鸟。 DATA和DATA segment是一个意思只是写法不同是吗 这个我不懂,因为汇编语言各个编译器的命令语法都不同,我是用的intel的汇编格式。 完后循环程序那块,我明白用JA和JB的意思,但是为什么不用JC和JNC看借位呢?完后NEXT2这步为啥有两个INC BX。 比较大小,你看借位标志标志干嘛呀,借位标志是用在数学运算有进借位的情况下,两个inc是因为每次读取的是一个字(2个)字节)内存 最后就是修改运行后发现最大值最小值都正确,总和应该是10613,显示的却是 :613,这是为什么啊 这个是因为程序代码不正确。这个程序存在以下问题, 1、没有检验数组数据是否小于0和大于2的16次方-1(无符号字变量的最大值) 2、没有考虑超过总和超过10000,即五位数的情况;因为它只是将其中的4个字节转换为ascii码显示 3、还有就是这个程序读起来真是很难受,si用来代表基址,那bx用来干吗?明明是循环程序,却偏要一条一条写,如各个位数的除法和转换,还有就是最后的显示段代码也有问题,你把一段内存整个读到屏幕上,最小值和最大值前面的0都被当作求和的低位值了。 我建议你还是找王爽老师的书自己自学吧,这个老师,教的太不符合程序员应该有的思维模式了
c1z1h1 2016-03-13
  • 打赏
  • 举报
回复
@fornetuse123 已经修改好了,可以运行,谢谢帮助!话说这分数是个什么机制。。
fornetuse123 2016-03-12
  • 打赏
  • 举报
回复
DATA segment ; 数组直接在数据段内初始化 ARRY DW 150,263,370,472,580,666,776,860,944,70 DW 59,959,875,771,678,583,460,371,527,179 ARRY_LEN EQU ($-ARRY)/2 ; 避免了计算数据个数的麻烦 ; 定义显示数据 STR_MAX DB 13,10,"MAX=" D_MAX DB 4 DUP("0"),13,10 STR_MIN DB "MIN=" D_MIN DB 4 DUP("0"),13,10 STR_SUM DB "SUM=" D_SUM DB 4 DUP("0"),13,10 STR_LEN EQU $-STR_MAX ; 定义变量 MAX DW 0 ; 最大值 MIN DW 0 ; 最小值 SUM DW 0 ; 总和 DATA ends ;------------------------------------------------------------- ; 代码段的定义 ;------------------------------------------------------------- .assume cs:CODE,ds:DATA CODE segment ; 函数:将WORD变量中的数值转换成4位ASCII字符 ; 入口:(AX)=数据,(DX)=4位ASCII字符的首地址 ; 运行结果:首地址开始的四个字节内分别是:千位、百位、十位、个位 NUM_STR PROC mov si,DX ;求个位数 MOV AX,AX SUB DX,DX MOV BX,10 DIV BX ; (AX)=D100×10+D10 ; (DX)=D1 PUSH DX ; 保存个位数 ;求十位数 SUB DX,DX DIV BX ; (AX)=D100 ; (DX)=D10 PUSH DX ; 保存十位数 SUB DX,DX MOV BX,10 DIV BX ; (DX)=D100,(AX)=千位及以上 PUSH DX ; 保存百位数 PUSH AX ; 保存千位 ; 数字转换成字符 exit: pop ax add al,'0' mov [si],al inc si pop ax add al,'0' mov [si],al inc si pop ax add al,'0' mov [si],al inc si pop ax add al,'0' mov [si],al RET NUM_STR ENDP ; 启动函数 START:MOV AX,DATA MOV DS,AX -------------------------------------分割线!下面这段就是自己补的部分,不过差不多全是在模仿别人写过的----------------------------------- ;以下循环程序 求MAX、MIN、SUM MOV BX, OFFSET ARRY MOV CX, ARRY_LEN LOP: MOV AL,[BX] CMP AL,byte ptr MAX JC NEXT1 MOV byte ptr MAX,AL NEXT1: CMP AL,byte ptr MIN JNC NEXT2 MOV byte ptr MIN,AL NEXT2: ADD byte ptr SUM,AL INC BX LOOP LOP ------------------------------------------------------------------------------------------------------------------------------------------------------------------------ ;以下程序处理MAX的显示 MOV AX,MAX LEA DX,D_MAX CALL NUM_STR ;以下程序处理MIN的显示 MOV AX,MIN LEA DX,D_MIN CALL NUM_STR ;以下程序处理SUM的显示 MOV AX,SUM LEA DX,D_SUM CALL NUM_STR ;调用系统中断,在控制台显示STR_MAX,STR_MIN,STR_SUM LEA DX,STR_MAX MOV BX,0 MOV CX,STR_LEN MOV AH,40H INT 21H ;程序结束 MOV AX,4C00H INT 21H code ends END START ;以下程序处理SUM的显示 MOV AX,SUM LEA DX,D_SUM CALL NUM_STR 这里D_MAX D_MIN D_SUM的值都没有从变量MAX MIN SUM哪里获得实际值,都还是0你传给字符转换函数有什么用 另外,怎么没有 segment /end segment/assume ds=data 这些命令,还用@来表示当前段基址,这是什么汇编语言[/quote] 哦 明白你的意思了,你是把最小最大和总和值转换后存入相应显示变量中了 那你这程序就是段定义和段引用以及相关的程序段开始结束命令不对了
fornetuse123 2016-03-12
  • 打赏
  • 举报
回复
引用 1 楼 fornetuse123 的回复:
以下程序处理MAX的显示 MOV AX,MAX LEA DX,D_MAX CALL NUM_STR ;以下程序处理MIN的显示 MOV AX,MIN LEA DX,D_MIN CALL NUM_STR ;以下程序处理SUM的显示 MOV AX,SUM LEA DX,D_SUM CALL NUM_STR 这里D_MAX D_MIN D_SUM的值都没有从变量MAX MIN SUM哪里获得实际值,都还是0你传给字符转换函数有什么用 另外,怎么没有 segment /end segment/assume ds=data 这些命令,还用@来表示当前段基址,这是什么汇编语言
哦 明白你的意思了,你是把最小最大和总和值转换后存入相应显示变量中了 那你这程序就是段定义和段引用以及相关的程序段开始结束命令不对了
fornetuse123 2016-03-12
  • 打赏
  • 举报
回复
以下程序处理MAX的显示 MOV AX,MAX LEA DX,D_MAX CALL NUM_STR ;以下程序处理MIN的显示 MOV AX,MIN LEA DX,D_MIN CALL NUM_STR ;以下程序处理SUM的显示 MOV AX,SUM LEA DX,D_SUM CALL NUM_STR 这里D_MAX D_MIN D_SUM的值都没有从变量MAX MIN SUM哪里获得实际值,都还是0你传给字符转换函数有什么用 另外,怎么没有 segment /end segment/assume ds=data 这些命令,还用@来表示当前段基址,这是什么汇编语言
c1z1h1 2016-03-12
  • 打赏
  • 举报
回复
@fornetuse123 大神我看了你的回复,这个程序前半段是老师直接给的,所以就没深究。。我上网查了一下说.DATA和DATA segment是一个意思只是写法不同是吗。。完后循环程序那块,我明白用JA和JB的意思,但是为什么不用JC和JNC看借位呢?完后NEXT2这步为啥有两个INC BX。。最后就是修改运行后发现最大值最小值都正确,总和应该是10613,显示的却是 :613,这是为什么啊问题较多见谅哈
fornetuse123 2016-03-12
  • 打赏
  • 举报
回复
DATA segment ARRY DW 150,263,370,472,580,666,776,860,944,70 DW 59,959,875,771,678,583,460,371,527,179 ARRY_LEN EQU ($-ARRY)/2 STR_MAX DB 13,10,"MAX=" D_MAX DB 4 DUP("0"),13,10 STR_MIN DB "MIN=" D_MIN DB 4 DUP("0"),13,10 STR_SUM DB "SUM=" D_SUM DB 4 DUP("0"),13,10 STR_LEN EQU $-STR_MAX MAX DW 0 ; 最大值 MIN DW 0 ; 最小值 SUM DW 0 ; 总和 DATA ends CODE segment assume cs:CODE,ds:DATA NUM_STR PROC mov si,DX ;求个位数 MOV AX,AX SUB DX,DX MOV BX,10 DIV BX PUSH DX SUB DX,DX DIV BX PUSH DX SUB DX,DX MOV BX,10 DIV BX PUSH DX PUSH AX pop ax add al,'0' mov [si],al inc si pop ax add al,'0' mov [si],al inc si pop ax add al,'0' mov [si],al inc si pop ax add al,'0' mov [si],al RET NUM_STR ENDP ; 启动函数 START:MOV AX,DATA MOV DS,AX MOV BX, OFFSET ARRY MOV CX, ARRY_LEN MOV Ax,[BX] MOV word ptr MIN,Ax LOP: MOV Ax,[BX] CMP Ax,word ptr MAX Jb NEXT1 MOV word ptr MAX,Ax jmp next2 NEXT1: CMP Ax,word ptr MIN Ja NEXT2 MOV word ptr MIN,Ax NEXT2: ADD word ptr SUM,Ax ADc word ptr SUM+2,0 INC BX inc bx LOOP LOP MOV AX,MAX LEA DX,D_MAX CALL NUM_STR ;以下程序处理MIN的显示 MOV AX,MIN LEA DX,D_MIN CALL NUM_STR ;以下程序处理SUM的显示 MOV AX,SUM LEA DX,D_SUM CALL NUM_STR MOV AX,SUM+2 LEA DX,D_SUM+2 CALL NUM_STR ;调用系统中断,在控制台显示STR_MAX,STR_MIN,STR_SUM LEA DX,STR_MAX MOV BX,0 MOV CX,STR_LEN MOV AH,40H INT 21H MOV AX,4C00H INT 21H code ends END START
iagme 2016-03-12
  • 打赏
  • 举报
回复
学习学习 一起进步

21,497

社区成员

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

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