这个汇编代码应该计算10个用户输入的4位数字的平均值,但我不知道为什么我输入的数字,它总是给我2340的平均值。
data segment
sum dw 2dup(0)
msg1 db 'Enter 10 numbers:', 0dh,0ah,'$'
msg2 db 'Average= ','$'
ends
stack segment
dw 10dup(0)
ends
code segment
assume cs:code,ds:data,ss:stack
main proc far
mov ax, data
mov ds, ax
mov ax, stack
mov ss, ax
mov ah, 09h
mov dx, offset msg1
int 21h
mov ch, 10
NextNumber:
mov cl, 4
mov di, 0
get:
mov ah, 07h
int 21h
cmp al, 30h
jb get
cmp al, 39h
ja get
mov ah, 02h
mov dl, al
int 21h
sub al, 30h
mov bl, al
mov ax, 10
mul di
mov bh, 0
add ax, bx
mov di, ax
dec cl
jnz get
add sum, di
mov sum+2, 0
adc sum+2, 0
mov ah, 02h
mov dl, 0ah
int 21h
mov dl, 0dh
int 21h
dec ch
jnz NextNumber
mov dx, sum+2
mov ax, sum
mov bx, 10
div bx
mov ah, 09h
mov dx, offset msg2
int 21h
mov cx, 4
mov bx, 10
next1: mov dx, 0
div bx
push dx
dec cx
jnz next1
mov cx,4
next2: pop dx
add dl, 30h
mov ah, 02h
int 21h
dec cx
jnz next2
mov ah, 4ch
int 21h
main endp
ends
end main
答案 0 :(得分:2)
stack segment
dw 10 dup (0)
ends
小的堆栈不会起作用......
mov ax, stack
mov ss, ax
...除非您忘记设置SP寄存器,因为现在程序可以认为它有足够大的堆栈。
add sum, di
mov sum+2, 0
adc sum+2, 0
上面的代码段显示了第一个问题。您不希望不断将 sum 变量的高位字归零。只需删除mov sum+2, 0
行即可。 sum 变量位于数据段中,并由编译器初始化为零。因此,从零开始不需要运行时工作。
mov dx, sum+2
mov ax, sum
mov bx, 10
div bx
mov ah, 09h
mov dx, offset msg2
int 21h
此代码段显示了第二个问题。您设法计算平均值并将其保存在AX寄存器中,然后通过调用DOS函数来销毁AX寄存器以显示消息!只需颠倒这些操作的顺序即可。首先显示,然后计算平均值。
答案 1 :(得分:1)
接下来是一个从键盘获取10个数字并显示平均值的程序。使用EMU8086制作并完全评论以帮助您理解。希望它可以帮到你:
.stack 100h
;------------------------------------------
.data
;------------------------------------------
msj1 db 13,10,'Enter a number (4 digits): $'
str db 6 ;MAX NUMBER OF CHARACTERS ALLOWED (5).
db ? ;LENGTH (NUMBER OF CHARACTERS ENTERED BY USER).
db 6 dup (?) ;CHARACTERS ENTERED BY USER.
buf db 6 dup('$') ;WILL HOLD NUMBERS WITH 5 DIGITS OR LESS.
suma dw 0 ;SUMATORY OF 10 NUMBERS.
msj2 db 13,10,'Average : $'
count db ? ;JUST A COUNTER.
;------------------------------------------
.code
;INITIALIZE DATA SEGMENT.
mov ax, @data
mov ds, ax
;------------------------------------------
;CAPTURE 10 NUMBERS
call clear_screen
mov count, 10 ;WE WILL CAPTURE 10 NUMBERS.
ten_numbers:
;DISPLAY MESSAGE.
mov ah, 9
mov dx, offset msj1
int 21h
;CAPTURE NUMBER AS STRING.
mov ah, 0Ah
mov dx, offset str
int 21h
;CONVERT CAPTURED NUMBER FROM STRING TO NUMERIC.
mov si, offset str ;PARAMETER FOR STRING2NUMBER.
call string2number ;NUMBER RETURNS IN BX.
;ADD TO SUMATORY.
add suma, bx
;REPEAT PROCESS FOR NEXT NUMBER.
dec count
jnz ten_numbers ;IF LAST OPERATION WAS NOT ZERO, JUMP
;------------------------------------------
;AVERAGE.
mov ax, suma
mov bl, 10
div bl ;AX / BL = QUOTIENT:AL, REMAINDER=AH.
;CONVERT QUOTIENT INTO STRING TO DISPLAY.
call dollars ;FILLS BUF WITH DOLLARS (REQUIRED TO DISPLAY).
mov ah, 0 ;CLEAR AH TO USE AX.
call number2string ;CONVERT AX. STRING RETURNS IN "BUF".
;DISPLAY MESSAGE.
mov ah, 9
mov dx, offset msj2
int 21h
;DISPLAY AVERAGE.
mov ah, 9
mov dx, offset buf
int 21h
;------------------------------------------
;WAIT FOR ANY KEY.
mov ah,7
int 21h
;------------------------------------------
;FINISH THE PROGRAM.
mov ax, 4c00h
int 21h
;------------------------------------------
;NUMBER TO CONVERT MUST ENTER IN AX.
;ALGORITHM : EXTRACT DIGITS ONE BY ONE, STORE
;THEM IN STACK, THEN EXTRACT THEM IN REVERSE
;ORDER TO CONSTRUCT STRING (BUF).
proc number2string
mov bx, 10 ;DIGITS ARE EXTRACTED DIVIDING BY 10.
mov cx, 0 ;COUNTER FOR EXTRACTED DIGITS.
cycle1:
mov dx, 0 ;NECESSARY TO DIVIDE BY BX.
div bx ;DX:AX / 10 = AX:QUOTIENT DX:REMAINDER.
push dx ;PRESERVE DIGIT EXTRACTED FOR LATER.
inc cx ;INCREASE COUNTER FOR EVERY DIGIT EXTRACTED.
cmp ax, 0 ;IF NUMBER IS
jne cycle1 ;NOT ZERO, LOOP.
;NOW RETRIEVE PUSHED DIGITS.
mov si, offset buf
cycle2:
pop dx
add dl, 48 ;CONVERT DIGIT TO CHARACTER.
mov [ si ], dl
inc si
loop cycle2
ret
endp
;------------------------------------------
;CONVERT STRING TO NUMBER IN BX.
;SI MUST ENTER POINTING TO THE STRING.
proc string2number
;MAKE SI TO POINT TO THE LEAST SIGNIFICANT DIGIT.
inc si ;POINTS TO THE NUMBER OF CHARACTERS ENTERED.
mov cl, [ si ] ;NUMBER OF CHARACTERS ENTERED.
mov ch, 0 ;CLEAR CH, NOW CX==CL.
add si, cx ;NOW SI POINTS TO LEAST SIGNIFICANT DIGIT.
;CONVERT STRING.
mov bx, 0
mov bp, 1 ;MULTIPLE OF 10 TO MULTIPLY EVERY DIGIT.
repeat:
;CONVERT CHARACTER.
mov al, [ si ] ;CHARACTER TO PROCESS.
sub al, 48 ;CONVERT ASCII CHARACTER TO DIGIT.
mov ah, 0 ;CLEAR AH, NOW AX==AL.
mul bp ;AX*BP = DX:AX.
add bx,ax ;ADD RESULT TO BX.
;INCREASE MULTIPLE OF 10 (1, 10, 100...).
mov ax, bp
mov bp, 10
mul bp ;AX*10 = DX:AX.
mov bp, ax ;NEW MULTIPLE OF 10.
;CHECK IF WE HAVE FINISHED.
dec si ;NEXT DIGIT TO PROCESS.
loop repeat ;COUNTER CX-1, IF NOT ZERO, REPEAT.
ret
endp
;------------------------------------------
;FILLS VARIABLE BUF WITH '$'.
;USED BEFORE CONVERT NUMBERS TO STRING, BECAUSE
;THESE STRINGS WILL BE DISPLAYED.
proc dollars
mov si, offset buf
mov cx, 6
six_dollars:
mov bl, '$'
mov [ si ], bl
inc si
loop six_dollars
ret
endp
;------------------------------------------
proc clear_screen
mov ah,0
mov al,3
int 10H
ret
endp
程序 string2number 和 number2string 对您未来的程序非常有用。注意它们的工作方式: string2number 采用0AH捕获的字符串并在BX中返回, number2string 从AX获取数字并将其返回到名为“buff”的变量中(填写'$')。
如果您有任何疑问,请询问。