Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Met_Lab2_121113

.pdf
Скачиваний:
16
Добавлен:
11.05.2015
Размер:
1.72 Mб
Скачать

является то обстоятельство, что она, просматривая устройство ввода, не останавливает программы (является асинхронной), если не обнаруживает в нём символа, а просто устанавливает флаг ZF = 1. Допускает перенаправление ввода-вывода. Для чтения расширенного кода ASCII требуется повторное выполнение функции.

Вызов: AH =06h, Int 21h.

Ввод (без эха): DL = FF. Выход: ZF = 0, AL = код символа; ZF = 1 – устройство ввода пустое.

Вывод: DL = FE¸00. Код в регистре DL является одновременно и кодом выводимого символа.

Функция 07h. Нефильтрованный ввод символа без эха.

Вводит символ из стандартного устройства ввода без его отображения на экране. При отсутствии символа ждёт его ввода. Допустимо перенаправление ввода. Не выполняет отработку <Ctrl+C>. Для чтения расширенного кода ASCII требует повторное выполнение функции. Функция, как правило, используется для ввода пароля с целью защиты программы от несанкционированного запуска

Функция 08h. Ввод символа без эха.

Вводит символ из стандартного устройства ввода. При отсутствии символа ждёт его ввода. Допустимо перенаправление ввода. Для чтения расширенного кода ASCII требует повторное выполнение функции. Если ввод не перенаправлен, чувствительна к <Ctrl+C> (иначе надо предварительно включить режим Break). Как и функция 07h, используется для ввода пароля. Пример использования данной функции будет рассмотрен в одной из программ этой работы.

Вызов: AH = 08h, Int 21h.

Вывод: AL = код символа.

Функция 0Ah. Буферизованный ввод с клавиатуры.

Вводит строку байт из устройства стандартного ввода в буфер пользователя по адресу DS:DX, с отображением на устройстве стандартного вывода. Допустимо перенаправление ввода. Если ввод не перенаправлен, выполняет отработку <Ctrl+C> (иначе надо предварительно включить режим Break). Функция допускает редактирование данных при их вводе клавишами: Backspace (отмена последнего символа), Exc (отмена всего набранного текста), F5 (запоминает текущую строку как подсказку), F3 (восстанавливает подсказку для ввода). Ввод символов строки заканчивается нажатием клавиши <Enter>, код которой (0Dh) вводится в качестве последнего символа в отведённый буфер.

Структура буфера (резервируется в сегменте данных): байт 0 – назначаемая пользователем максимальная длина строки (1-254) с учётом символа CR (код 0Dh), байт 1 – число реально введённых символов без учёта символа CR, байт 2 и далее – строка. В следующем примере приведена процедура In_string ввода строки в буфер, емкостью 50 символов. Она возвращает адрес первого символа строки в регистре DX, а число символов в регистре CX.

Функция 0Bh. Проверка состояния ввода.

81

Проверяет наличие символа в буфере клавиатуры. Допустимо перенаправление ввода. Если ввод не перенаправлен, выполняет отработку <Ctrl+C>. Это даёт возможность организовать с её помощью аварийное завершение программы (нажатием комбинации <Ctrl+C>) с циклом, состоящим из чисто процессорных команд, включив предварительно в цикл вызов функции 0Bh.

Вход: AH = 0Bh.

Возврат: Если символа нет, то AL = 0, если символ ждет, то AL = FFH.

Функция 0Ch. Вызов служебной функции DOS для ввода данных с предварительной очисткой буфера клавиатуры. Допускает переопределение ввода.

Вызов: AH = 0Ch, Int 21h,

AL = номер функции ввода: 01, 07, 08, 0Ah (если AL = 0, то только очистка), DS:DX = адрес буфера, если AL = 0Ah.

Выход: AL = байт входных данных (если при вызове Al = 0Ah, данные помещаются в буфер).

Функция 3Fh. Ввод данных из файла или устройства.

