Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- ;/****************************************************************************/;
- ;; Задание:
- ;; Програма вводит строку текста и выводит множество символов этой строки в
- ;; порядке убывания числа вхождений каждого символа в строку.
- ;; Выходное множество символов представляется в формате ""C1:N1,C2:N2,...",
- ;; где Ci - символ, а Ni - число вхождений этого символа, представленное в
- ;; десятичном виде. Если какие-либо слова строки могут быть интерпретированы
- ;; как беззнаковые пятиричные числа (размерность не более 2 байт), то цифры этих
- ;; чисел не попадают в процесс формирования выходного множества. Сумма всех
- ;; таких чисел выводится в двоичном виде.
- ;/****************************************************************************/;
- ;сегмент данных
- datas segment
- maxlength_in db 79 ;начало буфера для входной строки
- length_in db 0 ;реально введеннное количество символов
- string_in db 80 dup('0')
- length db 0 ;длина строки, не содержащей пятиричных чисел
- string db 79 dup ('0') ;сама строка
- length2 db 0 ;длина массива символов
- symbols db 158 dup ('$') ;массив символов в виде [ASCII код символа][частота]
- sum dw 0 ;сумма всех пятиричных чисел
- max_frequency db 0 ;максимальная частота
- digitFh db 05h
- fiveexp dw 1 ;Табличка для перевода из основания 5
- dw 5 ;в основание 10
- dw 25
- dw 125
- dw 625
- dw 3125
- dw 15625
- numFlag db 0
- wordLength db 0
- numberLength db 0
- message01 db 10,13,'Введите строку:',10,13,'->$'
- message02 db 0,' : ',30h,30h,30h,10,13,'$'
- message03 db 10,13,'Вхождение символов:',10,13,'$'
- datas ends
- ;сегмент стека
- stacks segment
- db 100h dup(?)
- stacks ends
- ;сегмент кода
- codes segment
- assume ss:stacks, ds:datas, cs:codes
- ;/****************************************************************************/;
- ; Ввод строки и определение ее длины
- ;/****************************************************************************/;
- enter_string proc
- mov ah,0Ah
- lea dx,maxlength_in
- int 21h
- ret
- enter_string endp
- ;/****************************************************************************/;
- ; подсчет частоты каждого символа
- ;/****************************************************************************/;
- calculate_symbols proc
- LOCALS
- cmp length,0 ;Длина стороки без чисел = 0
- jz @@end
- xor bx,bx
- mov bl,length ;bх = length
- xor di,di ;di для строки symbols
- mov si,-1
- mov dl,20h ;в dl код пробела
- mov dh,0
- @@scan_beg:
- inc si ;идем по циклу в поисках нового символа
- cmp si,bx ;Надеюсь ещё не конец строки
- jge @@scan_end ;А ТО КАК....
- mov al,string[si] ;al = string[si]
- cmp al,dl ;al = пробел?
- jz @@scan_beg ;Если ,то следю символ, а так - дальше
- push si ;подсчет кол-ва символов
- mov ah,1 ;Ага, первое вхождение уже есть!!!
- @@calc_freq_beg:
- inc si
- cmp si,bx
- jge @@calc_freq_end ;Искать до конца строки!!!
- cmp string[si],al ;Неужли снова он?
- jne @@calc_freq_beg ;Не, показалось!!!
- inc ah ; Или всё-таки ОН?!?!
- mov string[si],dl ;заменяем новый, подсчитанный символ на пробел
- jmp short @@calc_freq_beg ;Что бы не видеть его снова, походу!!!
- ;Или нам так больше нравится?!?!
- @@calc_freq_end:
- cmp ah,max_frequency ;определяем максимальную частоту среди символов
- jle @@not_greater
- mov max_frequency,ah ;и заносим её из ah
- @@not_greater:
- mov word ptr symbols[di],ax ;записываем в массив symbols код символа
- ;и его частоту
- add di,2 ;в di 2,т.к. у нас там и символ и его вхождение
- pop si ;Так или иначе, а начнём мы все равно
- ;с символа, следующего за предыдущим!!!
- jmp short @@scan_beg
- @@scan_end:
- mov dx,di ;длина массива symbols
- mov length2,dl
- @@end:
- ret
- calculate_symbols endp
- ;/****************************************************************************/;
- ; вывод "символ : частота "
- ;/****************************************************************************/;
- print_symbols proc
- LOCALS
- cmp length,0 ;В строке с символами кто нибудь наблюдается???
- jz @@for1end ;@@for1end - зашифрованная метка конца процедуры!
- xor di,di
- mov bx,0A64h ;в bh - 10, в bl - 100
- xor cx,cx
- mov cl,length2 ;В сх длину строки symbols
- @@for1beg:
- cmp max_frequency,0h ;Если получилось так, что символов с нулевым
- ;вхождением отсутствует, тогда
- jz @@for1end ;конец!!!
- xor si,si ;Счётчик, с помощью колторого просматриваем строку.
- @@for2beg:
- cmp si,cx ;Ба, конец!!! Надо уменьшить max_frequency
- jge @@for2end
- mov ax,word ptr symbols[si] ;ах = очередному символу.
- cmp ah,max_frequency ;частота символа меньше максимальной - не выводим
- jnz @@not_equal_max
- ;ZYRAB
- mov message02[0],al ;вывод символа symbols[si]
- inc si
- mov al,ah ;делим на 100 - выделяем цифру сотен
- xor ah,ah
- div bl
- add message02[4],al
- mov al,ah ;делим на 10 - выделяем цифры десятков и единиц
- xor ah,ah
- div bh
- add message02[5],al
- add message02[6],ah
- mov ah,09h
- lea dx,message02
- int 21h
- mov message02[4],30h
- mov message02[5],30h
- mov message02[6],30h ;начиная от ZYRAB, сначала выводится символ
- ;а затем, количество вхождений.
- inc si
- jmp short @@for2beg
- @@not_equal_max:
- add si,2
- jmp short @@for2beg
- @@for2end: ;А здесь как раз и творится беспредел с
- dec max_frequency ;уменьшением числа вхождений
- jmp @@for1beg ;Будем искать символ с меньшим вхождением!!!Go!!!
- @@for1end:
- ret
- print_symbols endp
- ;/****************************************************************************/;
- ; поиск пятиричных чисел и вывод их суммы
- ;/****************************************************************************/;
- find_pental_numbers proc
- LOCALS
- cmp length_in,0 ;Вы забыли ввести символы???
- jnz @@ok
- jmp @@binary_sum_end
- @@ok:
- mov si,-1 ;si счётчик.
- xor di,di ;Очень важный момент!!!
- xor bh,bh ;в bx - length_in
- mov bl,length_in
- @@calc_sum_beg:
- inc si
- cmp si,bx ;если не конец строки
- jl @@ok1 ;то дальше
- jmp @@calc_sum_end ;Единственный выход из этой процедуры
- @@ok1:
- cmp string_in[si],20h ;если пробел - переходим к следующему символу
- jz @@calc_sum_beg
- ;ПОДСЧЁТ ДЛИНЫ ОЧЕРЕДНОГО СЛОВА
- push si ;si в стек
- mov wordLength,1 ;В wordLength длина слова
- inc si
- @@calc_length_beg:
- cmp si,bx ;если конец строки,
- jge @@calc_length_end
- cmp string_in[si],20h ;ИЛИ ПРОБЕЛ
- jz @@calc_length_end ;то закончим с определением wordLength
- inc wordLength
- inc si
- jmp short @@calc_length_beg
- @@calc_length_end:
- pop si ;si из стека
- cmp wordLength,7 ;максимальное пятиричное число - 4044120(5)=65535(10)
- jg @@copy_word_beg
- push si ;ПРОВЕРКА НА 5тиричные цифры
- mov cl,wordLength ;В cl длину слова
- mov numberLength,0 ;Длина числа = 0
- @@check_word_beg:
- xor ax,ax
- cmp si,bx
- jge @@check_word_end ;Лишь бы не конец строки
- cmp string_in[si],30h ;Если <'0'
- jl @@check_word_end
- cmp string_in[si],34h ;или >'4'
- jg @@check_word_end ;то это не число!!!
- inc numberLength
- inc si
- inc ax ;Это логика!!! (true or false)
- dec cl
- cmp cl,0
- jg @@check_word_beg
- @@check_word_end:
- pop si
- cmp ax,0 ;Прочитанное слово не число!!!
- jz @@copy_word_beg
- xor dh,dh ;преобразование в число
- mov dl,numberLength ;В dx - количество цифр в числе
- push dx
- xor cx,cx
- push si
- push di
- xor di,di
- add si,dx ;si указывает на конец числа.
- dec si
- @@convert_beg:
- xor ax,ax
- mov al, byte ptr string_in[si] ;Преобразование с конца
- sub al,30h
- mul fiveexp[di] ;Помните табличку для перевода из
- ;основания 5 в основание 10
- add cx,ax ;В сх - десятичное представление числа
- add di,2
- dec si ;Мы ещё ближе к началу числа
- dec numberLength
- cmp numberLength,0 ;От числа ещё что-то осталось
- jg @@convert_beg
- @@convert_end:
- pop di
- pop si
- pop dx
- add si,dx
- add sum,cx ;Скаладываем с тем что есть
- jmp @@calc_sum_beg
- @@copy_word_beg: ;копируем слово в строку символов
- cmp wordLength,0
- jnz @@ok2
- jmp @@calc_sum_beg ;Перепрыгнуть туда, где определ-ся
- ;Длина слова, числа и т.п.
- @@ok2:
- mov al,string_in[si] ;В аl - очередной символ
- mov string[di],al ;Засунем мы его в строку без чисел!!!
- inc di
- inc si
- dec wordLength
- jmp short @@copy_word_beg
- @@calc_sum_end:
- mov bx,di
- mov length,bl ;В байте bl - длина строки без чисел
- ;Помещаем это чило в length
- mov bx,sum ;Почти стандартный вывод суммы
- mov cx,16 ;в двоичном виде даже ничего интересного нет!!!
- mov ah,2h
- @@binary_sum_end:
- ret
- find_pental_numbers endp
- ;/****************************************************************************/;
- ; точка входа
- ;/****************************************************************************/;
- main:
- mov ax,datas
- mov ds,ax
- mov ah,9h ;вывод приглашения
- lea dx,message01
- int 21h
- call enter_string ;ввод строки
- call find_pental_numbers ;поиск пятиричных чисел и вывод их суммы
- mov ah,9h
- lea dx,message03
- int 21h
- call calculate_symbols ;подсчет частоты символов
- call print_symbols ;вывод данных
- mov ah,4Ch
- int 21h
- codes ends
- end main
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement