Пильщиков В.Н. - Упражнения по языку ассемблера MASM (1110572), страница 5
Текст из файла (страница 5)
где <адрес> - это адрес (смещение) переменной в виде четырехзначного 16-ричного числа, а <содержимое> - значение переменной в виде двузначного 16-ричного числа (например: 01A8:F5).
При решении этой задачи описать и использовать следующие процедуры:
- вывод числа от 0 до 15 в 16-ричном виде;
- вывод байта в виде двух 16-ричных цифр;
- вывод строки указанного вида для одной переменной.
7.21 Описать программу, которая в цикле вводит приказы указанных ниже типов и тут же выполняет их. (Считать, что приказы задаются без ошибок.)
Возможные приказы:
S seg:ofs. - напечатать в 16-ричном виде (4 цифры) слово памяти, абсолютный адрес которого определяется парой seg:ofs (сегмент : смещение);
L seg:ofs=w. - в слово памяти, абсолютный адрес которого задан парой seg:ofs, записать новое значение w;
E. - завершить работу программы.
Здесь seg, ofs и w - 16-ричные числа (от 1 до 4 цифр), в которых "буквенные" цифры записываются большими латинскими буквами от A до F.
7.22 Описать программу, которая вводит два массива из 100 знаковых чисел-слов в каждом и определяет, составлены ли эти массивы из одних и тех же чисел (без учета порядка их следования, но с учетом повторяющихся чисел). (Рекомендация: упорядочить оба массива, а затем сравнить их.)
7.23 Описать близкую рекурсивную процедуру C, вычисляющую биномиальный коэффициент C(m,n), где 0mn, по следующей формуле:
1 при m=0 или m=n
C(m,n) =
C(m,n-1)+C(m-1,n-1) при 0<m<n
Параметры n и m передаются процедуре через регистры AH и AL соответственно, а свой ответ она возвращает через регистр BX.
7.24 Для ввода задана последовательность символов (отличных от точки), за которой следует точка. Описать дальнюю рекурсивную процедуру REVERSE без параметров, которая вводит эти символы и выводит их (без точки) в обратном порядке.
7.25 Для ввода задана последовательность ненулевых чисел, за которой следует 0. Описать близкую рекурсивную процедуру PR без параметров, которая вводит эти числа и выводит сначала всех отрицательные числа, а затем - все положительные (в любом порядке).
7.26 Описать близкую рекурсивную процедуру BITS1, которая подсчитывает количество двоичных единиц в значении регистра AX и возвращает ответ через регистр BL.
7.27 Для ввода задана последовательность символов, представляющая собой правильную запись формулы следующего вида:
<формула> ::= <цифра> | M(<формула>,<формула>) |
m(<формула>,<формула>)
<цифра> ::= 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9
(M трактуется как максимум (max), а m - как минимум (min)). Описать близкую рекурсивную процедуру MM без параметров, которая вводит эту формулу, вычисляет ее значение (как число) и присваивает его регистру AL.
7.28 Описать программу, которая вводит текст вида
<формула> = <формула>
где
<формула> ::= <цифра> | (<формула> <знак> <формула>)
<знак> ::= + | -
<цифра> ::= 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9
и которая определяет, равны ли значения двух указанных формул. Ответ: ДА или НЕТ.
В программе описать и использовать рекурсивную процедуру, которая вводит и вычисляет значение одной формулы.
7.29 Описать близкую рекурсивную процедуру FORM без параметров, которая вводит текст из любых символов (кроме точки), за которым (обязательно) следует точка, и проверяет, удовлетворяет ли этот текст следующему определению:
<текст> ::= <пусто> | <элемент> <текст>
<пусто> ::=
<элемент> ::= <буква> | (<текст>) | [<текст>] | {<текст>}
<буква> ::= A | B
8. ДИНАМИЧЕСКИЕ СТРУКТУРЫ ДАННЫХ.
8.1 Используя, если надо, регистр AX как вспомогательный и считая, что флаг направления DF равен 0, описать через другие (не строковые) команды действие команды:
а) MOVSB б) CMPSB в) SCASB г) LODSB д) STOSB е) REP MOVSB
8.2 S DB 'abcde',0
T DB 'abxyz'
Считая, что строки S и T описаны в сегменте данных и что регистры DS и ES уже установлены на начало этого сегмента, определить значения регистров CX и BL и флага ZF после выполнения следующей группы команд:
а) CLD б) STD в) CLD г) CLD
LEA SI,S LEA SI,S+4 LEA DI,S LEA DI,S
LEA DI,T LEA DI,T+4 MOV CX,5 MOV CX,5
MOV CX,5 MOV CX,5 MOV AL,'e' MOV AL,'f'
REPE CMPSB REPNE CMPSB REPNE SCASB REPNE SCASB
MOV BL,[SI] MOV BL,[SI] MOV BL,ES:[DI] MOV BL,ES:[DI]
8.3 S DB 100 DUP(?) ; S[0..99] of char
T DB 100 DUP(?) ; T[0..99] of char
Рассматривая S и T как символьные строки фиксированной длины, описанные в сегменте данных, на начало которого уже установлены регистры DS и ES, и используя строковые команды, выписать фрагмент программы для решения следующей задачи.
а) Определить, со скольких пробелов начинается строка S, и записать ответ в регистр CL.
б) Определить, сколькими пробелами заканчивается строка S, и записать ответ в регистр CL.
в) Найти индекс (от 0 до 99) первого вхождения буквы 'Q' в строку S и записать ответ в регистр DI; если эта буква не входит в S, то в DI записать -1.
г) Заменить в строке S последнее вхождение буквы 'n' на букву 'N'.
д) Записать в регистр BH число вхождений символа '*' в строку S.
е) Определить, равны ли левая и правая половины строки S, и записать ответ 1 (равны) или 0 в регистр AL.
ж) Определить, входят ли первые 5 символов строки T в строку S как подстрока, и записать ответ 1 (входят) или 0 в регистр AL.
з) Заменить последние 10 символов строки S на 10 первых символов строки T.
и) Циклически сдвинуть элементы строки S на две позиции влево.
к) Если первая и вторая четверти строки S не равны, то заменить третью четверть на последнюю.
л) Переписать содержимое строки T в строку S с заменой всех пробелов на символ '*'.
м) В строке S заменить все пробелы на символ '*'.
н) В строке S заменить все большие латинские буквы на соответствующие малые.
о) Удалить из строки S все цифры, сдвинув к ее началу все остальные символы и дописав пробелы в ее конец.
8.4 Считая, что в программе на сегмент стека отведено 1000 байтов, и используя строковые команды, выписать фрагмент программы для решения следующей задачи: если в стеке нет ни одного нулевого байта, тогда переписать содержимое стека в область памяти, начинающейся с абсолютного адреса 12345h.
8.5 Не делая никаких предположений о кодировке букв русского алфавита и используя команду SCASB, описать близкую процедуру LOWRUS, которой через регистр AL передается некоторый символ и которая, если это большая русская буква, заменяет ее (в AL) на соответствующую малую русскую букву (иные символы не менять). Все данные, необходимые процедуре, описать в самой процедуре.
8.6 S DB 256 DUP(?) ; длина(S)255
T DB 101 DUP(?) ; длина(T)100
Рассматривая S и T как символьные строки переменной длины (с текущей длиной в начальном байте), размещенные в одном сегменте памяти, на начало которого уже установлены регистры DS и ES, и используя строковые команды, выписать фрагмент программы для решения следующей задачи.
а) В строке S оставить только первые 10 символов (не более).
б) Сделать значением S строку из 50 пробелов.
в) В строке S заменить все большие латинские буквы на соответствующие малые.
г) Удалить все пробелы в конце строки S.
д) Удалить все пробелы в начале строки S.
е) Если в строке S от 10 до 40 символов, то продублировать 10-й символ.
ж) Удалить из строки S все пробелы.
з) В конец строки S дописать символы строки T, отбросив при этом лишние (256-й и последующие) символы, если такие окажутся.
и) Сравнить строки S и T и записать ответ 1 (S>T), 0 (S=T) или -1 (S<T) в регистр AL.
к) Определить, является ли строка T подстрокой строки S, и записать ответ 1 (является) или 0 в регистр AL.
л) Удалить из строки S все вхождения подстроки T.
8.7 Описать указанные ниже процедуры при следующих условиях:
- все используемые строки - это строки переменной длины (с текущей длиной в начальном байте), их максимальная длина - 255, нумерация их символов начинается с 1;
- все параметры передаются через стек, причем порядок их записи в стек - слева направо;
- числовые параметры положительны и имеют размер слова;
- параметр-строка задается своим абсолютным начальным адресом в виде пары "сегмент : смещение" ("сегмент" записывается в стек первым).
Процедуры (len(S) означает текущую длину строки S):
а) copy(R,S,i,n) - в строку R переписываются n символов строки S начиная с i-го (старое значение R уничтожается); если i>len(S), то строка R становится пустой; при i+n-1>len(S) копируются все символы до конца S;
б) delete(S,i,n) - из строки S удаляются n символов начиная с i-го; при i>len(S) строка S не меняется; при i+n-1>len(S) удаляются все символы до конца S;
в) insert(SS,S,i) - строка SS вставляется в строку S между (i-1)-м и i-м символами; если i>len(S), то SS добавляется в конец S; если длина строки-результата больше 255, то все лишние (256-й и последующие) символы отбрасываются;
г) pos(SS,S) - это функция, которая определяет, входит ли строка SS в строку S как подстрока, и возвращает (через регистр AL) как свое значение номер той позиции строки S, с которой начинается первое вхождение SS в S; если SS не входит в S, тогда значение функции равно 0.
8.8 L DW ?
L1 DW ?
X DW 100 DUP(?)
Считая, что уже описаны константа NIL, тип NODE и процедуры NEW и DISPOSE, что регистр ES уже установлен на начало сегмента кучи и что значения L и L1 трактуются как ссылки на списки (возможно, пустые) из знаковых чисел-слов, выписать фрагмент программы для решения следующей задачи.
а) Определить число положительных элементов в списке L и записать это число в регистр AX.
б) Обнулить все отрицательные элементы списка L.
в) Если в списке L не менее двух элементов, то изменить знак у его предпоследнего элемента. (Рекомендация: хранить в двух модификаторах, например BX и SI, адреса текущего и предыдущего звеньев списка.)
г) Сравнить массив X и список L (равны ли последовательности их элементов?) и записать ответ 1 (равны) или 0 в регистр AL.
д) Сравнить списки L и L1 и записать ответ 1 (равны) или 0 в регистр AL.
е) Определить, есть ли в списке L равные элементы, и записать ответ 1 (есть) или 0 в регистр AL.
ж) По массиву X построить список L - из тех же элементов и в том же порядке. (Рекомендация: список строить от конца.)
з) Ввести непустую последовательность ненулевых чисел, за которой следует 0, и напечатать эти числа в обратном порядке.
и) Создать L1 - копию списка L.
к) В список L вставить нулевой элемент после первого отрицательного элемента, если такой есть.
л) В список L вставить нулевой элемент перед первым отрицательным элементом, если такой есть.
м) В списке L продублировать каждый положительный элемент.
н) Вставить между первым и вторым элементами непустого списка L копии всех элементов списка L1.
о) Удалить из непустого списка L его последний элемент.
п) Удалить из списка L первый нулевой элемент, если такой есть.
р) Перенести первый элемент непустого списка L в конец списка.
с) Перенести последний элемент непустого списка L в начало списка.
т) Удалить из списка L все его отрицательные элементы.
у) Уничтожить список L, освободив место, занимаемое его звеньями, и присвоить переменной L значение NIL.
ф) Удалить из списка L все элементы, которые входят в список L1.
8.9 Описать близкую рекурсивную процедуру, параметр (ссылка на список) для которой передается через регистр BX и которая возвращает ответ через регистр AX, для решения следующей задачи.
а) Найти последний элемент непустого списка.
б) Найти длину (число элементов) заданного списка.
в) Определить, входит ли заданное (в регистре AX) число в заданный список (ответ: 1 (входит) или 0).
г) Найти число отрицательных элементов в заданном списке.
д) Определить, есть ли в заданном списке хотя бы один отрицательный элемент (ответ: 1 (есть) или 0).
е) Найти максимальный элемент непустого заданного списка.