Универсальная функция ввода данных в буфер с указателем DS:DX из источника, определённого дескриптором в регистре BX. Допускает переопределение ввода. В регистре CX указывается число байтов, которое необходимо ввести. Пример использования.

Команда Int 21h ожидает окончания ввода символов, которое фиксируется нажатием клавиши Enter. После ввода текста и нажатия клавиши Enter в буфер In_Area автоматически вводятся два управляющих символа: CR (код 0Dh) и LF (код 0Ah). Вследствие данной особенности максимальное число символов и размер буфера ввода должны содержать место для двух дополнительных символов. При успешном завершении операции флаг CF = 0, а в регистре AX устанавливается число байтов, введённых с клавиатуры (плюс два дополнительных символа). Если CF = 1, то в регистре AX содержится возвратный код ошибки. Это либо 5 (отказ в доступе), либо 6 (неверный дескриптор).

К особенностям использования данной функции следует отнести автоматический переход на новую строку по окончании ввода данных.

4.1.3. Команды работы со строками

Строкой или литералом в языке ассемблера называется последовательность букв, цифр и других символов, заключённых в кавычки или апострофы (двойные кавычки). Следует отметить, что иногда понятие строки трактуется в расширительном смысле, а именно, как последовательность байтов, которые могут либо представлять, либо не представлять ASCII-символы.

Строковые команды, несмотря на синонимичное название со строковыми переменными, предназначены для обработки не только ASCII-строк, но и вообще блоков байтов, одинарных или двойных слов, каждое из которых хранится в памяти в двоичном коде.

Строковые команды представлены в табл. 3.1 и по своему назначению делятся на две группы:

команды перемещения данных (LODS, STOS, MOVS);

82

команды для поиска и сравнения данных (SCAS, CMPS).

Любая строковая команда может оперировать как байтами, так и словами, что

отражается в мнемокоде команды (например: MOVSB, MOVSW, MOVSD). Все строковые команды, в отличие от других команд процессора Intel x86, используют для выполнения своих функций одни и те же регистры:

DS:SI(ESI) – регистры строки-источника;

ES:DI(EDI) регистры строки-приёмника.

Т а б л и ц а 3 . 2 .

Команды обработки строк

Название команды и её мнемокод

Действие

Префикс

Влияние на флаги

 

 

 

 

LODS source – Загрузка из строки

al src

-

Нет

source=byte DS:SI LODSB

ax src

 

 

source=word DS:SI LODSW

eax src

 

 

source=dword DS:SI LODSD

 

 

 

 

 

 

 

STOS dest – Сохранение Acc в строке

al dst

Rep

Нет

dest=byte ES:DI Stosb

ax dst

 

 

dest=word ES:DI Stosw

eax

 

 

dest=dword ES:DI Stosd

 

 

 

 

 

 

 

MOVS dest,source – Пересылка элемента строки

dst src

Rep

Нет

dest=byte ES:DI, source=byte DS:SI Movsb

 

 

 

dest=word ES:DI, source=word DS:SI Movsw

 

 

 

dest=dword ES:DI, source=dword DS:SI Movsd

 

 

 

 

 

 

 

SCAS dest – Поиск элемента в строке

aldst

Repe

Все флаги

dest=byte ES:DI Scasb

axdst

(Repz)

операции

dest=word ES:DI Scasw

eaxdst

Repne

сравнения

dest=dword ES:DI Scasd

 

(Repnz)

 

 

 

 

 

CMPS dest, source – Сравнение элементов строк

srcdst

Repe

Все флаги

source=byte DS:SI, dest=byte ES:DI Cmpsb

 

(Repz)

операции

source=word DS:SI, dest=word ES:DI Cmpsw

 

Repne

сравнения

source=dword DS:SI, dest=dword ES:DI Cmpsd

 

(Repnz)

 

 

 

 

 

