Команды обработки строк
При этом индексные регистры si(esi) и di(edi) определяют смещения элементов строк в сегментах данных, определяемых регистрами ds и es соответственно. Установите es = ds, если это не противоречит другим условиям реализации программы, что позволит вам не беспокоиться о корректной адресации сегментов памяти. Необходимо помнить, что в строковых инструкциях приёмник – строка es: di(edi) не допускает переопределение, а источник – строка ds: si(esi), допускает переопределение на es: si(esi). Каждая из строковых команд выполняет операцию только над парой элементов двух строк (или над одним для команд Lods, Stos, Scas) и автоматически настраивается на обработку соседних элементов, обеспечивая продвижение по строке в нужном направлении, а именно: si: =si+d, di: =di+d. Здесь величина d определяется согласно правилу: Тип операнда Флаг направления df =0 df =1 byte +1 -1 word +2 -2 dword +4 -4 Префикс повторения, помещённый непосредственно перед строковой командой, заставляет её циклически выполняться определённое число раз до реализации заданного условия. Существуют три командных префикса: - rep (repeat) – повторять, пока cx ¹ 0; - repe/repz – повторять, пока (cx ¹ 0) & (zf = 1); - repne/repnz – повторять, пока (cx ¹ 0) & (zf = 0). Префиксы используют регистр CX как счётчик числа циклов (беззнаковое число), которое должно быть записано в cx до начала выполнения строковой команды. Счётчик cx декрементируется на 1 после выполнения строковой команды, но проверяется перед её выполнением. Если cx = 0, то строковая команда не выполняется ни разу. Префиксы repe и repne дополнительно выставляют флаг нуля zf после выполнения строковой операции. В листинге 2.2. рассматривается использование строковой команды сравнения cmpsb на примере программы с паролем. Идея простейшей защиты программы от несанкционированного запуска заключается в том, что где-то в программе записывается ключевое слово-пароль, и программа, начав работать, требует ввода этого слова с клавиатуры. Если пользователь ввёл пароль правильно, программа продолжит свою работу, иначе попросит ввести его заново или завершится. Ввод пароля обычно осуществляется функцией DOS, не отображающей вводимые символы на экране (обычно 07h или 08h) и заканчивается нажатием клавиши < Enter>. Листинг 2.2. Фрагмент программы с паролем. ................... password DB 'camel'; Пароль pass_len = $ – password string DB 80 DUP(?) promt DB 13, 10, 'Введите пароль: $' OK DB 13, 10, 'Работаем! $' CODESEG start: mov ax, @data mov ds, ax begin: mov ah, 09h; Вывод запроса на ввод пароля mov dx, offset promt; Адрес запроса int 21h ; Введём пароль mov bx, 0; Инициализация индексирования ввода pass: mov ah, 08h; Функция ввода символа в AL без эха int 21h cmp al, 13; < Enter>? je compare; Да, на сравнение mov [string+bx], al; Нет, сохраним символ mov ah, 02 mov dl, '*'; Запишем на экран * int 21h inc bx jmp pass; Повторять ; Сравнение введённого пароля с действительным (сравнение строк) compare: push ds; Установить ES на сегмент данных pop es mov si, offset string; DS: SI- начало string mov di, jffset password; ES: DI- начало password cld; DF=0- просмотр вперёд mov cx, pass_len; Установить счётчик сравнения repe cmpsb; Сравнивать, пока {CX³ 0 и ZF=1} (или повторять ; пока символы двух строк совпадают, но не более CX раз) jne err; Строки не равны Вывод сообщения ОК, подтверждающего правильность пароля mov ah, 09h mov dx, offset OK int 21h ; продолжение программы ................. exit: mov ax, 4C00h; Ввод функции 4С для завершения программы int 21h err: jmp begin; Повторить ввод пароля END start Логика построения программы поясняется подробными комментариями. В программе ввод пароля выполняется в бесконечном цикле, поэтому пользователь, не знающий пароля и запустивший программу, для выхода из неё вынужден будет нажать комбинацию клавиш < Ctrl+C>.
|