.model small
.stack 100h
.data
msg1 db "Enter a 3-digit number: $"
msg2 db "Armstrong number!"
msg3 db "Not an Armstrong number!"
notValid db "Please enter a 3-digit number (100-999): $"
numStr db 10 dup('$') ; String to store user input (10 characters)
num dw 0 ; Integer to store converted number
.code
main proc
mov ax, @data
mov ds, ax
mov dx, offset msg1
mov ah, 09h
int 21h
; Read user input as a string
mov ah, 0Ah
mov dx, offset numStr
int 21h
; Check if the input length is 3
mov cx, 0
loop_check:
mov bl, [numStr + cx]
cmp bl, '$'
je check_done ; Reached end of string
inc cx
jmp loop_check
check_done:
cmp cx, 3
jne not_valid ; Not a 3-digit number
; Convert string to integer (assuming digits only)
mov si, offset numStr
mov di, offset num
mov cx, 0
loop_convert:
mov al, [si]
sub al, 30h ; Convert ASCII digit to integer
mov [di], ax
inc si
inc di
loop loop_convert
; Process the number as before (unchanged)
mov ax, num
xor cx, cx
xor bx, bx
mov dx, 10
l1:
div dx
add bx, dx
inc cx
cmp ax, 0
jne l1
cmp bx, num
jne not_armstrong
mov dx, offset msg2
mov ah, 09h
int 21h
jmp exit
not_armstrong:
mov dx, offset msg3
mov ah, 09h
int 21h
exit:
ret
main endp
end main
我尝试读取用户的多个数字,但无法工作。
阿姆斯特朗数/自恋数
是一个数字,它是它自己的数字的总和,每个数字的位数次方。
https://en.wikipedia.org/wiki/Narcissistic_number
在上述情况
(100 - 999)
中,我们搜索3-digit numbers
。确切地说,有 4 种可能的结果。
153 = 1^3 + 5^3 + 3^3
370 = 3^3 + 7^3 + 0^3
371 = 3^3 + 7^3 + 1^3
407 = 4^3 + 0^3 + 7^3
Masm 汇编 op 的代码,但指令
mov bl, [numStr + cx]
被解释为 mov bh, [bx + si + 0070]
,8A B8 70 00
。
Tasm 显示错误
Illegal indexing mode
。
上面的代码中也不存在标签
not_valid
。
解决方案:
首先我们要检查用户输入了多少个字符。
此信息存储在偏移量
numStr + 1
下。这就是服务ah = 0ah, int 21h
的运作方式。
第一个字节
numStr
是最大字符数+0dh(CR)
第二个字节
numStr + 1
是没有0dh(CR)的所有字符
第三个字节
numStr + 2
是缓冲区的开始
在上面的代码中
numStr
包含 10 x '$' = 24h = 36
所以这不好。
我将其更改为
numStr db 4, ?, 4 dup('$')
First byte, max 4 chars = 3 digits + 0dh
Second byte, ? = after pressing enter this byte contains max number of values
Third byte, 4 dup('$') = start of the buffer
loop_convert
应该将数字从缓冲区转换为整数,但计算错误,因为 si
不包含缓冲区的偏移量。
另外 ax
有一些奇怪的值。代码:
.model small
.stack 100h
.data
msg1 db "Enter a 3-digit number: $"
msg2 db "Armstrong number!",13,10,'$'
msg3 db "Not an Armstrong number!",13,10,'$'
msg4 db "Not enough digits in the buffer, we need 3 digits!",13,10,'$'
msg5 db "Number in buffer starts with 0.",13,10,'$'
msg6 db "Characters in the buffer are not digits.",13,10,'$'
numStr db 4,?, 4 dup('$') ; String to store user input (3 characters + 0dh (CF))
num dw 0 ; Integer to store converted number
.code
main proc
mov ax, @data
mov ds, ax
mov dx, offset msg1
mov ah, 09h
int 21h
; Read user input as a string
mov ah, 0Ah
mov dx, offset numStr
int 21h
; Check if the input length is 3
mov dl, [numStr + 1]
cmp dl, 3
je digits_in_the_buffer
jmp buffer_msg
; search for buffer errors
digits_in_the_buffer:
mov cx, 3 ; check 3 digits
mov si, offset numStr ; digits are stored here
add si, 2
push si ; save buffer offset
cmp byte ptr [si], '0' ; first character in the buffer can't be 0
je first_char_is_zero
check_characters: ; all characters should be digits
cmp byte ptr [si], '0'
jb wrong_char
cmp byte ptr [si], '9'
ja wrong_char
inc si
dec cx
jnz check_characters
; Convert string to integer
chars_in_the_buffer_ok: ; number ok
pop si ; restore buffer offset
mov cx, 2
mov bl, 10
xor ax, ax
xor dx, dx
mov al, [si] ; first digit from the buffer
sub al, '0' ; Convert ASCII digit to integer
loop_convert:
mul bl ; 8bit multiplication, result is in ax
inc si
mov dl, [si]
sub dl, '0'
add al, dl
dec cx
jnz loop_convert
mov [num], ax
mov dx, offset msg2 ; print new line
add dx, 17
mov ah, 09h
int 21h
sub si, 2 ; return to start of the buffer
; armstrong number
armstrong_number:
mov cx, 3 ; outer loop counter for each digit
xor di, di ; result will be stored in di
xor bx, bx
process_digit:
xor ax, ax
mov al, [si] ; digit from buffer
sub al, '0'
mov bl, al
push cx ; save outer loop counter
mov cx, 2 ; inner loop counter
inner_loop:
mul bx ; calculate power of each digit
dec cx
jnz inner_loop
add di, ax
inc si
pop cx
dec cx
jnz process_digit
cmp di, word ptr [num] ; compare armstrong number with our integer
jnz not_armstrong
mov dx, offset msg2 ; if armstrong number print hooray msg
mov ah, 09h
int 21h
jmp exit_app
; error messages
not_armstrong: ; else quit app
mov dx, offset msg3
mov ah, 09h
int 21h
jmp exit_app
first_char_is_zero:
mov dx, offset msg5
mov ah, 09h
int 21h
jmp exit_app
wrong_char:
mov dx, offset msg6
mov ah, 09h
int 21h
jmp exit_app
buffer_msg:
mov dx, offset msg4
mov ah, 09h
int 21h
exit_app:
mov ax,4c00h
int 21h
main endp
end main