При этом индексные регистры SI(ESI) и DI(EDI) определяют смещения элементов строк в сегментах данных, определяемых регистрами ds и es соответственно. Установите es = ds, если это не противоречит другим условиям реализации программы, что позволит вам не беспокоиться о корректной адресации сегментов памяти. Необходимо помнить, что в строковых инструкциях приёмник – строка ES:DI(EDI) не допускает переопределение, а источник – строка DS:SI(ESI), допускает переопределение на ES:SI(ESI).

Префикс повторения, помещённый непосредственно перед строковой командой, заставляет её циклически выполняться определённое число раз до реализации заданного условия. Существуют три командных префикса:

Rep (repeat) – повторять, пока CX0;

Repe/Repz (repean while zero) – повторять, пока (CX0)&(ZF=1);

Repne/Repnz (repean while not zero) – повторять, пока (CX0)&(ZF=0).

Префиксы используют регистр CX как счётчик числа циклов (беззнаковое число),

которое должно быть записано в CX до начала выполнения строковой команды. Счётчик CX декрементируется (уменьшается) на 1 после выполнения строковой команды, но проверяется

83

перед её выполнением. Если CX = 0, то строковая команда не выполняется ни разу. Префиксы Repe и Repne дополнительно выставляют флаг нуля ZF после выполнения строковой операции.

4.1.4. Системные функции DOS вывода данных

DOS предоставляет следующие способы вывода данных на экран:

использование функций Int 21h (02h, 06h, 09h), обеспечивающих посимвольный ввод

склавиатуры в разных режимах;

обращение к экрану, как к файлу, с помощью функции 40h.

Функция 02h. Вывод одиночного символа.

Выводит символ, находящийся в регистре DL, на экран, после чего курсор сдвигается на одну позицию вправо. Для вывода строки функцию следует использовать в цикле. Допустимо перенаправление вывода. Выполняет обработку <Ctrl/C> при вводе этой комбинации с клавиатуры перед выводом каждого 64-го символа. Эта функция выводит и управляющие ASCII-символы с кодами 07h, 08h, 09h, 0Ah, 0Dh. Символ с кодом 07h (bell, звонок) вызывает звуковой сигнал, с кодом 08h (backspace, забой) – возвращает курсор на одну позицию влево, с кодом 09h (tab, табуляция) – смещает курсор на одну позицию вправо, кратную 8. Действия управляющих клавиш с кодами 0Ah и 0Dh рассматривались ранее.

Вызов: AH = 02h, Int 21h.

Выход: DL = ASCII – код символа

AL = код последнего записанного символа (кроме случая, когда DL= 09, тогда возвращается значение 20h).

Использование данной функции рассмотрим на примере процедуры перехода на новую строку.

PROC NewLine

mov ah,2 ;Запрос функции 02h mov dl,13 ;Возврат каретки int 21h ;Вызов DOS

mov dl,10 ;перевод строки int 21h ;Второй вызов DOS ret

ENDP NewLine

Функция 09h. Вывод строки.

Выводит строку символов на устройство стандартного вывода (используется в системных программах для вывода на экран информационных сообщений). Строка должна заканчиваться символом $ (код 24h), который служит признаком конца строки, и сам не выводится. Допустимо перенаправление вывода. В сообщение могут быть включены и управляющие коды (07h, 08h, 09h, 0Ah, 0Dh), которые вызывают соответствующие им действия (см. функцию 02h). Допустимо использование Exc-последовательностей. Функция выполняет обработку <Ctrl/C> при вводе этой комбинации с клавиатуры перед выводом каждого 64-го символа.

Пример использования.

84

.....................

Promt DB ‘Name? $’

.....................

lea dx,[Promt] ;Адрес строки Promt: DS:DX mov ah,09h ;Запрос функции 09h

int 21h ;Вызов DOS

.....................

Вместо оператора LEA можно использовать оператор mov, указав в качестве пересылаемого значения не [Promt], а offset Promt.

Функция 40h. Вывод данных в файл или в устройство.

Универсальная функция вывода данных из буфера пользователя в сегменте данных в файл или на устройство, дескриптор которого указывается в регистре BX. Дескриптор 1, закреплённый за стандартным устройством вывода, обеспечивает перенаправление вывода. Значение регистра CX определяет число байтов, которые должны быть выведены, а пара регистров DS:DX указывает адрес выводимых данных. Управляющие коды 08h, 0Ah, 0Dh и некоторые другие приводят к выполнению соответствующих им действий. После завершения вывода при CF = 0 регистр AX содержит число действительно выведенных байтов, а при CF =1 – возвратный код ошибки. Как и при использовании функции 3Fh, это коды ошибок 5 или 6. Пример использования.

.......................

Out_Area DB 20 DUP(?)

.......................

mov ah,40h ;Запрос функции 40h mov bx,01 ;Дескриптор дисплея

mov cx,20 ;Число пересылаемых байт

lea dx,[Out_Area] ;Адрес буфера для выводимого сообщения int 21h ;Вызов DOS

........................

Таблица кодирования символов ASCII

В данном разделе приведена полная таблица отображаемых символов ASCII, состоящая из двух равных частей по 128 символов. Номера строк соответствуют первой цифре 16-теричного кода символа, номера столбцов – второй, так что, например, код прописной латинской буквы А = 41h. Первая половина таблицы символов с кодами 00h – 7Fh является Американским стандартным кодом для обмена информации (английская аббревиатура ASCII) и имеет международный стандарт, вторая – соответствует одному из широко распространённых в России вариантов кодирования символов для IBM-совместимых компьютеров.

Первая половина таблицы ASCII содержит символы двух типов: управляющие (коды 00h – 1Fh, 7F) и алфавитно-цифровые (20h-7E), вторая – символы кириллицы и псевдографики.

85

Рис. 3.2. Таблица символов ASCII

Лабораторная работа №3

Тема работы. Использование сервисных функций DOS ввода-вывода и работа со строками.

Цель работы. Научиться работать с некоторыми функциями 21-го прерывания и строковыми переменными. Понять структуру таблицы ASCII кодов.

Содержание работы.

В данной работе происходит знакомство с функциями DOS 21-го прерывания. Вызов функций, параметры входа и параметры вывода.

П р о г р а м м а 1

1IDEAL

2MODEL small

3STACK 256

4

descrip_in

=

0

;Дескриптор стандартного ввода

5

descrip_out

=

1

;Дескриптор стандартного вывода

6

descrip_err

=

2

;Дескриптор стандартной ошибки (экрана)

7

 

DATASEG

 

 

 

8

msg

Db

'Введите строку!',10,13,'$'

9

Buf

DB

80 DUP(?)

 

10

act_in

DW

?

 

 

11

 

CODESEG

 

 

 

12

Start:

 

mov ax,@data

13

 

 

mov ds,ax

 

14

 

 

mov ah,09h

;Функция вывода

15mov dx,offset msg ;Адрес сообщения

16int 21h

17

mov ah,3fh ;Функция ввода

18mov bx,descrip_in

19mov cx,80 ;Ввод максимум 80 байт

20mov dx,offset Buf ;Адрес буфера

21int 21h

22

mov [act_in],ax

;Фактически введено

23

mov cx,[act_in]

;Счётчик элементов строки

24

mov si,0

;Инициализация указателя элементов строки

25

filter: mov al,[Buf+si]

;Возьмём символ

26

cmp al,'a'

;Меньше

'a'?

27

jb no_letter

;Да, не

преобразовывать

28

cmp al,'z'

;Больше

'z'?

29

ja no_letter

;Да, не

преобразовывать

30

sub al,20h

;Преобразуем в прописную

 

 

 

 

86

31

mov [Buf+si],al

;Отправим в Buf

