- •1.1.1. Кодирование символов
- •2. Системный отладчик Debug
- •2.1. Адресация памяти
- •2.2. Работа в отладчике
- •Лабораторная работа № 1
- •3. Основы программирования
- •3.1. Процесс программирования
- •3.1.1. Этапы создания программы
- •3.1.2. Компиляция программы. Опции командной строки
- •3.2. Cинтаксис ассемблерной программы
- •3.3. Простейшая программа
- •3.4. Скелет (каркас) программы
- •3.4.1. Модуль EXE
- •3.4.2. Модуль COM
- •3.5. Образ программы в памяти
- •3.5.1. Модуль EXE
- •3.5.2. Модуль COM
- •3.6. Работа с отладчиком Turbo Debugger (TD)
- •Лабораторная работа №1
- •4. Операторы и директивы
- •4.1. "Препроцессорные" директивы INCLUDE и EQU
- •4.2. Директивы описания и инициализации переменных DB, DW и DD
- •4.2.1. Директива DB (Define Byte - определить байт)
- •4.2.2. Директивы DW и DD (Define Word и Define Double Word)
- •4.3. Операторы Assembler
- •4.3.1. Операторы обработки данных
- •4.3.2. Операторы передачи управления
- •4.4. Вспомогательные псевдооператоры
- •4.5. Работа с макрооператорами
- •Лабораторная работа № 2
- •4.6. Приложение к лабораторной работе № 2. Адресация
- •4.6.1. Форматы машинных команд и их кодирование
- •4.6.2. 16-битный режим адресации операндов в памяти
- •5. Сервисные функции DOS
- •5.1.1. Ввод с клавиатуры символьной информации
- •5.1.2. Системные функции DOS ввода данных с клавиатуры
- •5.1.3. Команды работы со строками
- •5.1.4. Системные функции DOS вывода данных
- •Лабораторная работа №3
- •Лабораторная работа №4
- •6. Функции BIOS для работы с экраном и клавиатурой
- •6.1. Прямое программирование видеобуфера в текстовом режиме
- •6.2. Прерывание 10h. Видеофункции BIOS
- •6.3. Прерывания 16h, 1Ah, 15h
- •6.3.1. Прерывание 16h
- •6.3.2. Прерывание 1Ah
- •6.3.3. Прерывание 15h
- •Лабораторная работа №5
- •Заключение
- •Рекомендуемая литература
- •Использованная литература
Рис. 3.2. Таблица символов ASCII
Лабораторная работа №3
Тема работы. Использование сервисных функций DOS ввода-вывода и работа со строками.
Цель работы. Научиться работать с некоторыми функциями 21-го прерывания и строковыми переменными. Понять структуру таблицы ASCII кодов.
Содержание работы.
В данной работе происходит знакомство с функциями DOS 21-го прерывания. Вызов функций, параметры входа и параметры вывода.
П р о г р а м м а 1
1 |
IDEAL |
2 |
MODEL small |
3STACK 256
4 |
descrip_in |
= |
0 |
;Дескриптор стандартного |
ввода |
|
|
5 |
descrip_out = 1 |
;Дескриптор |
стандартного |
вывода |
|||
6 |
descrip_err |
= |
2 |
;Дескриптор |
стандартной ошибки |
(экрана) |
7DATASEG
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 |
;Преобразуем в прописную |
80
31 |
mov [Buf+si],al |
;Отправим в Buf |
||
32 |
no_letter: |
inc si |
;Цикл |
|
33 |
loop 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 и произойдет произойдет
81
преобразование очередного строчного символа в прописной и загрузка получившегося прописного символа в буфер (строки 30-31).
В строке 33 оператор LOOP организует цикл, длина которого находится в регистре CX, предварительно в него загружено значение act_in. Оператор LOOP будет возвращаться на метку filter, пока значение CX>0, при этом, при каждом очередно возврате CX автоматически уменьшается на 1. В завершении происходит вывод получившейся преобразованной строки на экран средствами функции 40h.
Задания к работе.
1.Измените программу таким образом, чтобы в случае, если в веденной строке не оказалось ни одной строчной латинской буквы, программа бы потребовала повторного воода строки.
2.Измените блок вывода строки таким образом, что бы вывод производился средствами функции 09h, а не 40h.
82
Лабораторная работа №4
Тема работы. Работа с одиночными символами и сравнение строк.
Цель работы. Научиться использовать функции DOS для работы с одиночными символами и использование оператора сравнения строк для сравнения массива байт в памяти.
Содержание работы.
В данной работе рассматривается программа, в которой демонстрируется работа функции ввода одиночных символов с клавиатуры и процесс сравнения двух строк.
П р о г р а м м а 1
1IDEAL
2 |
MODEL |
small |
3 |
STACK |
256 |
4DATASEG
5 |
password |
DB |
'tspu' |
;Пароль |
6 |
pass_len |
= |
$ - password |
7string DB 80 DUP(?)
8 promt DB 13,10,'Введите пароль: $'
9OK 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 (строки 17-
83
19). Сразу после ввода идет проверка завершения ввода пароля путем сравнения содержимого регистра 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
84