- •ПЕРЕЧЕНЬ СОКРАЩЕНИЙ
- •ПРЕДИСЛОВИЕ
- •Регистр флагов
- •Программа вывода строки
- •Примеры резервирования памяти
- •Регистровая адресация
- •Непосредственная адресация
- •Прямая адресация
- •Косвенная регистровая адресация
- •Адресация по базе
- •Пример программы задержки выполнения
- •Сложение, вычитание, умножение, деление
- •Рис. 15.1. Структурная схема ввода данных с клавиатуры
- •Пример программы для ввода с клавиатуры
- •Пример посимвольного ввода
- •Сортировка выбором
- •Сортировка вставками
- •Использование параметров в макрокомандах
- •Библиографический список
- •Приложение 1
- •Перечень команд
- •Приложение 2
Приложение 1
ПЕРЕЧЕНЬ КОМАНД
•AAA: Коррекция ASCII-формата для сложения
•AAD: Коррекция ASCII-формата для деления
•AAМ: Коррекция ASCII-формата для умножения
•AAS: Коррекция ASCII-формата для вычитания
•ADC: Сложение с переносом
•ADD: Сложение двоичных чисел
•AND: Логическое И
•CALL: Вызов процедуры
•CBW: Преобразование байта в слово
•CLC: Сброс флага переноса
•CLD: Сброс флага направления
•CLI: Сброс флага прерывания
•CMC: Переключение флага переноса
•CMP: Сравнение
•CMPS/CMPSB/CMPSW: Сравнение строк
•CWD: Преобразование слова в двойное слово
•DAA: Десятичная коррекция для сложения
•DAS: Десятичная коррекция для вычитания
•DEC: Декремент
•DIV: Деление
•HLT: Останов микропроцессора
•IDIV: Целое деление знаковых величин
•IMUL: Целое умножение знаковых величин
•IN: Ввод байта или слова из порта
•INC: Инкремент
•INT: Прерывание
•INTO: Прерывание по переполнению
•IRET: Возврат из обработки прерывания
•JA/JNBE: Переход по «выше» или «не ниже или равно»
•JAE/JNB: Переход по «выше или равно» или «не ниже»
•JB/JNAE: Переход по «ниже» или «не выше или равно»
•JBE/JNA: Переход по «ниже или равно» или «не выше»
88
•JC: Переход по переносу
•JCXZ: Переход по «CX равно нулю»
•JE/JZ: Переход по «равно» или по «нулю»
•JG/JNLE: Переход по «больше» или «не меньше или равно»
•JGE/JNL: Переход по «больше или равно» или «не меньше»
•JL/JNGE: Переход по «меньше» или «не больше или равно»
•JLE/JNG: Переход по «меньше или равно» или «не больше»
•JMP: Безусловный переход
•JNC: Переход если нет переноса
•JNE/JNZ: Переход по «не равно» или по «не нуль»
•INO: Переход, если нет переполнения
•JNP/JPO: Переход, если нет паритета или паритет нечетный
•JHS: Переход, если нет знака
•JO: Переход по переполнению
•JP/JPE: Переход, если есть паритет или паритет четный
•JS: Переход по знаку
•LAHF: Загрузка флагов в регистр АН
•LDS: Загрузка регистра сегмента данных
•LES: Загрузка регистра дополнительного сегмента
•LODS/LODSB/LODSW: Загрузка однобайтовой или двухбайтовой строки
•LOOP: Цикл
•LOOPE/LOOPZ: Цикл, если равно или нуль
•LOOPNE/LOOPNZ: Цикл, если не равно или не нуль
•MOV: Пересылка данных
•MOVS/MOVSB/MOVSW: Пересылка строки байт или строки слов
•MUL: Беззнаковое умножение
•NEG: Изменение знака числа
•NOP: Нет операции
•NOT: Логическое НЕТ
•OR: Логическое ИЛИ
•OUT: Вывод байта или слова в порт
•POP: Извлечение слова из стека
•POPA: Извлечение из стека всех общих регистров (80188, 80186, 80286)
•POPF: Извлечение флагов из стека
89
•PUSH: Занесение слова в стек
•PUSHA: Занесение в стек всех общих регистров (80188, 80186,
80286)
•PUSHF: Занесение флагов в стек
•RCL и RCR: Циклический сдвиг влево через перенос и циклический сдвиг вправо через перенос
•REP/REPE/REPZ/REPNE/REPNZ: Повтор строковой операции
•RET: Возврат из процедуры
•ROL и ROR: Циклический сдвиг влево и циклический сдвиг вправо
•SAHF: Установка флагов из регистра АН
•SAL, SAR, SHL и SHR: Сдвиг влево или вправо
•SBB: Вычитание с заемом
•SCAS/SCASB/SCASW: Поиск байта или слова в строке
•STC: Установка флага переноса
•STD: Установка флага направления
•STI: Установка флага прерывания
•STOS/STOSB/STOSW: Запись однобайтовой или двухбайтовой строки
•SUB: Вычитание двоичных чисел
•TEST: Проверка битов
•WAIT: Установка процессора в состояние ожидания
•XCHG: Перестановка байт или слов
•XLAT: Перекодировка
•XOR: Исключающее ИЛИ
90
Приложение 2
РАСЧЕТ СЛОЖНОСТИ АЛГОРИТМА НА ПРИМЕРЕ ПЕРЕМЕШИВАНИЯ СЛУЧАЙНЫХ ЧИСЕЛ
Программистские задачи редко решаются единственным способом. Почти всегда есть много решений . Один из существенных критериев – скорость работы программы. Если для решения какой-то задачи программа выполняет меньше действий, чем другая программа, то она работает быстрее на любом компьютере.
Задача. Расположить некоторый набор элементов в случайном порядке. Предположим, что в нашем распоряжении имеется идеальный датчик случайных чисел.
Решение 1. Будем получать от датчика случайных чисел числа от 1 до N. Первое полученное число запишем, а каждое последующее будем по очереди сравнивать со всеми уже записанными. Если это число уже встречалось, то его надо выбросить, а если еще нет, то записать. Через некоторое время записанными окажутся числа от 1 до N в случайном порядке.
Главные действия
1.Обращение к датчику случайных чисел,
2.Сравнение нового числа с имеющимися (записанными). Алгоритм может работать сколь угодно долго, так как одно число
от 1 до N может вообще не выпасть. Подсчет количества действий в среднем
Определение количества (D) обращений к датчику:
D = d[0] +d[1] +... +d[N −1],
где D – количество обращений (общее); d[k] – количество обращений к датчику для получения следующего числа, когда k-чисел уже записано.
Найдем d[k]для произвольного k.
С вероятностью q = k
N при очередном обращении к датчику выпадает число, которое уже есть и с вероятностью p =1−q выпадает
новое число.
Тогда p – вероятность одного обращения к датчику; pq – вероятность двух обращений к датчику (1-е обращение неудачное, 2-е –
удачное), pq2 – вероятность трех обращений к датчику.
91
Среднее число обращений получим, умножив каждую из этих вероятностей на соответствующее ей число обращений и сложив все эти произведения.
d[k] =1p +2 pq +3pq2 +... =(т.к.p =1−q) =
=1−q +2(1−q)q +3(1−q)q2 +... =
=1−q +2q −2q2 +2q2 +3q2 −3q3 +... =
=1−q +q2 +q3 +... =1−1q = NN−k ,
учитывая, что |
q = |
k |
. |
|
|||
|
|
N |
|
Тогда общее количество обращений к датчику:
D = NN + NN−1 + NN−2 + NN−3 +... + N2 + N1 =
|
|
1 |
|
1 |
|
1 |
|
|
= N 1 |
+ |
2 |
+ |
3 |
+... + |
|
≈ N ln N , |
|
|
|
|||||||
|
|
|
|
N |
|
|||
так как сумма N членов |
гармонического ряда равна lnN |
+ С, |
||||||
где С = 0,5772. D(N) = N ln N , где N – количество элементов. |
|
|||||||
Определение количества (Т) сравнений: |
|
|||||||
T =t[0] +t[1] +... |
+t[N −1], |
(*) |
||||||
где T – общее количество сравнений, t[k] – количество сравнений при записи в список числа с номером k + 1.
Для записи числа с номером k + 1 необходимо d[k] обращений к датчику. После каждого обращения полученное число сравнивается с записанными. После получения нужного сравниваем его со всеми предыдущими, т. е. проводим k сравнений.
При первых ( d[k] −1) обращениях число сравнений может оказать-
ся с равной вероятностью любым от 1 до k , так как вновь полученное
число с равной вероятностью может совпадать с любым из уже записанных.
92
Среднее число сравнений при этом равно |
k +1 |
, тогда |
|
|||||||
|
|
|
||||||||
|
|
|
|
|
|
|
2 |
|
|
|
N |
k +1 |
|
k(k +1) |
|
k(2N −k +1) |
|
||||
t[k] = k + |
|
−1 |
|
= k + |
|
|
= |
|
|
. |
|
2 |
2N −k |
|
|
2(N −k) |
|||||
N −k |
|
|
|
|
|
|
||||
Если вместо количества уже записанных чисел k использовать количество оставшихся чисел m, где k +m = N, то для t[k] :
t[N −m] = |
(N −m)(N +m +1) |
= |
|
N 2 |
|
−m2 + N −m |
= |
|
N 2 + N |
− |
m +1 |
. |
|||||||||||||||||||||||||||||||||||
|
|
|
|
|
|
2m |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2m |
|
|
|
|
|
|
2m |
|
|
2 |
||||||||||||||||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
||||||||||
Подставим t[k] в выражение (*): |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
||||||||||||||||||||||||
|
T |
= |
|
N 2 + N |
|
− |
N +1 |
+ |
N 2 |
+ N |
|
|
− |
N |
+... + |
|
N |
2 + N |
− |
2 |
= |
|
|
|
|
||||||||||||||||||||||
|
|
|
|
|
2m |
|
2 |
|
|
|
2(N −1) |
|
2 |
|
|
|
|
2 |
|
2 |
|
|
|
|
|||||||||||||||||||||||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
||||||||||||||||||
|
|
|
|
|
|
|
N 2 |
+ N |
|
1 |
|
|
|
|
|
|
1 |
|
|
|
|
1 |
(2 +3 +... + N +1) = |
|
|
|
|
|
|||||||||||||||||||
|
|
|
= |
|
|
|
|
|
|
|
1+ |
|
+... + |
|
|
|
|
− |
|
|
|
|
|
|
|||||||||||||||||||||||
|
|
|
|
|
|
|
2 |
|
|
2 |
|
|
2 |
|
|
|
|
|
|||||||||||||||||||||||||||||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
N |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
||||||
|
N 2 |
+ N |
|
|
|
|
|
|
|
N(N +3) |
|
|
N 2 |
|
|
|
|
|
|
1 |
|
|
N |
|
|
|
|
3 |
|
|
|||||||||||||||||
= |
|
|
|
|
|
|
|
H (N) |
|
− |
|
|
|
|
|
|
|
= |
|
|
|
|
|
|
H (N) − |
|
+ |
|
|
|
H (N) − |
|
. |
|
|||||||||||||
|
2 |
|
|
|
|
|
|
|
|
4 |
|
|
|
|
|
2 |
|
|
2 |
|
2 |
2 |
|
||||||||||||||||||||||||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
||||||||||||
При больших N: |
T (N) ≈ |
N 2 ln N |
; |
|
|
T (N) =0(N 2 ln N) . |
|
|
|
|
|
|
|||||||||||||||||||||||||||||||||||
2
Итак, наше решение требует в худшем случае бесконечного количества действий, а в среднем:
N · lnN –обращений к датчику и порядка N · 2lnN сравнений.
N · 2 lnN – вычислительная сложность алгоритма.
Решение 2. Основное время при реализации решения 1 тратится на проверку следующие: «а не записано ли уже в последовательности полученное от датчика число». Попробуем сократить число проверок.
Заведем таблицу, в которой будем отмечать числа, которые уже есть в последовательности. В программе этой таблице будет соответствовать дополнительный массив из N элементов. В начальный момент таблица очищена, так как никаких чисел в последовательности нет.
93
Записывая в последовательность число i, мы отмечаем его использование в i-м элементе таблицы. Теперь каждое обращение к датчику потребует ровно одной проверки. Соответствующий элемент таблицы покажет, встречалось ли ранее полученное число. В остальном алгоритм такой же, как и в решении 1.
Количество обращений к датчику будет таким, как и в решении 1. Количество сравнений будет такое же, как количество обращений,
так как на каждое обращение приходится ровно одно сравнение.
N · lnN – вычислительная сложность алгоритма. Лучше чем в предыдущем случае, но это количество сравнений в среднем. В худшем случае оно бесконечно.
Решение 3. Предыдущие решения требовали большого числа обращений к датчику.
На каждое место в последовательности претендует на один элемент меньше, чем на предыдущее, а мы каждый раз запрашиваем у датчика один из N вариантов и вынуждены делать повторные обращения, если результат оказывается неподходящим.
Будем запрашивать у датчика числа от 1 до m, где m – количество незаполненных мест в последовательности.
При этом результат, полученный от датчика, будем рассматривать ни как число, которое следует записать, а как порядковый номер числа среди тех, которые еще не записаны.
Например, для N = 7 в начале последовательности записаны числа
3, 6 и 2.
Необходимо записать в последовательность еще четыре элемента, поэтому при очередном обращении к датчику мы запрашиваем числа от 1 до 4.
Предположим, что получилось 3. Это означает, что необходимо записать третье из неиспользованных чисел. Будем последовательно проверять все элементы таблицы, подсчитывая при этом пустые клетки. В третью пустую клетку поставим знак «+», а ее номер покажет очередное число в последовательности. У нас число 5.
Все обращения к датчику результативны, их количество всегда равно N или N – 1, так как при последнем обращении результат заранее известен. Но увеличилось количество сравнений, так как после каждого обращения к датчику необходимо пройти по таблице в поисках нужного элемента.
Количество сравнений после каждого обращения к датчику зависит и от результата этого обращения, и от результатов предыдущих обра-
94
щений. Тем не менее вычислить общее число сравнений при выполнении алгоритма можно. Каждый раз мы останавливаем проход по таблице на том элементе, номер которого заносим в последовательность. Поскольку все числа от 1 до N должны попасть в последовательность ровно по одному разу, мы будем выполнять один раз одно сравнение, один раз два сравнения, 1 раз три сравнения и т. д. Предсказать порядок невозможно, так как он случайный и совпадает с порядком элементов, полученных случайной перестановкой, но общее количество сравнений можно найти:
T =1+2 +3 +... + N = N(N2 +1) ,
T ≈0(N 2 ).
Таким образом, алгоритм в решении 3 имеет вычислительную сложность N2, т. е. алгоритм квадратичный. N2>N · lnN при больших N, т. е. третий алгоритм медленнее второго, но для третьего алгоритма найденное нами количество действий постоянно, а у второго достигается только в среднем, а в худшем случае может быть сколь угодно большим. На практике это означает, что второй алгоритм быстрее, но в отдельных случаях он может работать очень долго. Третий алгоритм в среднем медленнее, но зато гарантированно завершается в фиксированное время.
Подобная ситуация типична: одно решение оказалось лучше в среднем, другое в худшем случае. Какой вариант выбрать, зависит от того, где используется программа; в случае, если необходимо многократно выполнять какие-то расчёты, важна бывает средняя скорость, и не страшно, если какой-то единичный расчёт займёт много времени. Для программ, которые должны работать в экстренных ситуациях, важна скорость, в худшем случае необходимо гарантировать, что результат будет получен вовремя.
Решение 4. В решении 3 время уходило на поиск нужного элемента в таблице. Сделаем так, чтобы результат, полученный от датчика, сразу показывал номер этого элемента. Для этого будем заносить в таблицу не плюсики, а сами числа. В начальный момент в таблице находятся все числа от 1 до N. Когда очередное число заносится в выходную последовательность, будем сдвигать элементы таблицы так, чтобы все неиспользованные значения группировались в ее начале.
95
Пусть N = 7, в начале последовательности записаны числа 3, 6 и 2. Если теперь при обращении к датчику будет получено число 2, в выходную последовательность попадает 2-й элемент, т. е. число 4, а в
таблице произойдёт очередной сдвиг.
Количество обращений к датчику равно N – 1, никаких сравнений нет, но появились сдвиги.
Количество сдвигаемых элементов на каждом шаге может быть различным – от 0 (если выпал последний из оставшихся элементов) до числа m (если выпал 1-й элемент).
Поскольку все элементы выпадают с равной вероятностью, то сред-
нее число сдвигов будет |
m , а в ходе работы m изменяется от N до 2. |
|||||||
|
|
|
2 |
|
|
|
|
|
Общее количество сдвигов будет: |
|
|
|
|
||||
V = |
N |
+ |
N −1 |
+... + |
2 |
= |
(N −1)(N +2) |
, |
2 |
|
2 |
|
2 |
|
4 |
|
|
V ≈0(N 2 ).
Получился алгоритм сложности N 2, мы ничего не выиграли. Лишь коэффициент при N2 стал меньше. Но N 2 – это количество сдвигов, а не сравнений, и много будет зависеть от того, как реализованы операции сдвига и сколько времени занимает каждая из них.
Решение 5. Попробуем избавиться от сдвигов. Сдвиги нужны только для того, чтобы избавиться от пустых мест в таблице, а сохранять порядок элементов при этом не обязательно. Поскольку все числа при построении перестановки равноправны, они могут располагаться в таблице в любом порядке. Важно, чтобы они могли быть выбраны с одинаковой вероятностью.
Поэтому вместо сдвига можно просто переносить на освободившееся место в таблице ее последний (текущий) элемент.
Теперь на каждое из N – 1 обращений к датчику приходится единственный перенос элемента. Вычислительная сложность алгоритма N (линейный алгоритм).
Дальнейшее снижение сложности невозможно, так как получить последовательность из N элементов меньше, чем за N действий нельзя.
Решение 6. Кроме времени можно проанализировать память.
Для реализации последнего решения требуется 2N элементов памяти: для полученной перестановки и для вспомогательной таблицы.
96
Можно обойтись только количеством N элементов. В последнем решении мы выводим элемент из таблицы в итоговую последовательность и одновременно переносим в освободившееся место последний элемент, а последнее место в таблице не используем. Будем помещать на это последнее место тот элемент, который мы выбрали для включения в перестановку. Тем самым всё сводится к перестановке последнего элемента со случайно выбранным. А сама случайная перестановка будет формироваться с конца таблицы.
97
|
ОГЛАВЛЕНИЕ |
|
Перечень сокращений.................................................................................. |
3 |
|
Предисловие................................................................................................. |
4 |
|
1. |
Архитектура микропроцессора i8086..................................................... |
5 |
|
Регистр флагов......................................................................................... |
7 |
2. |
Структура и образ памяти программы типа .EXE и .COM.................. |
9 |
|
2.1. Структура программы типа . EXE................................................... |
9 |
|
2.2. Структура и образ памяти программы типа .COM...................... |
11 |
3. |
Процесс подготовки программы на Ассемблере ................................ |
13 |
4. |
Описание данных................................................................................... |
15 |
|
Примеры резервирования памяти........................................................ |
19 |
5. |
Система команд, режимы адресации.................................................... |
20 |
6. |
Циклы...................................................................................................... |
27 |
7. |
Обработка строк байтов и слов............................................................. |
29 |
|
7.1. Пересылка и сравнение строк........................................................ |
31 |
|
7.2. Поиск в строке, загрузка регистра из строки, запись в строку |
|
|
из регистра....................................................................................... |
32 |
8. |
Переходы................................................................................................. |
33 |
|
8.1. Прямой короткий (short) переход.................................................. |
34 |
|
8.2. Прямой ближний (near), или внутрисегментный переход.......... |
35 |
|
8.3. Прямой дальний (far), или межсегментный переход................... |
35 |
|
8.4. Косвенный ближний (внутрисегментный) переход..................... |
36 |
|
8.5. Косвенный дальний (межсегментный) переход........................... |
39 |
|
8.6. Условный переход .......................................................................... |
41 |
|
98 |
|
9. Вызовы процедур................................................................................... |
43 |
|
9.1. Прямой ближний вызов.................................................................. |
45 |
|
9.2. Косвенный ближний вызов............................................................ |
46 |
|
9.3. Прямой дальний вызов................................................................... |
46 |
|
9.4. Косвенный дальний вызов............................................................. |
47 |
|
10. |
Основные команды пересылки, обмена, ввода-вывода.................... |
47 |
11. |
Основные арифметические команды................................................. |
49 |
|
Многословное сложение..................................................................... |
52 |
12. |
ASCII-формат....................................................................................... |
55 |
12.1. Сложение в ASCII-формате......................................................... |
55 |
|
12.2. Преобразование ASCII-формата в двоичный формат............... |
57 |
|
12.3. Преобразование двоичного формата в ASCII-формат .............. |
60 |
|
13. |
Команды логических операций: AND, OR, XOR, TEST, NOT ........ |
61 |
14. |
Работа с файлом................................................................................... |
62 |
14.1. Уровни обращения к дискам, основные понятия: блок |
|
|
|
управления файлом, дескриптор файла, блок описания файла... |
62 |
14.2. Функции DOS. Создание, открытие и закрытие файла............. |
63 |
|
14.3. Функции DOS. Чтение и запись данных, изменение |
|
|
|
характеристик файла..................................................................... |
66 |
15. |
Ввод информации с клавиатуры по прерываниям DOS и BIOS...... |
69 |
15.1. Ввод с клавиатуры средствами файловой системы................... |
69 |
|
15.2. Использование группы функций DOS посимвольного ввода |
|
|
|
с клавиатуры................................................................................... |
72 |
15.3. Работа с клавиатурой на уровне BIOS ........................................ |
73 |
|
16. |
Вывод информации на экран по прерываниям DOS и BIOS. |
|
Управление экраном с помощью ESC-последовательности.................. |
74 |
|
Управление экраном через ESC-последовательности........................ |
75 |
|
17. |
Сортировка одномерных массивов выбором, обменом, |
|
|
вставками............................................................................................. |
76 |
18. |
Команды сдвига и циклического сдвига............................................ |
79 |
|
99 |
|
19. Макросредства...................................................................................... |
81 |
|
Использование параметров в макрокомандах..................................... |
82 |
|
Библиографический список ..................................................................... |
85 |
|
Приложение 1. |
Перечень команд.............................................................. |
87 |
Приложение 2. |
Расчет сложности алгоритма на примере |
|
|
перемешивания случайных чисел.................................. |
90 |
100