32no_letter: inc si

33loop filter ;Цикл

34

mov ah,40h ;Функция вывода

35

mov

bx,descrip_out

 

36

mov

cx,[act_in]

;Длина сообщения

37mov dx,offset Buf ;Адрес сообщения

38int 21h

39Exit: mov ax,4C00h

40int 21h

41END Start

В данной программе происходит ввод строки с клавиатуры с дальнейшим

преобразованием полученых строчных символов в прописные.

Программа состоит из 3х основных логических блоков - ввода строки, преобразования строчных символов в прописные и вывод получившейся строки. Сначала с помощью функции 09h выводится сервисное сообщение "Введите строку", затем, функцией 3Fh производится ввод строки с клавиатуры, поскольку строковой переменной Buf в сегменте данных было выделено максимум 80 байт, то в счетчик CX так же нужно загрузить число не более 80. В регистр BX загружается дескриптор стандартного ввода, в регистр DX смещение буфера ввода.

Замечание. Поскольку адрес буфера состоит из DS:DX, а при использовании модели памяти small, мы работаем только с одним сегментом, который загружается в самом начале, то устанавливать адрес сегмента нет необходимости, нужно установить только смещение в данном сегменте.

После того, как все регистры подготовлены к функции 3Fh, производится ее вызов и программа принимает с клавиатуры строку символов.

После того, как строка введена нужно сохранить значение ее длины, оно потребуется для процедуры преобразования символов и для вывода преобразованной строки. Для этих целей была декларирована переменная act_in.

Далее идет подготовка регистров к переводу строчных символов в прописные. Основной принцип данной операции заключается в том, что бы выделить из всей строки именно строчные латинские символы и уменьшить их ASCII код на 20h, если внимательно посмотреть на таблицу кодов ASCII можно увидеть что код символа каждой строчной буквы больше на 20h кода аналогичной ей прописной буквы. Выделение строчных латинских букв происходит с помощью опертора сравнения и двух операторов условного перехода. В качестве счетчика символов (указателя на номер символа в строке) используется регистр SI. Начало цикла сравнения и преобразования начинается с загрузки очередного символа в регистр AL (строка 25), на данной строке установлена метка filter для того, что бы цикл начинался именно с оператора загрузки очередного символа. Очередной символ сравнивается с символом 'a', если код очередного символа меньше кода символа 'a', произойдет переход оператором JB (если меньше) на метку no_letter (строка 32), и в результате операторы в строках 28-31 пропускаются, увеличивается указатель на символ в строке и операция повторяется. Данная часть отсекает от преобразования все символы коды которых меньше кода символа 'a'. Аналогично отсекаются все коды, которые больше кода символа 'z', при этом используется оператор JA (если больше).

В случае, если же код символа лежит в диапазоне 'a' - 'z', то ни оператор JB, ни оператор JA не вызовет перехода на метку no_letter и произойдет произойдет

87

преобразование очередного строчного символа в прописной и загрузка получившегося прописного символа в буфер (строки 30-31).

В строке 33 оператор LOOP организует цикл, длина которого находится в регистре CX, предварительно в него загружено значение act_in. Оператор LOOP будет возвращаться на метку filter, пока значение CX>0, при этом, при каждом очередно возврате CX автоматически уменьшается на 1. В завершении происходит вывод получившейся преобразованной строки на экран средствами функции 40h.

Задания к работе.

1.Измените программу таким образом, чтобы в случае, если в веденной строке не оказалось ни одной строчной латинской буквы, программа бы потребовала повторного воода строки.

2.Измените блок вывода строки таким образом, что бы вывод производился средствами функции 09h, а не 40h.

88

Лабораторная работа №4

Тема работы. Работа с одиночными символами и сравнение строк.

Цель работы. Научиться использовать функции DOS для работы с одиночными символами и использование оператора сравнения строк для сравнения массива байт в памяти.

Содержание работы.

