- •Курсовая работа
- •Часть I. Разработка гипотетической машины.
- •1.Цель работы Целью данной курсовой работы является изучение стандартных макросредств ассемблера ibm pc.
- •2.Задание
- •3.Введение
- •4.Постановка задачи
- •5.Разработка алгоритма
- •Задачи удаления лишних знаков препинания и определения длины каждого слова не являются сложными и их можно реализовать не разбивая их на подзадачи.
- •BeginProg – Инициализация программы. Здесь производится привязка сегментных регистров к соответствующим сегментам.
- •6.Алгоритм
- •7.Результаты
- •8.Листинг программы
- •Часть II. Самостоятельная работа
- •Основные понятия и определения.
- •Описание типов и экземпляров объектов
- •Скрытые поля и методы.
- •Как сказано выше приватные поля и методы должны располагатся после общедоступных. Директива public позволяет, если это удобно, расположить их наоборот.
- •Наследование и переопределение .
- •Статические и виртуальные методы.
- •Виртуальные методы и полиморфизм.
- •Совместимость объектных типов.
- •Преимущества и недостатки виртуальных методов.
- •Заключение
- •Литература
Задачи удаления лишних знаков препинания и определения длины каждого слова не являются сложными и их можно реализовать не разбивая их на подзадачи.
Рассмотрим задачу удаления лишних препинаний. Эта задача реализована макросом
DeleteSign. Решить задачу можно определением знаков препинаний и затем“удаления”
их путём затирания буквами, следующих за этими знаками. При этом надо не забывать
уменьшать длину строки в первом байте строки. Также нужно в конец каждого слова
записывать символ запятой, т.к. это записано в задании. Реализовать затирание
знаков препинания можно пересылая байты с буквами на место байтов с препинаниями.
Такую пересылку можно осуществить применив команду MOVSB столько раз сколько это необходимо. Т.о. команда DeleteSign работает по следующему алгоритму:
Найти начало первого слова.
Затереть препинания следующие перед первым словом.
Найти следущее слово.
Затереть препинания следущие перед этим словом.
Повторять п.4 пока не конец предложения.
Команду вставки в конец слова значения его длины также достаточно просто реализовать. Небольшую сложность представляет собой преобразование численного значения длины слова в символьный эквивалент. В случае если мы сможем это сделать , то вставку этого символьного эквивалента можно будет осуществить путем непосредственной записи соответствующих символов в строку , необходимо будет только зарезервировать в конце каждого слова определенное количество байт , в противном случае значение длины слова может затереть следующее слово.
Далее проходя последовательно по строке и находя конец слова вставлять его длину пока предложение не закончится.
Рассмотрим как реализуется алгоритм преобразования численного значения длины слова в символьный эквивалент.
Одним из возможных вариантов преобразования является табличное преобразование , т.е. по значению регистра R0 мы выбираем из заранее созданной таблицы необходимый символьный эквивалент , например с помощью команды XLAT. Однако такой вариант требует создания таблицы. Но есть у этого варианта и свои преимущества – так например если для записи использовать числа 16-ой или другой системы счисления , где используются не только символы цифр , то этот вариант более предпочтителен.
В данной команде(реализуется в макросе WriteLenWords) будем использовать числа в 10-й системе , как более наглядные. Преобразование производится следущим образом:
Если к примеру в R0 значение длины от 0 до 9 , то преобразовать к символьному эквиваленту достаточно легко прибавив к значению R0 число 4810 или 3016 . Тогда мы получим ASCII код числа. Если же в R0 число 2-ух или выше разрядов , то таким образом мы сможем преобразовать только единицы этого числа , но не десятки , сотни и т.д. Следовательно необходимо “выделить” из этого числа единицы , десятки , сотни и т.д. (в нашем случае только десятки и сотни , т.к. вся строка состоит из 250 символов идля представления самого длинного слова понадобится только 3 знака).
А т.к. числа в 10-й системе представляются так:
Xn*10^N+…+X2*10^2+X1*10^1+X0*10^0=десятичное число
где Хn – значение числа в N – ом разряде
N – разряд
то выделить их можно путем деления на 1 , 10 и 100 тогда каждый раз в остатке получим единичные разряды Xn. Далее прибавляя к ним константу 3016 получим необходимый символ.
Теперь рассмотрим разработку основного и самого сложного алгоритма – сортировка.
Сортировку будем осуществлять методом “пузырька”. Сама сортировка реализована в макросе Sorting. Однако сам макрос использует несколько других более простых макросов , т.е. задачу сортировки мы разбили на более простые подзадачи.
Алгоритм сортировки можно представить следущим образом:
While Flag do
Begin
Flag:= false;
For i:=1 to (N-1) do
if Word[i] > Word[i+1] then
Begin
ChangeWords Word[i] , Word[i+1];
Flag:= true
End;
End.
Где N – число элементов (слов).
Flag – флаг выхода из цикла(если все “пузырки всплыли”)
Word – элементы строки (слова).
Сложность представляет не сам процесс сортировки , и даже не процесс обращения к элементам сортировки – словам , а процесс обмена слов , т.к. слова могут быть различной длины , а команда ChangeWords выполняет обмен слов с одинаковой длиной. Одним из выходов является усложнение алгоритма обмена слов. На первый взгляд это решит проблему , однако решив эту проблему таким образом мы породим еще несколько проблем. В частности придется ввести еще команды которые будут: удалять в строке лишние буквы оставшиеся от более длиного слова и расширять строку для записи более длинного слова. Таким образом придется усложнить алгоритм работы всей программы и , соответственно , увеличить ее размеры и уменьшить быстродействие. Вместо всего этого можно предпринять следущее – в строке все слова “привести к одному размеру“ путем добавления к концу слов пробелов или других знаков препинания. Длина такого слова с добавленними пробелами должна быть равна длине максимального слова в строке. Соответственно к самому длинному слову ничего добавлять не надо. Этим самым мы добились:
Не надо писать новых команд расширения и удаления лишних символов
Не придется усложнять алгоритм обмена слов
Процесс обращения к элементам сортировки (словам) значительно облегчится , т.к. длина всех слов одинакова и тогда они отстоят друг от друга на некоторое постоянное число.
Приведение всех слов к одному размеру осуществляется макросом ToOneSize.
Алгоритм команды заключается в вычислении длины слова , определении его конца и сдвига вправо строки на определенное число равное (длина max слова-длина текущего слова) , этим мы приравниваем все слова к одному размеру. Перед выполнением этой команды мы удаляем из строки все знаки препинания и разделяем слова запятыми. Поэтому при сдвиге кажды предыдущий символ дублируется как символ запятой и нет опасности “появления нового ненужного слова”.
Сдвиг осуществляется макросом ShiftRight offset. Для которого указывается адрес начала сдвига. Далее вычисляется количество сдвигаемых байтов и , с помощью команды MOVSB , производится сдвиг на один байт вправо.
Для нахождения длины максимального слова разработан макрос FindMaxLen. Алгоритм его работы прост – он просматривает строку считая длину текущего слова и сравнивая её с длиной максимального слова , если длина текущего слова больше длины максимального , то длина текущего становится максимальной длиной. Далее максимальная длина записывается в регистр R0 и к нему прибавляется число 5. 5 – это число 3-х цифр и 2-х скобок для записи в конец каждого слова его длины.
Теперь приступим к разработке алгоритма сортировки. Далее нам понадобятся еще некоторые команды , однако они не так сложны и объемны , поэтому мы их рассмотрим по ходу разработки алгоритма.
При разработке будем использовать паскалевский эквивалент приведенный выше.
Для начала сортировки необходимо иметь указатели на сравниваемые слова и флаг устанавливающийся в 1 если мы за один проход совершили хотя бы один обмен , в противном случае все “пузырки всплыли” и сортировка закончена. В качестве указателей будут выступать переменные Р1 и Р2 (можно было бы использовать стандартные регистры , но для улучшения читабельности вводим 2-е переменные). В качестве флага вводим переменную Flag и устанавливаем ее в 1 чтобы не выйти из цикла до его просмотра. Устанавливаем переменную P1 на первое слово , а Р2 на второе (Р1+R0 т.к. в R0 длина максимального слова). Далее сравниваем слова и осуществляем либо обмен либо ищем дальше. Для продолжения сравнения необходимо сдвинуть указатели Р1 и Р2 на следущую пару слов , для этого присваиваем указателю Р1 значение Р2 , а к значению Р2 прибавляем R0. Важным является определение конца строки , т.к. Р2 приходит к концу строки раньше то проверяем не стоит ли Р2 на конце строки. Для этого удобно ввести макрос проверки конца строки TestEnd offset. Он осуществляет сравнение текущего элемента с признаком конца строки “$”. Если Р2 стоит на конце строки , то проверяем произвели ли за этот проход хотя бы один обмен , если да , то продолжаем “выталкивать очередной пузырёк” иначе сортировка закончена.
Рассмотрим еще несколько макросов необходимых для работы программы:
