# Лабораторная работа №3 ## Строковые операции в MASM32 **Дисциплина:** Основы вычислительной техники и операционные системы автоматизированных технологических комплексов (Б1.В.01) **Направление:** 15.03.06 «Мехатроника и робототехника» **Семестр:** 3 · **Объём:** 4 часа аудиторных + самостоятельная работа **Среда:** MASM32 (редактор QEditor / сборка `ml` + `link`), отладчик OllyDbg --- ## 1. Цель работы Получение навыков программирования на языке Assembler для Win32, в частности освоение команд работы со строками (цепочечных команд) и их практического применения в операциях поиска, копирования, изменения данных. **Задачи:** - освоить цепочечные команды `MOVS`, `LODS`, `STOS`, `SCAS`, `CMPS` и префиксы повторения `REP`/`REPE`/`REPNE`; - научиться создавать GUI-приложение Win32 на MASM32 (главное окно, поле ввода, кнопка, обработка сообщений); - реализовать индивидуальный вариант обработки строки с вводом и выводом в диалоговом окне Windows; - провести вычислительный эксперимент и убедиться в правильности результата. --- ## 2. Задание Разработать алгоритм и программу на языке Assembler для Win32 в соответствии с **индивидуальным заданием** (см. раздел 5, вариант выдаёт преподаватель). Ввод и вывод осуществить **в диалоговом окне Windows**. Работа состоит из пяти частей. ### Задание 1. Окно Windows: ввод и вывод — 2 балла Создать GUI-приложение Win32 на MASM32: 1. Стандартная «шапка» программы: `.386`, `.model flat, stdcall`, `option casemap:none`, подключение `windows.inc`, `user32.inc`, `kernel32.inc` и соответствующих `.lib`. 2. В `WinMain`: заполнить структуру `WNDCLASSEX`, зарегистрировать класс (`RegisterClassEx`), создать окно (`CreateWindowEx`), показать его (`ShowWindow`) и запустить цикл сообщений (`GetMessage` / `TranslateMessage` / `DispatchMessage`). 3. В оконной функции `WndProc` обработать: - `WM_DESTROY` — выход из программы (`PostQuitMessage`); - `WM_CREATE` — создать **поле ввода** (класс `edit`) и **кнопку** (класс `button`) с уникальными ID. 4. Обработать `WM_COMMAND`: получить строку из поля ввода (`GetWindowText` в буфер) и вывести результат обработки обратно в поле (`SetWindowText`) или в `MessageBox`. > Подробное описание создания окна, регистрации класса, структуры > `WNDCLASSEX`, создания дочерних элементов `edit`/`button`, разбора > `WM_COMMAND` и функций `GetWindowText`/`SetWindowText` — в > дополнительном материале **«Программирование на Ассемблере в Win32»** > (файл `Окна в MASM32.PDF`, разделы 9, 10, 14). **Проверка:** программа собирается и запускается; окно содержит поле ввода и кнопку; закрытие окна завершает процесс. ### Задание 2. Алгоритм варианта — 2 балла По номеру варианта (раздел 5) разработать алгоритм: - определить тип обработки: одну строку, числа в тексте, слова или две строки; - выбрать направление просмотра (`CLD`) и регистры: `ESI` — источник, `EDI` — приёмник результата, `ECX` — счётчик; - указать, какие цепочечные команды применяются на каждом шаге и как меняются `EDI`/`ESI`/`ECX`; - предусмотреть крайний случай (пустая строка / конец данных). Оформить блок-схему или пошаговое описание алгоритма. **Проверка:** алгоритм соответствует варианту; указаны начальные регистры и результат. ### Задание 3. Программа — 2 балла Реализовать алгоритм на MASM32. **Обязательно** использовать цепочечные команды и префикс повторения: | Команда | Назначение | |---------|------------| | `MOVS` (`MOVSB`/`MOVSW`/`MOVSD`) | копирование элемента цепочки `ES:[EDI] ← DS:[ESI]` | | `LODS` | загрузка элемента цепочки в `AL`/`AX`/`EAX` | | `STOS` | запись элемента из аккумулятора в `ES:[EDI]` | | `SCAS` | сравнение элемента цепочки с аккумулятором (поиск) | | `CMPS` | сравнение двух элементов цепочек `DS:[ESI]` и `ES:[EDI]` | Префиксы: `REP` — повторять, пока `ECX ≠ 0`; `REPE`/`REPZ` — повторять, пока `ECX ≠ 0` **и** `ZF = 1`; `REPNE`/`REPNZ` — пока `ECX ≠ 0` **и** `ZF = 0`. Направление просмотра задаётся флагом `DF`: `CLD` (DF = 0, вперёд) или `STD` (DF = 1, назад). > **Числовые варианты (12–16, 23–24):** числа в тексте нужно разбирать > посимвольно — выполняйте `SCASB`/`LODSB`, выделяйте цифры (ASCII > `'0'`..`'9'`), накапливайте цифры в число и анализируйте его. **Проверка:** программа собирается и выдаёт правильный результат; использованы минимум две цепочечные команды и префикс `REP*`. ### Задание 4. Вычислительный эксперимент и отладка — 1,5 балла 1. Прогнать программу на 3–5 контрольных строках: | № | Контрольная строка | Назначение | |---|--------------------|------------| | 1 | пустая строка | проверка краевого случая | | 2 | строка из одних пробелов | проверка обработки пробелов | | 3 | строка с цифрами | вариант числового задания | | 4 | строка со смешанным регистром | проверка ASCII | | 5 | строка длиной около длины буфера | защита от переполнения | 2. Сверить результат, посчитанный вручную. 3. При расхождении — пройти ключевой фрагмент **пошагово** (OllyDbg или встроенный отладчик) и зафиксировать в отчёте состояние `EDI`/`ESI`/`ECX` и флагов `ZF`/`DF` после выполнения ключевой команды. **Проверка:** результаты совпадают с ручным расчётом; в отчёте приведены значения регистров/флагов; пустая строка и строка пробелов не приводят к сбою. ### Задание 5. Отчёт — 0,5 балла Оформить отчёт по структуре из методических указаний: Титульный лист. Задание на лабораторную работу. Введение. 1. Разработка алгоритма. 2. Разработка программы (листинг с комментариями). 3. Вычислительный эксперимент (контрольные строки, результаты, отладочная трассировка). Выводы. Список литературы. --- ## 3. Краткая теория ### 3.1. Цепочечные команды Цепочечные команды (команды обработки строк символов) выполняют действия над блоками памяти — последовательностями элементов размером в байт (8 бит), слово (16 бит) или двойное слово (32 бита). - **`MOVS dest,src`** — передаёт байт/слово/двойное слово из цепочки, адресуемой `DS:[ESI]`, в цепочку `ES:[EDI]`. `EDI` и `ESI` автоматически корректируются согласно флагу `DF`. Разновидности: `MOVSB` (байт), `MOVSW` (слово), `MOVSD` (двойное слово). - **`LODS src`** — загружает элемент цепочки в аккумулятор: байт → `AL`, слово → `AX`, двойное слово → `EAX`; `ESI` корректируется. Префикс `REP` не используется. - **`STOS dest`** — команда, обратная `LODS`: передаёт элемент из аккумулятора в цепочку и корректирует `EDI`. - **`SCAS dest`** — сканирование цепочки: вычитает элемент цепочки из аккумулятора (`AL`/`AX`/`EAX`) и модифицирует флаги. С префиксом `REPNE` позволяет найти в цепочке нужный элемент. - **`CMPS dest,src`** — сравнение цепочек: вычитает элемент цепочки `dest` из соответствующего элемента `src`, модифицирует флаги; `EDI` и `ESI` продвигаются к следующему элементу. **Префикс `REP`** повторяет строковую операцию до обнуления `ECX`. Разновидности: `REPZ` (`REPE`) — выполнять, пока `ZF = 1` (или пока `ECX ≠ 0`); `REPNZ` (`REPNE`) — выполнять, пока `ZF = 0`. Цепочечная команда без префикса выполняется один раз. В Win32 программа пишется в одном большом («плоском») сегменте, поэтому заботиться о сегментных регистрах `DS` и `ES` не нужно. Флаг `DF` сбрасывается командой `CLD` и устанавливается `STD`. ### 3.2. Примеры типовых алгоритмов **Пример 1. Копирование `STR1` в `STR2`:** ```asm CLD MOV ECX, N ; длина строки LEA ESI, STR1 LEA EDI, STR2 REP MOVSB ``` **Пример 2. Сравнение двух строк:** ```asm CLD MOV ECX, N ; длина сравниваемых строк LEA ESI, STR1 LEA EDI, STR2 REPE CMPSB JNE NO_SAME ; ... строки равны ``` **Пример 3. Заполнение строки символом:** ```asm CLD MOV AL, 65 ; код символа MOV ECX, 10 ; число символов LEA EDI, STR2 REP STOSB ``` **Пример 4. Поиск в строке знаков '$' и замена их на '_':** ```asm CLD MOV AL, '$' LEA EDI, STR2 MOV ECX, 20 LO: REPNE SCASB ; поиск JNZ DONE MOV BYTE PTR [EDI-1], '_' ; замена JMP LO DONE: ``` **Пример 5. Поиск подстроки `STR1` (длина `N1`) в строке `STR2` (длина `N2`), при `N2 > N1`:** ```asm CLD LEA EDI, STR2 MOV EAX, 0 MOV EDX, EDI ; EDX — адрес начала очередной попытки LO: MOV ECX, N1 LEA ESI, STR1 REPE CMPSB JE FOUND INC EDX INC EAX CMP EAX, N2-N1-1 JZ NO_FOUND MOV EDI, EDX JMP LO NO_FOUND: ; ... строка не найдена FOUND: ; ... строка найдена (начало — в EDX) ``` > Разбирая Пример 5, обратите внимание на роль регистра `EDX`: > в нём хранится адрес символа в `STR2`, с которого начинается > очередная попытка. При успехе именно в `EDX` находится начало > найденной подстроки. ### 3.3. Окна, элементы управления и ввод строки Чтобы создать окно в Win32, нужно: 1. получить дескриптор программы (`GetModuleHandle`); 2. зарегистрировать класс окна (`RegisterClassEx`), если не используется предопределённый класс; 3. создать окно (`CreateWindowEx`); 4. показать окно (`ShowWindow`) и обновить его (`UpdateWindow`); 5. запустить цикл сообщений (`GetMessage`/`DispatchMessage`); 6. обрабатывать сообщения в оконной функции (`WndProc`). Дочерние элементы управления (`button`, `edit`, список, флажок и т. д.) создаются функцией `CreateWindowEx` с указанием предопределённого класса и **дескриптора родителя** и **уникального ID**. Делается это обычно в обработке `WM_CREATE`. Созданный элемент посылает родителю сообщения `WM_COMMAND`: младшее слово `wParam` — ID элемента, старшее — код уведомления (для кнопки — `BN_CLICKED`), `lParam` — дескриптор элемента. Для сообщений **меню** `lParam == 0`. Работа со строкой ввода: ```asm SetWindowText proto hWnd:HWND, Str:PChar GetWindowText proto hWnd:HWND, Str:PChar, MaxCount:DWORD ``` - `SetWindowText hwndEdit, ADDR TestString` — заполнить поле; - `GetWindowText hwndEdit, ADDR buffer, 512` — прочитать текст (в `EAX` возвращается число скопированных символов). Родитель может слать команды элементу функцией `SendMessage`, например эмулировать нажатие кнопки из пункта меню: `invoke SendMessage, hWnd, WM_COMMAND, IDM_GETTEXT, 0`. > Полный разбор (структура `WNDCLASSEX`, параметры `CreateWindowEx`, > стили `WS_*`/`ES_*`/`BS_*`, примеры программ `PR2.ASM`, `PR8.ASM`) > — в файле `Окна в MASM32.PDF`, разделы 9, 10, 14. --- ## 4. Содержание отчёта **Титульный лист.** **Задание на лабораторную работу** (номер варианта и его формулировка). **Введение** (цель, краткие теоретические сведения). 1. **Разработка алгоритма** (блок-схема / пошаговое описание, распределение регистров). 2. **Разработка программы** (листинг с комментариями; пояснения по использованным цепочечным командам). 3. **Вычислительный эксперимент** (контрольные строки, ожидаемый и полученный результат, фрагменты окна с введенной строкой и полученным в результате работы программы результатом). **Выводы** (что подтвердилось, какие трудности, где применяются цепочечные команды). **Список литературы.** --- ## 5. Варианты индивидуальных заданий (Приложение А) Номер варианта выдаёт преподаватель. ### I. В диалоговом окне ввести строку, выполнить преобразование, вывести результат 1. Циклический сдвиг вправо на 1 символ. 2. Циклический сдвиг влево на 1 символ. 3. Выделить байт с наибольшим ASCII-кодом. 4. Выделить байт с наименьшим ASCII-кодом. 5. Произвести реверс байтов. 6. Поменять крайние символы местами. 7. Поменять средние символы местами. 8. Заменить чётные цифры символом `?`. 9. Заменить нечётные цифры символом `?`. 10. Убрать пробелы в тексте. 11. Заменить все символы `a` на символ, введённый с клавиатуры. ### II. В тексте определить количество чисел, у которых 12. Все цифры не совпадают. 13. Цифры образуют комбинацию «стрит» (напр.: 43576). 14. Три одинаковых цифры в числе (напр.: 36533). 15. Все цифры идут подряд (по возрастанию или убыванию). 16. Ни одной цифры подряд. ### III. В тексте найти 17. Количество гласных букв. 18. Количество согласных букв. 19. Количество слов с удвоенными согласными. 20. Количество слов с удвоенными гласными. 21. «Слова-перевёртыши» (напр.: кабак). 22. Слово с максимальным количеством одинаковых символов. 23. Количество чётных чисел. 24. Количество нечётных чисел. ### IV. Ввести 2 строки одинаковой длины, определить 25. Количество одинаковых символов. 26. Количество одинаковых слов. 27. Количество ошибок, если 1-я строка — шаблон, 2-я — проверяемый текст. --- ## 6. Контрольные вопросы (допуск и защита) 1. Что такое цепочечная команда? Чем «цепочка» отличается от «строки символов»? 2. Какую роль играют регистры `ESI`, `EDI`, `ECX` при выполнении цепочечных команд? 3. Что делает команда `CLD` и как флаг `DF` влияет на изменение `ESI`/`EDI`? 4. Чем отличаются префиксы `REP`, `REPE` (`REPZ`) и `REPNE` (`REPNZ`)? 5. Приведите определение команд `MOVS`, `LODS`, `STOS`, `SCAS`, `CMPS`. 6. Как в программе получить введённую пользователем строку? Где хранится её длина? 7. Как различаются сообщения меню и элементов управления в `WM_COMMAND`? Что хранится в `wParam` при `BN_CLICKED`? 8. Зачем при создании окна Win32 регистрировать класс окна перед вызовом `CreateWindowEx`? 9. Что произойдёт, если не обработать `WM_DESTROY`? 10. В Примере 5 (поиск подстроки) зачем нужен регистр `EDX` и почему после неудачного прохода `EDI` восстанавливается из `EDX`? --- ## 7. Оценивание | Составляющая | Вес | |--------------|-----| | Задание 1 (окно: ввод/вывод) | 2,0 | | Задание 2 (алгоритм варианта) | 2,0 | | Задание 3 (программа: цепочечные команды) | 2,0 | | Задание 4 (вычислительный эксперимент и отладка) | 1,5 | | Задание 5 (отчёт) | 0,5 | | Защита и допуск | 2,0 | | **Максимум** | **10** | Проходной балл — **6,0**. Допуск — устный опрос (раздел 6), не менее 3 правильных ответов из 5. **Литература:** 1. Лекомцев П.В. Строковые операции в MASM32: методические указания к выполнению лабораторной работы №3 по дисциплине «Основы вычислительной техники». — Ижевск: ИжГТУ, 2012. 2. Яковлев А.В. Программирование на Ассемблере в Win32: дополнительный лекционный материал. — Муром: Муромский институт (филиал) ВлГУ, 2003. 3. Пирогов В.Ю. Assembler. Учебный курс. — М.: Молгачева С.В., Нолидж, 2001. — 848 с. 4. Пирогов В.Ю. Ассемблер для Windows. — 2-е изд., перераб. и доп. — СПб.: БХВ-Петербург, 2003. — 656 с. 5. Юров В.И. Assembler. Учебник для вузов. — 2-е изд. — СПб.: Питер, 2004. — 637 с.