В данной работе рассматривается программа, в которой демонстрируется работа функции ввода одиночных символов с клавиатуры и процесс сравнения двух строк.

П р о г р а м м а 1

1

IDEAL

 

 

 

2

MODEL

small

 

 

3

STACK

256

 

 

 

4

DATASEG

 

 

 

5

password

DB

'tspu'

;Пароль

6

pass_len

=

$ - password

7

string

DB

80

DUP(?)

 

8

promt

DB

13,10,'Введите пароль: $'

9

OK DB

13,10,'Верный пароль $'

10CODESEG

11Start: mov ax,@data

12mov ds,ax

13begin: mov ah,09h

14mov dx,offset promt

15int 21h

16mov bx,0

17pass: mov ah,08h

18int 21h

19cmp al,13

20je cmpr

21mov [string+bx],al

22mov ah,02

23mov dl,'*'

24int 21h

25inc bx

26jmp pass

27cmpr: push ds

28pop es

29mov si,offset string

30mov di,offset password

31cld

32mov cx,pass_len

33 repe cmpsb

34jne Error

35mov ah,09h

36mov dx,offset OK

37int 21h

38Exit: mov ax,4C00h

39int 21h

40Error: jmp begin

41END Start

Как и программа из предыдущей лабораторной работы, данная программа состоит из трех основных логических блока - ввод пароля, сравнение с правильным паролем, вывод результата.

Для ввода пароля используется функция DOS 08h, которая считывает скан-код клавиши и заносит ASCII код, соответствующий нажатой клавиши, в регистр AL (строки 1719). Сразу после ввода идет проверка завершения ввода пароля путем сравнения

89

содержимого регистра AL с числом 13, т.к. 13 - это ASCII код клавиши <Enter>. В случае, если нажата клавиша <Enter>, оператор JE произведет переход на метку cmpr и начнется сравнение пароля. В случае, если нажата любая другая клавиша (не <Enter>) произойдет загрузка полученного очередного символа в заранее созданную строковую переменную string. В качестве указателя на номер символа в строке используется регистр BX. Для повтора считывания символа используется оператор безусловного перехода JMP (строка 26), который будет постоянно возвращать ход программы на метку pass. Параллельно со считыванием вновь введенных символов и загрузкой их в string, в данном "цикле" размещен вызов функции 02h с предварительной загрузкой в регистр DL кода символа '*', для того, чтобы получить эффект ввода пароля - т.е. при нажатии очередной клавиши считывается ее код, загружается в строковую переменную и сразу же выводится на экран символ '*'.

Сравнение полученной строки string и строки password, в которой хранится пароль, производится с помощью оператора CMPSB, который побайтно сравнивает строки с адресами DS:SI и ES:DI. Для данного оператора используется префикс Repe, это означает, что сравнение будет происходить до тех пор, пока сравниваемые символы совпадают, но не более, чем длина, указанная заранее в CX . Перед тем, как вызвать оператор СMPSB, нобходимо подготовить все нужные регистры, а именно уравнять значения регистра сегмента данных DS и регистра расширенного сегмента данных ES, что делается в строках 27 и 28 при помощи стека, затем поместить смещение одной строки в SI, другой в DI (строки 29 и 30), и установить количество сравниваемых байт в CX (строка 32). Так же, помимо подготовки регистров нужно обнулить флаг направления DF оператором CLD (строка 31).

В случае единственного несовпадения флаг ZF станет равным 0 и сравнение закончится, при этом, так же, сработает безусловный переход оператором JNE на метку Error, которая отсылает ход программы на начало и ввод пароля повторяется.

Данная программа не закончится пока не будет введен правильный пароль, либо не будет нажато сочетание клавиш Ctrl+C.

Задания к работе.

1.Напишите программу, которая будет считывать набор из n символов средствами функции считывания одиночных символов, после считывания программа должна вывести этот набор в виде строки.

2.2

90

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]