10 个用户在程序集中输入数字的平均值
Average of 10 user entered numbers in assembly
这段汇编代码应该计算 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
接下来是一个从键盘获取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 捕获的字符串,returns 它在 BX 中,number2string 从 AX 中获取数字和 returns 它在一个名为 "buff" 的变量中(用“$”填充)。
有什么问题尽管问。
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 寄存器!只需颠倒这些操作的顺序即可。所以先显示,再计算平均值。
这段汇编代码应该计算 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
接下来是一个从键盘获取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 捕获的字符串,returns 它在 BX 中,number2string 从 AX 中获取数字和 returns 它在一个名为 "buff" 的变量中(用“$”填充)。
有什么问题尽管问。
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 寄存器!只需颠倒这些操作的顺序即可。所以先显示,再计算平均值。