Лабораторна робота 8.
Тема: Ланцюжкові команди Асемблера
Ціль: Вивчити основні прийоми обробки рядків у програмах на асемблері.
model tiny
.code
org 100h
Start:
mov si, offset MyStr ; Инициализируем
mov di, offset SubSt ; индексы строк.
M1: call StrLen ; Подсчитать длину строки SubSt
call Compare ; Производим поиск SubStr в MyStr с
; очередного символа.
jc M2
sub si, offset MyStr ; !!! Нашли !!!
inc si
mov InNum, si ; Запишем позицию вхождения.
ret
M2: inc si ; Подстроку не нашли - продолжаем цикл.
cmp byte ptr [si], 0
jne M1
mov InNum, 0 ; Так и не удалось найти подстроку.
ret
MyStr db 'Ассемблер - это язык низкого уровня.',0
SubSt db 'язык ',0
InNum dw ?
StrLen proc
; Осуществляет подсчёт длины строки ASCIIZ.
; Вход - адрес начала строки (в регистре DI).
; Выход - количество символов в строке (в регистре CX).
; !Сама очищает стек от параметров!
push si ; Сохраняем значение регистра SI.
mov si, di
dec si
L11: inc si
cmp byte ptr [si], 0
jne L11
mov cx, si ; Возвращаем результат в CX.
sub cx, di
pop si ; Восстанавливаем значение SI.
ret
StrLen endp
Compare proc
; Производит сравнение CX байт строки по адресу SI с соответствующими
; CX байтами строки по адресу DI. В случае равенства строк флаг CF=0,
; если строки неравны CF=1.
push si ; Сохраняем
push di ; использумые
push cx ; регистры.
cld ; Направление - вперёд.
repe cmpsb ; Сравнение.
jne L21
clc ; Строки равны.
jmp L22
L21: stc ; Строки не равны.
L22: pop cx ; Восстанавливаем
pop di ; сохранённые
pop si ; регистры.
ret
Compare endp
end Start
Задание 2
; Задана строка ASCII. Определить наиболее часто повторяющийся символ.
; Будем считать, что признаком конца строки является байт 00h. Дойдя до этого
; байта, считаем, что строка закончилась и прекращаем просмотр.
; Есть два способа решения этой задачи (оба плохие):
; I способ:
; Создаётся массив статистики из 256 однобайтовых элементов. Строка
; просматривается 1 раз и в зависимости от текущего символа строки,
; соответствующий байт массива статистики увеличивается на единицу.
; После чего, ищем максимальный элемент в массиве статистики. Позиция
; этого элемента и есть ответ.
; В этом алгоритме на вспомогательную структуру (массив статистики) тратится
; много памяти (весь код программы займёт около 20 байт, а этот массив целых
; 256). Зато строка будет просматриваться только один раз.
; II способ.
; Никакого массива статистики не создаётся. Вместо этого, исходная строка
; просматривается 256 раз и на каждом очередном просмотре подсчитывается
; количество соответствующих символов. После этого, количество символов
; сравнивается с максимумом и таким образом определяется часто встречающийся
; символ. Этот алгоритм требует меньше памяти, но гораздо дольше выполняется.
; Рассмотрим реализацию II способа:
model tiny
.code
org 100h
Start:
mov ah, 0 ; Счётчик внешнего цикла по всем элементам
; таблицы ASCII-кодов.
mov ch, 0 ; Частота вхождения самого частовстреч. символа.
M1: mov si, 0 ; Счётчик внутреннего цикла по всем символам
; строки MyStr.
mov cl, 0 ; Сколько раз встречался текущий символ.
M2: mov al, MyStr[si]
cmp al, ah
jne M3
inc cl ; Да, встретился текущий символ.
M3: inc si
cmp MyStr[si], 0 ; Завершение тела внутреннего цикла.
jne M2
cmp cl, ch
jna M4
mov ch, cl ; Нашли новый, более частовстречающися
mov FrecSim, ah ; символ.
M4: inc ah ; Завершение внешнего цикла - пока не
jnz M1 ; переберём все ASCII-символы от 0 до 255.
ret
MyStr db 'Шла Саша по шоссе и сосала сушку.',0 ; Исходная строка.
FrecSim db ? ; Наиболее часто встречающийся символ.
end Start