我面临着关于 8086 汇编语言中的阿姆斯特朗数字的问题。该代码在 0 到 9 的范围内工作,但我希望它是 3 位数字

问题描述 投票:0回答:1
.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

我尝试读取用户的多个数字,但无法工作。

assembly x86-16 dosbox
1个回答
0
投票

阿姆斯特朗数/自恋数

是一个数字,它是它自己的数字的总和,每个数字的位数次方。

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


解决方案:

  1. 首先我们要检查用户输入了多少个字符。

    此信息存储在偏移量

    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
    

  1. 接下来我添加了代码,检查输入的字符是否仅为数字并且数字不以 0 开头。

  1. 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
© www.soinside.com 2019 - 2024. All rights reserved.