Определить, есть ли в записи числа цифра, равная среднему арифметическому остальных цифр - 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
- Вычисление суммы всех цифр и их количества в числе
- Проверка каждой цифры на то, что она равна среднему арифметическому остальных цифр
- Вывод сообщений о найденных или не найденных цифрах
- Завершение программы.
ИИ поможет Вам:
- решить любую задачу по программированию
- объяснить код
- расставить комментарии в коде
- и т.д