当前位置:编程学习 > 汇编语言 >>

汇编问题,请高手指教

从键盘输入N个十进制数,求它们的和(累加和要求不大于65535),并将累加结果在屏幕上显示出来。要求给出必要的提示信息(用宏调用完成);累加功能由子程序调用实现;二进制数形式的累加和转换为十进制数并显示由子程序调用实现。
答案:;从键盘输入N个十进制数(数与数之间用空格隔开),以回车结束
;求它们的和(累加和要求不大于65535),
;并将累加结果在屏幕上显示出来。
;----------------------------------------------
DISP_STR  MACRO  X     ;宏定义.
    MOV  DX, OFFSET X
    MOV  AH, 9
    INT  21H
ENDM
;----------------------------------------------
DATA  SEGMENT          ;数据段.
  MSG1 DB  13, 10, 'Please Input : $'
  MSG2 DB  13, 10, 'I can not count so much ! $'
  MSG3 DB  13, 10, 'The SUM is : $'
    x DW  ?            ;存放新输入数据.
    y DW  ?            ;求和.
DATA  ENDS
;----------------------------------------------
CODE   SEGMENT         ;代码段.
    ASSUME   CS: CODE, DS: DATA
START:
    MOV  AX, DATA
    MOV  DS, AX
;--------------------------------
    DISP_STR  MSG1     ;宏调用,提示 Please Input :
    MOV  y,  0         ;和 清零.
;--------------------------------
IN_LOOP:
    MOV  x,  0         ;数据清零.
_INX:
    MOV  AH, 1         ;输入字符.
    INT  21H
    CMP  AL, 13        ;回车?
    JZ   _IN_END       ;全部数字结束.
    CMP  AL, ' '       ;空格?
    JZ   _INY          ;本数字结束.
    CMP  AL, 30H
    JB   _IN_ERR       ;小于'0',输入错误.
    CMP  AL, 3AH
    JNB  _IN_ERR       ;大于'9',输入错误.
;--------------------------------
    SUB  AL, 30H
    MOV  AH, 0
    MOV  CX, AX
    MOV  AX, x
    MOV  BX, 10        ;老数据乘以10
    MUL  BX
    AND  DX, DX
    JNZ  _IN_ERR       ;输入过大,错误.
    ADD  AX, CX        ;加上新数据.
    JC   _IN_ERR
    MOV  x,  AX        ;保存.
    JMP  _INX          ;继续输入.
;--------------------------------
_INY:
    MOV  AX, x         ;完整的新数据.
    ADD  AX, y         ;求和.
    JC   _IN_ERR
    MOV  y,  AX        ;保存.
    JMP  IN_LOOP       ;继续输入.
;--------------------------------
_IN_END:
    DISP_STR  MSG3     ;宏调用,提示  The SUM is :
    MOV  AX, x
    ADD  AX, y
    CALL PRINTAX       ;调用显示子程序
    JMP  EXIT
;--------------------------------
_IN_ERR:
    DISP_STR  MSG2     ;宏调用,提示 can not count so much !
EXIT:    
    MOV  AH, 4CH
    INT  21H
;--------------------------------
PRINTAX PROC   
    MOV  BX, 10 
    OR   AX, AX
    JZ   _0_
LOOP_P:
    XOR  DX, DX
    DIV  BX
    MOV  CX, AX     ;商.
    OR   CX, DX
    JZ   _E_        
    PUSH DX   
    CALL LOOP_P     ;递归.
    POP  DX         
    ADD  DL, '0'    
    JMP  _1_
_0_:MOV  DL, '0'  
_1_:CALL PUTC
_E_:RET
PRINTAX ENDP
;------------------------------
PUTC  PROC  
    MOV  AH, 2
    INT  21H
    RET
PUTC  ENDP
;------------------------------
CODE  ENDS
    END  START
;======================================
其他:;从键盘输入N个十进制数(数与数之间用空格隔开),回车求它们的和(累加和要求不大于65535),并将累加结果在屏幕上显示出来。
;
;
;用MASM 5.0 编译通过。(ESC退出)
;运行结果示范如下:
;E:\masm1>ins2
;11 22 33
;Sum all: 00066
;1 65534
;Sum all: 65535
;1 65535
;Sorry,too big!

