1

如何编写 8086 汇编语言程序来计算任何n数字的平均值?我写了两个程序。一个使用mov ah,01 int 21h输入函数,因此它只接受一个数字。出于这个原因,我不能输入像 10 这样的数字。

我从另一个缓冲区中读取。它可以接受很多数字,但问题是它不断循环。

这是第一个程序:

.MODEL SMALL
.DATA
        VAL1    DB      ?
        NL1     DB      0AH,0DH,'ENTER HOW MANY NO U WANT:','$'
        NL2     DB      0AH,0DH,'ENTER NO:','$'
        NL3     DB      0AH,0DH,'AVEARGE:','$'
.CODE
MAIN    PROC
        MOV AX,@DATA
        MOV DS,AX

        LEA DX,NL1
        MOV AH,09H
        INT 21H

        MOV AH,01H
        INT 21H
        SUB AL,30H

        MOV CL,AL
        MOV BL,AL
        MOV AL,00
        MOV VAL1,AL

LBL1:
        LEA DX,NL2
        MOV AH,09H
        INT 21H

        MOV AH,01H
        INT 21H
        SUB AL,30H

        ADD AL,VAL1
        MOV VAL1,AL
        LOOP LBL1

LBL2:
        LEA DX,NL3
        MOV AH,09H
        INT 21H

        MOV AX,00
        MOV AL,VAL1
        DIV BL
        ADD AX,3030H
        MOV DX,AX
        MOV AH,02H
        INT 21H

        MOV AH,4CH
        INT 21H

MAIN    ENDP
        END     MAIN

这是第二个:

TITLE "THIS PROGRAM CALCULATES ANY N NUMBER OF STUDENT AVERAGE SCORES"

.MODEL SMALL
.DATA
        VAL1         DB      ?
        DISPLAY1     DB      0AH,0DH,'HOW MANY NUMBER OF STUDENT SCORES DO YOU WANT TO INPUT? :','$'
        DISPLAY2         DB      0AH,0DH,'ENTER NO:','$'
        DISPLAY3         DB      0AH,0DH,'AVEARGE:','$'
    BUFFER       DB      3,4 DUP(?)
.CODE
MAIN    PROC

.STARTUP

        LEA DX,DISPLAY1 ; loads the message in the variable display 1
        MOV AH,09H  ; interrupt function to display the message
        INT 21H

        MOV AH,0AH  ; Read into buffer
    INT 21H
    SUB AL,30H

    MOV CL,AL
    MOV BL,AL   ; moves the content of al to bl register
        MOV AL,00   ; sets the value of al to zero, the value of al is now in bl register
        MOV VAL1,AL ; stores al in val1 NB: al is still zero.

LBL1:
        LEA DX,DISPLAY2 ; displays message in display 2
        MOV AH,09H
        INT 21H

        MOV AH,0AH  ;Read into buffer
    LEA DX,BUFFER
    INT 21H
    SUB AL,30H

        ADD AL,VAL1 ; add val1 to al i.e, it now adds the previous value to the new one.
        MOV VAL1,AL ; saves the added value to val 1.
        LOOP LBL1   ; continues too add.

LBL2:
        LEA DX,DISPLAY3 ; displays character in display 3
        MOV AH,09H
        INT 21H

        MOV AX,00   ; sets ax value back to 00
        MOV AL,VAL1 ; moves the total value back to al
        DIV BL      ; divides the total value with the inputed number of values tht was stored in bl
        ADD AX,3030H    ;  convert to ASCII
        MOV DX,AX   ; now moves the content of ax register to data register
        MOV AH,09H  ; this displays the result
        INT 21H

.EXIT

MAIN    ENDP
        END     MAIN
4

2 回答 2

1

您似乎对int 21h/0Ah. 第一次这样做时,您没有设置dx任何合理的缓冲区。您的输入将在您的提示下乱写(可能不会造成太大伤害)。在循环内部,您确实设置dx了正确的缓冲区。但是当int 21h/0Ah返回时,你使用al它就好像它很有用(两次)。我已经很久没有做dos了,但我记得那al将是输入的最后一个字符——几乎可以肯定是“输入”键——我认为是13或0Dh。

返回时int 21h/0Ah,缓冲区 ( buffer + 1) 中的第二个字节将是输入的字符数。我记得,这将包括“输入”键。您可能希望检查此值以查看需要多少个字符才能“转换”为数字。输入的字符(1 或 2)将从 开始buffer + 2。这些是您要转换为数字的字符 - 第一个字符 -'0' 乘以 10 + 第二个字符 -'0'。如果只有一个,或者只是字符 -'0'。

当您尝试打印结果时,您可以通过add ax, 3030h. 然后将此值移动到dx. int 21h/9需要一个指向 . 中以 $ 结尾的字符串的指针dx。这不是你所拥有的!要么将这两个字符移动到缓冲区并用'$'终止它,要么一次打印一个......我曾经喜欢那个 hokey int 29h,但你最好使用可以打印的东西标准输出(int 29h进入屏幕,无法重定向)。也许像...

...
add ax, 3030h
mov dx, ax
mov ah, 2
xchg dl, dh ; print dh first, then dl
int 21h
xchg dl, dh
int 21h ; I think ah is still okay here...
...

在进入你的循环之前LBL1:,你设置cl为......某事(我认为这是不对的)。ch“可能”是 xero,但我会确定!

这一切都未经测试,“来自记忆”......我可能记错了,但它应该让你更接近一点(我希望)......

于 2013-01-16T21:14:42.780 回答
-3
DATA SEGMENT 
  ONENO DW 04h
  SECONDNO DW 08h
  SUM DB 00h
  AVG DB 00h
ENDS    
CODE SEGMENT
ASSUME DS:DATA CS:CODE
    START:
        MOV AX,DATA
        MOV DS,AX
        MOV AX,00
        MOV AX,ONENO
        ADD AX,SECONDNO
        MOV SUM,AL
        MOV BL,02
        DIV BL
        MOV AVG,AL
     CODE ENDS
END START
于 2019-09-24T08:19:30.143 回答