Определить, есть ли в записи числа цифра, равная среднему арифметическому остальных цифр - Assembler (223113)
Формулировка задачи:
Задано целое беззнаковое число Х<65536. Определить, есть ли в записи числа цифра, равная среднему арифметическому остальных цифр?
Входное значение - число без знака длиной в слово – должно вводиться с клавиатуры. Результат работы – найденная цифра или соответствующее сообщение - необходимо вывести на экран. Обмен информацией с пользователем организовать в виде специальных сообщений, каждое из которых следует размещать в отдельной строке экрана.
Решение задачи: «Определить, есть ли в записи числа цифра, равная среднему арифметическому остальных цифр»
textual
Листинг программы
- LOCALS
- .model small
- .stack 100h
- .data
- X dw ?
- Prompt db 'Input X: ', '$'
- Error01 db 'Input error number',0Dh, 0Ah, '$'
- msgFoundDigit db 'Found Digit: '
- Digit db 0
- db 0Dh, 0Ah, '$'
- msgNotFound db 'Not found', 0Dh, 0Ah, '$'
- CrLf db 0Dh, 0Ah, '$'
- kbdBuf db 6, 0, 6 dup(?)
- .code
- main proc
- mov ax, @data
- mov ds, ax
- lea si, X
- lea di, Prompt
- call InputUInt16
- ;вычисление суммы всех цифр и их количества в числе
- mov ax, X
- mov bx, 0 ;bx=SumDigits - сумма цифр
- mov cx, 0 ;cx=N - количество цифр
- mov di, 10
- @@CalcSum:
- mov dx, 0 ;ax=Digit - очередная цифра
- div di
- add bx, dx
- inc cx
- or ax, ax
- jnz @@CalcSum
- ;проверка каждой цифры на то, что она равна
- ;среднему арифметическому остальных цифр
- ;т.е. Digit*(N-1)==(SumDigits-Digit)
- mov ax, X ;ax=X
- mov di, 10
- dec cx ;cx=N-1
- mov si, 0 ;количество найденных цифр
- jcxz @@Result ;если всего одна цифра в числе, то искать нечего
- @@ForEachDigit:
- mov dx, 0
- div di
- push ax
- push bx
- sub bx, dx ;bx=SumDigits-Digit
- mov ax, dx ;ax=Digit*(N-1)
- add dl, '0' ;перед затиранием от операции умножения значения в dx
- mov Digit, dl ;сохраним очередную цифру в памяти в виде символа
- mul cx
- cmp ax, bx ;Digit*(N-1)==(SumDigits-Digit) ?
- jne @@SkipShow
- inc si ;признак - цифра была найдена
- push ax
- push dx
- mov ah, 09h
- lea dx, msgFoundDigit
- int 21h
- pop dx
- pop ax
- @@SkipShow:
- pop bx
- pop ax
- or ax, ax
- jnz @@ForEachDigit
- @@Result:
- cmp si, 0
- jnz @@SkipMsg
- mov ah, 09h
- lea dx, msgNotFound
- int 21h
- @@SkipMsg:
- mov ax, 4C00h
- int 21h
- main endp
- ;ввод числа с обработкой ошибок
- ; ds:si - адрес числа
- ; ds:di - адрес строки приглашения к вводу
- InputUInt16 proc
- push ax
- push bx
- push cx
- push dx
- push si
- push di
- @@Input:
- push si
- push di
- ; ввод числа с клавиатуры (строки)
- mov ah, 09h
- mov dx, di
- int 21h
- mov ah, 0Ah
- lea dx, [kbdBuf]
- int 21h
- ; перевод строки (на новую строку)
- mov ah, 09h
- lea dx, [CrLf]
- int 21h
- pop di
- pop si
- ; преобразование строки в число
- push si
- push di
- mov di, si
- lea si, kbdBuf+1
- call Str2Num
- pop di
- pop si
- ; проверка на ошибку
- jnc @@NoError
- ; если есть ошибка ввода - напечатать сообщение об ошибке
- mov ah, 09h
- lea dx, Error01
- int 21h
- jmp @@Input
- ; если нет ошибки ввода - напечатать число
- @@NoError:
- pop di
- pop si
- pop dx
- pop cx
- pop bx
- pop ax
- ret
- InputUInt16 endp
- ; преобразования строки в число
- ; на входе:
- ; ds:[si] - строка с числом
- ; ds:[di] - адрес числа
- ; на выходе
- ; ds:[di] - число
- ; CY - флаг переноса (при ошибке - установлен, иначе - сброшен)
- Str2Num proc
- push ax
- push bx
- push cx
- push dx
- push ds
- push es
- push ds
- pop es
- mov cl, ds:[si]
- xor ch, ch
- inc si
- mov bx, 10
- xor ax, ax
- @@Loop:
- mul bx ; умножаем ax на 10 ( dx:ax=ax*bx )
- mov [di], ax ; игнорируем старшее слово
- cmp dx, 0 ; проверяем, результат на переполнение
- jnz @@Error
- mov al, [si] ; Преобразуем следующий символ в число
- cmp al, '0'
- jb @@Error
- cmp al, '9'
- ja @@Error
- sub al, '0'
- xor ah, ah
- add ax, [di]
- jc @@Error ; Если сумма больше 65535
- inc si
- loop @@Loop
- mov [di], ax
- clc
- pop es
- pop ds
- pop dx
- pop cx
- pop bx
- pop ax
- ret
- @@Error:
- xor ax, ax
- mov [di], ax
- stc
- pop es
- pop ds
- pop dx
- pop cx
- pop bx
- pop ax
- ret
- Str2Num endp
- ; выводит число из регистра AX на экран
- ; входные данные:
- ; ax - число для отображения
- ; cx - система счисления (не больше 10)
- Show_AX proc
- push ax
- push bx
- push cx
- push dx
- push di
- mov cx, 10 ; cx - основание системы счисления
- xor di, di ; di - кол. цифр в числе
- @@Conv:
- xor dx, dx
- div cx ; dl = num mod 10
- add dl, '0' ; перевод в символьный формат
- inc di
- push dx ; складываем в стэк
- or ax, ax
- jnz @@Conv
- ; выводим из стэка на экран
- @@Show:
- pop dx ; dl = очередной символ
- mov ah, 2 ; ah - функция вывода символа на экран
- int 21h
- dec di ; повторяем пока di<>0
- jnz @@Show
- pop di
- pop dx
- pop cx
- pop bx
- pop ax
- ret
- Show_AX endp
- end main
Объяснение кода листинга программы
- Инициализация переменных:
X
- двухбайтовая переменная для хранения введенного числаPrompt
- строка для приглашения к вводуError01
- строка для сообщения об ошибке при вводе числаmsgFoundDigit
- строка для сообщения о найденной цифреDigit
- переменная для хранения текущей проверяемой цифрыmsgNotFound
- строка для сообщения о том, что цифра не найденаCrLf
- строка для вывода новой строки на экранkbdBuf
- массив для хранения вводимого числа с клавиатуры
- Ввод числа с клавиатуры и обработка ошибок в InputUInt16
- Вычисление суммы всех цифр и их количества в числе
- Проверка каждой цифры на то, что она равна среднему арифметическому остальных цифр
- Вывод сообщений о найденных или не найденных цифрах
- Завершение программы.
ИИ поможет Вам:
- решить любую задачу по программированию
- объяснить код
- расставить комментарии в коде
- и т.д