data segment

sum1	 db 0dh,0ah,"Sum all: "
sum2 	db 5 dup (" "),0DH,0AH,'$'	;定义结果输出串,其中0DH,0AH相当于回车换行

crlf 	db 0dh,0ah,'$'	;输出回车换行

sum	dw 0		;和
temp 	dw 0		;输入的数

s1    	db '0123456789'
LL EQU $-S1
s2 	db 0dh,0ah,'Sorry,too big! ',0dh,0ah,'$'


data ends
code segment
        assume cs:code, ds:data 
main proc far
start:
push ds
xor ax,ax
push ax
mov ax,data
mov ds,ax
PUSH DS
POP ES
;-------------------------
ini:		;初始化
mov ax,0
mov sum,ax
mov temp,ax

n1:		;输入字符起始位
mov ah,8
int 21h

cmp al,1bh	;ESC则结束
jnz goon
ret

goon:
cmp al,0DH	;是回车则输出结果
jnz goon2
mov bx,SUM
ADD BX,TEMP	;必须加上已输入但没有按空格的这个数
jnc noover1
JMP mul_over
noover1:
;jmp output
call print_c
jmp ini

goon2:
cmp al," "	;是" "则SUM=SUM+TEMP
jnz goon1

PUSH AX		;显示" "字符
MOV DL,AL
MOV AH,2
INT 21H
POP AX

MOV AX,TEMP
ADD AX,SUM
JNC SUM22
JMP mul_over
SUM22:
MOV SUM,AX
XOR AX,AX
MOV TEMP,AX
JMP N1


goon1:
CALL C_1	;检测输入字符是否合法
JNZ N1		;不合法,直接重新输入

mov ah,0
PUSH AX		;显示输入的字符
MOV DL,AL
MOV AH,2
INT 21H




mov bx,temp	;将上一位输入的数乘以10,再加上这次输入的数

mov ax,10
mul bx
cmp dx,0	;如果上一位输入的数乘以10后(dx<>0),溢出。	
jnz mul_over
pop bx
sub bl,'0'
add ax,bx	;如果AX有进位,溢出。	
jc mul_over

jmp no_over

mul_over:
mov ah,9	;数据溢出。
mov dx,offset s2
int 21h
jmp ini

no_over:


mov temp,ax

JMP N1


main endp 
;================== 

C_1 PROC NEAR  ;检测输入的字符是否合法子程序
MOV DI,OFFSET S1
MOV CX,LL
REPNZ SCASB
ret
;返回:NZ=输入的值不在表内  ZR=输入的值在表内
C_1 ENDP
;===========  
;=====================
  print_c proc near  	;显示结果子程序. 将和转换成10进制数并显示。
			;实质是将存放和的BX依次除以10000、1000、100、10,然后依次显示其商及最后的余数
mov di,offset sum2	;存放10进制显示串的起始地址
mov ax,bx		;BX是和,也就是要转换的被除数,放入AX
mov bx,10000		;10000是第一个除数,因为AX的最大值是65535
mov dx,0		;当除数是16位的BX时,被除数是DX:AX,所以DX必须置0
div_again:

div bx			;DX:AX/BX
cmp bx,10		;当BX=10时结束转换
jnz save
add al,30h		;10位
mov [di],al
inc di
add dl,30h
mov [di],dl		;个位
jmp disp		;转显示
save:
add al,30h
mov [di],al		;保存商位
inc di
push dx			;余数继续除
mov dx,0
mov ax,bx
mov bx,10		;需将除数依次缩小10倍(即:10000、1000、100、10),所以每次要要除10
div bx
mov bx,ax
pop ax
xor dx,dx
jmp div_again
disp:
mov ah,9		;显示结果
mov dx,offset sum1
int 21h
ret
print_c endp
;======================
   
code ends
end start 

上一个:哪位汇编高手能帮我“用汇编语言求两个数的最小公倍数和最大公约数”?
下一个:在线作业急等!!!!用汇编语言将内存中的16位的有符号二进制数转换为十进制ASCII码形式

CopyRight © 2012 站长网 编程知识问答 www.zzzyk.com All Rights Reserved
部份技术文章来自网络,