Обработка символьной информации с помощью функций dos

Прерыванием (interrupt),подробнее см. раздел 7, называется способ общения центрального процессора с периферийными устройствами. Периферийное устройство (клавиатура, дисковод и др.) посылает запрос на установление сеанса передачи, процессор прерывает выполнение основной программы и переходит на выполнение программы обработки запроса от периферийного устройства. Эта программа, драйвер устройства, предварительно загружена в память (резидентная программа) и её адрес известен процессору. Такая обработка запросов называется аппаратными прерываниями.

Программные прерывания и системные вызовы

Операционная система MS_DOS, как известно, является однозадачной операционной системой, т.е. одновременно может исполнять только одну задачу. Вместе с тем имеется необходимость во время выполнения основной задачи производить некоторые вспомогательные действия. Подход, основанный на предварительной загрузке резидентных программ, использованный в аппаратных прерываниях, которые можно вызывать в момент выполнения основной программы, например, переключение раскладки клавиатуры или обращение к дисководу, оказался очень продуктивным, так как делает MS-DOS псевдомногозадачной системой.

Вызовы резидентных программ, адрес которых заранее известен процессору, стали называть, по аналогии с аппаратными прерываниями, программными прерываниями, хотя никаких прерываний на самом деле не происходит. В систему команд процессора ввели команду вызова программного прерывания, которая вызывает соответствующую резидентную программу.

Команда вызова программного прерывания имеет вид

int <номер прерывания>

<номер прерывания> - число, обычно в шестнадцатеричное, в диапазоне 00h – 0FFh, определяет адрес вызываемой резидентной программы.

Некоторые резидентные программы, выполняющие низкоуровневое общение с периферийными устройствами записаны в ROM BIOS (Read Only Memory Base Input/Output System) и поставляются вместе с системной платой, например, учёт системного времени, форматирование секторов на дорожке диска и т.д., и не зависят от применяемой операционной системы.

Резидентные программы, использующие низкоуровневую систему резидентов BIOS и выполняющие более сложные задачи, например, файловые операции с диском, подгружаются в память при загрузке операционной системы. Их принято называть функциями операционной системы или системными вызовами.

Наибольшее число различных системных функций в MS-DOS сосредоточено в резидентной программе с номером прерывания 21h – диспетчер функций MS-DOS. В зависимости от значения, содержащегося при вызове прерывания в регистре ah, MS-DOS выполняет одну из нескольких десятков функций MS-DOS.

Все функции BIOS и DOS описаны в специальных справочниках с указанием для каждой функции набора входных и выходных параметров, передаваемых через регистры, а также перечнем возможных ошибок. В данной главе будут описаны функции прерывания 21h относящиеся к работе с клавиатурой и экраном ПЭВМ.

Описание функций работы с клавиатурой и дисплеем диспетчера функций MS-DOS

Для вызова функции прерывания DOS 21h необходимо проделать следующие действия:

· выбрать функцию, выполняющую требуемые действия;

· занести номер функции в регистр аh;

· подготовить другие регистры (если это необходимо);

· написать команду int 21h;

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

Ниже следует описание некоторых функций 21Н.

Функции 01Н

Выполняет ввод с клавиатуры одного символа и отоббражает его на экране.

· Вызов:

ah = 01h

· Возвращаемое значение:

аl = код ASCII введенного символа

· Примечание. Введенный символ отобращается на экране (выполняется эхо-отображение). Комбинация клавиш Ctrl/С (или Ctrl/Break) прекращает выполнение программ пользователя.

Функции 02Н

Выполняет отображение символа на стандартный вывод (дисплей).

· Вызов:

ah = 02h

dl = отображаемый символ

· Возвращаемое значение:

нет

· Примечание. Символ отображается на стандартный вывод. Комбинация клавиш Ctrl/C (или Ctrl/Break) прекращает выполнение программ пользователя.

Функция 05Н

Выполняет отображение символа на принтер.

· Вызов:

аh = 02h

dl = символ для принтера

· Возвращаемое значение:

нет

· Примечание. Символ отображается на принтер. Комбинация клавиш Ctrl/C (или Ctrl/Break) прекращает выполнение программ пользователя. Эта функция не возвращает ошибки состяния принтера.

Функция 07Н

Выполняет ввод с клавиатуры одного символа.

· Вызов:

аh=07h

· Возвращаемое значение:

al = код ASCIL введенного символа

· Примечание. Введенный символ не отображается на экране (не выполняется эхо-отображения). Комбинация клавиш Ctrl/C (или Ctrl/Break) прекращает выполнение программы пользователя.

Функция 08Н

Выполняет ввод с клавиатуры одного символа.

· Вызов:

аh=08h

· Возвращаемое значение:

al = код ASCII введенного символа

· Примечание. Введенный символ не отображается на экране (не выполняется эхо-отображение). Комбинация клавиш Ctrl/C ( или Ctrl/Break) прекращает выполнение программы пользователя.

Функция 09Н

Выполняет отображение строки на стандартный вывод.

· Вызов:

аh = 09Н

ds: dx=указатель на отображаемую строку

Возвращаемое значение:

нет

· Примечание: Строка отображается на стандартный вывод. $ признак конца строки, $ не отображается, dx содержит смещение строки, ds - сегментный адрес. Ниже приведены код управления курсором:

0dh (13) - перевод курсора в начало текущей строки;

0ah (10) - перевод курсора вниз на 1 строку;

08h (8) - перевод влево на 1 позицию;

07h (7) - звонок.

Пример.

Чтобы вывести на экран с новой строки текст: “Функция 09Н для

выдачи текста на экран” и затем перевести курсор в следующую

строку, следует в сегменте данных описать строку:

beg db 0dh, 0ah, “Функция 09Н для выдачи текста наэкран”, 0dh,0ah, “$”

а в программном сегменте записать команды:

lea dx,beg ; адрес строки в dx

mov ah,09h ; номер функции в аh

int 21h ; вызов функции

Функция ОАН

Выполняет ввод с клавиатуры в буфер строки символов.

· Вызов:

аh= 0аh

ds: dx = адрес буфера ввода

· Возвращаемое значение:

Строка символов по указанному адресу

· Примечание. Читается со стандартного ввода. dx содержит смещение буфер вывода, DS - сегментный адрес. Буфер вывода имеет следующую структуру: 0-й байт содержит максимальное количество символов в буфере; 1-й байт содержит количество реально введенных символов; начиная со 2-го размещён буфер для ввода размером не менее указанного в в 1-м байте. Выполняется эхо-отображение. Комбинация клавиш Ctrl/C (или Ctrl/Break) прекращает выполнение программы пользователя. Символы вводятся один за другим, до тех пор, пока не будет введен код ODh (код клавиш “Enter”), завершающий строку. В ходе ввода строки пользователь может редактировать строку, и, в частности, использовать “забой”.

Пример.

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

buffer db 11 ; Нулевой байт буфера

entered db (?) ; Число введенных символов

string db 11 dup (?) ; Введенные символы

Сам ввод выполняется командами:

lea dx, buffer ; Адрес буфера в dx

mov ah, 0ah ; Номер функции в аh

int 21h ; Вызов функции

Функция 0Bh

Выполняет опрос состояния буфера клавиатуры.

· Вызов:

ah = 0Bh

· Возвращаемое значение:

аl = 00h, если нет символа в буфере клавпиатуры;

al = ffh, если есть символ в буфере клавиатуры.

· Примечание. Устанавливает значение AL в зависимости от наличия символов в буфере клавиатуры. Часто используются в задачах, действующих при нажатии определенных клавиш. Комбинация клавиш Ctrl/ (или Ctrl/Break) прекращает выполнение программы пользователя.

Пример выполнения работы

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

Текст программы:

data segment

COUNT db 10 dup (0) ; счетчик количества цифр

CIFR db ‘0123456789ABCDEF’ ; таблица преобразования цифр

IN_STR db 80, ?, 82 dup (?) ; буфер ввода

OUT_STR db 0Dh, 0Ah, ?,’-‘,?, ?,’$’ ; буфер вывода

data ends

code segment

assume cs:code, ds:data

START: mov ax, data

mov ds, ax ; Загрузить сегментный адрес данных

; Ввод строки

lea dx, IN_STR

mov ah, 0ah

int 21h

; Обработка

xor ah, ah ; обнуление старшего байта AX

lea bx, IN_STR+2 ; адрес начала введённой строки

xor cx, cx

mov cl, IN_STR+1 ; количество введенных символов

ВВ: mov al, [BX] ; очередной символ строки

cmp al,’0’ ; код символа меньше чем код нуля?

jb NC ; да, не цифра

cmp al, ‘9’ ; код символа больше чем код девяти

ja NC ; да, не цифра

; символ - десятичная цифра

sub al, ‘0’ ; преобразуем ASCII код в число

mov si, ax ; индекс в массиве счетчиков COUNT

inc COUNT[si] ; увеличиваем счетчик цифр

NC: inc bx ; получить очередной символ строки

loop BB

; Вывод результатов

mov cx, 10

lea bx, CIFR ; адрес таблицы преобразования цифр в ASCII

xor si, si ; номер выводимой цифры

OUT: mov al, ‘0’

add ax, si ; ASCII код очередной цифры с номером в si

mov OUT_STR+2, al ; в буфер вывода

mov dl, COUNT[si] ; читать количество цифр с номером в si

mov al, dl

push cx ;временное сохранение cx

mov cl, 4 ; сдвиг на четыре

shr al, cl ; выделить старшую цифру

xlat ; ASCII старшей цифры в al

pop cx ; восстановление cx

mov OUT_STR+4, al ; в буфер вывода

mov al, dl ; восстановить количество цифр в al

and al,00001111b ; выделить младшую цифру

xlat ; ASCII младшей цифры в al

mov OUT_STR+5, al ; в буфер вывода

lea dx, OUT_STR ; подготовка к выводу строки

mov ah, 09h ; номер функции

int 21h ; вывод строки

inc si ; Счетчик очередной цифры

loop OUT

QUIT: mov ax, 4C00h ; Код завершения 0

int 21h ; Выход в DOS

code ends

end START

Варианты заданий

Ввести с клавиатуры строку. Сжать строку, т.е. удалить пробелы и табуляции. Вывести результаты на экран.

Ввести с клавиатуры строку. Преобразовать все малые буквы в боль­шие. Вывести результаты на экран.

Ввести с клавиатуры строку. Посчитать количество слов в строке. Определить, что является разделителем слов. Вывести результаты на экран.

Ввести с клавиатуры строку. Ввести с клавиатуры коротенькую строку - шаблон. Найти шаблон во введенной строке. Вывести на экран “ДА”, если шаблон есть и “НЕТ”, если нет.

Ввести с клавиатуры две строки. Сравнить их. Вывести на экран “ДА”, если они равны и “НЕТ”, если нет.

Ввести с клавиатуры строку. Если она длиннее некоторой заданной величины, то обрезать, если короче растянуть, вставив нужное число пробелов между словами. Вывести результаты на экран.

Ввести с клавиатуры строку, состоящую из нескольких слов. Вывести каждое слово на экран в отдельной строке, т.е. выдать слова в столбик.

Ввести с клавиатуры строку. Переставить в ней символы, поменяв местами первый символ с последним, второй с предпоследним и т.д. Вывести результаты на экран.

Ввести с клавиатуры две строки. Сравнить их. Вывести на экран номер начала второй строки в первой.

Ввести с клавиатуры строку, содержащую несколько точек. Преобразовать строку, чтобы после каждой точки был пробел, и следующая буква после точки были заглавная. Вывести результаты на экран.

Ввести с клавиатуры строку, содержащую несколько слов, разделенных пробелом. Переставить в ней слова, поменяв местами первое слово с последним, второе с предпоследним и т.д. Вывести результаты на экран.

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

Ввести с клавиатуры строку. Преобразовать все буквы в числа. Построить криптограмму (вместо букв вывести на экран соответствующие им числа).

Ввести с клавиатуры строку, состоящую из нескольких букв. Заменить каждую букву в строке на другую букву, следующую за данной буквой по алфавиту. Вывести результаты на экран.

Ввести с клавиатуры строку и строку из двух чисел. Первое число указывает начало подстроки для ввода на экран, второе количество символов из первой строки, которое необходимо вывести на экран. Ввести с клавиатуры две строки. Сравнить их. Вывести на экран номер начала первой строки во второй. Ввести с клавиатуры строку. Ввести с клавиатуры коротенькую строку - шаблон. Найти шаблон во введенной строке. Вывести на экран “ДА”, если шаблон есть и “НЕТ”, если нет.

Ввести с клавиатуры две строки. Сравнить их. Вывести на экран какая из строк больше и насколько.

Ввести с клавиатуры строку и некоторое число. Если строка длиннее заданного числа, то обрезать, если короче растянуть, вставив нужное чис­ло пробелов между словами. Вывести результаты на экран.

Ввести с клавиатуры строку, состоящую из нескольких слов. Вывести каждое слово на экран в отдельной строке, со смещением влево на одно знакоместо по отношению к предыдущей строке.

Ввести с клавиатуры строку. Посчитать в ней количество запятых. Вывести результаты на экран.

Ввести с клавиатуры две строки. Вывести на экран все символы, которые содержатся в обеих строках.

Ввести с клавиатуры строку, содержащую несколько точек. Преобразовать строку, чтобы после каждой точки был пробел, и следующая буква после точки были заглавная. Вывести результаты на экран.

Ввести с клавиатуры строку, содержащую несколько слов, разделенных пробелом. Переставить в ней слова, поменяв местами первое слово с последним, второе с предпоследним и т.д. Вывести результаты на экран.

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

Ввести с клавиатуры строку. Преобразовать все буквы в числа. Построить криптограмму (вместо букв вывести на экран соответствующие им числа).

Ввести с клавиатуры строку, состоящую из нескольких букв. Заменить каждую букву в строке на другую букву, следующую за данной буквой через заданное число символов по алфавиту. Вывести результаты на экран.

Вопросы по теме

Что такое программное прерывание?

Какие возможности работы с клавиатурой имеются у программиста?

Чем отличаются друг от друга различные функции DOS? выполняющие ввод с клавиатуры?

Как работает команда xlat?

Можно ли выдать на экран текст ‘$1.00=25,00 rub/’, используя функции DOS 09h?

Какие режимы адресации удобно использовать при работе с одномерными массивами?

Что означает выражения в поле операндов в строках примера

lea bx, IN_STR+2

mov OUT_STR+3, al?

Как выделить младшую тетраду байта?

Как выделить старшую тетраду байта?

В чем отличие команд

lea BX, STR

mov BX, offset STR?

Подпрограммы

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

Структура подпрограммы

· Описание подпрограммы в языке ассемблер имеет следующую структуру:

· <имя процедуры> proc <тип процедуры>

. . .

операторы тела подпрограммы

. . .

ret [<выражение>]

<имя процедуры> endp

<тип процедуры> - определяет тип перехода: near (близкий), far (дальний). Если тип не задан, по умолчанию принимается near. Тип перехода near показывает, что тело процедуры описано в том же сегменте, что и её вызов. Тип перехода far обеспечивает вызов процедуры из других сегментов, с другим значением регистра CS. Такие процедуры обычно используются как отдельные объектные модули или в составе библиотек.

ret [<выражение>] - выполняет возврат из процедуры в вызывающую программу. В зависимости от типа процедуры, эта команда восстанавливает из стека значение IP (ближний вызов) или CS:IP (дальний вызов). Эта команда не обязана быть последней по тексту процедуры, но является последней по порядку выполнения. Значение <выражение> указывает размер стека в байтах, восстанавливаемого при возврате из процедуры. Восстановление стека необходимо производить при передаче параметров процедуры через стек. Так как работа со стеком выполняется словами, значение <выражение> всегда должно быть кратным двум.

Допускается вложение описания подпрограммы внутрь описания другой подпрограммы.

Вызов подпрограммы

· Вызов подпрограммы выполняется командой

call [<тип вызова> ptr] <адрес процедуры>

< тип вызова > - near(word) или far(dword). Если тип не задан, по умолчанию принимается near.

< адрес процедуры > - имя или адрес процедуры. При ближнем вызове в стеке запоминается текущее значение регистра IP. При дальнем вызове в стеке запоминаются значения CS:IP.

Если тип вызова не указан явно, он определяется типом, на который указывает <адрес процедуры>, аналогично команде безусловного перехода jmp.

Пример.

Пусть в сегменте данных описаны переменные:

FADDR dd ?

NADDR dw ?

в сегменте кода описаны подпрограммы:

FPROC proc far

. . .

FPROC endp

NPROC proc

. . .

NPROC endp

Рассмотрим различные примеры команд вызова:

call FPROC ;дальний вызов п/п FPROC

call FPROC ;дальний вызов п/п FPROC

call FADDR ;дальний вызов п/п, чей адрес в FADDR

call NADDR ;ближний вызов п/п, чей адрес в NADDR

call dx ; ближний вызов п/п, чей адрес в DX

call word ptr [BX] ; косвенный ближний вызов п/п

call dword ptr [BX] ; косвенный дальний вызов п/п

Передача параметров

· Для передачи входных параметров в подпрограмму и выходных в программу существует несколько способов. Чаше всего передача параметров осуществляется через регистры или через стек.

· При передаче через регистры перед вызовом подпрограммы параметры заносятся в регистры процессора, а после возврата вызывающая программа забирает из регистров значения результатов.

· При передаче через стек, параметры перед вызовом подпрограммы заносятся в стек командой

push src

Для обращения к параметрам, хранящимся в стеке, обычно используется регистр bp:

mov bp, sp

Необходимо помнить, что поверх параметров, передаваемых в подпрограмму, в стек записываются командой call одно или два слова адреса возврата. Каждая процедура «знает» свой тип вызова (одно или два слова) и отступив от верхушки стека на +2 или на +4 читает параметры.

mov ax, bp+2 ; первый параметр при ближнем вызове

mov ax, bp+4 ; первый параметр при дальнем вызове

Сохранение регистров

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

pusha

popa

сохраняющие в стеке, а после выполнения подпрограммы, вос­ста­нав­ли­ва­ющие значения всех регистров.

Пример выполнения работы

· Разработать подпрограмму, которая удаляет, начиная с заданной позиции строки, указанного числа символов. Написать программу, которая вводит с клавиатуры строку, позицию и длину удаляемой части строки, удаляет указанную часть и выводит строку.

Текст программы:

data segment

MESS1 db 0dh,0ah, "Введите строку:", 0dh,0ah, "$"

MESS2 db 0dh,0ah, "Введите позицию:", 0dh,0ah, "$"

MESS3 db 0dh,0ah, "Введите число удаляемых символов:", 0dh, 0ah, "$"

MESS4 db 0dh,0ah, "Строка после удаления:", 0dh,0ah, "$"

S_BUFLEN db 80 ; Максимальная длина строки

S_FACTLEN db ? ; Фактическая длина строки

S_INPBUF db 80 dup(?) ; Введённая строка

N_BUFLEN db 3 ; Максимальная длина числа при вводе

N_FACTLEN db ? ; Фактическая длина числа

N_INPBUF db 3 dup(?) ; Введённое число

POSDEL dw ? ; Позиция начала удаления

LENDEL dw ? ; Число удаляемых символов

data ends

code segment

assume cs:code, ds:data

START: mov ax, data

mov ds,ax

; Ввод строки

LOP: lea DX, MESS1

mov ah, 09h

int 21h ;приглашение к вводу строки

lea DX, S_BUFLEN

mov ah, 0Ah

int 21h ; ввод строки

mov AL, S_FACTLEN

cmp al, 0 ; строка пустая?

ja LLL0 ; нет продолжать

jmp quit ; закончить работу

LLL0: lea bx, S_INPBUF ; получить адрес начала строки

cbw ; получить длину в слове

add bx, ax ; адрес конца строки

mov byte ptr [bx], "$" ; записать признак конца строки

; Ввод позиции удаления

LLL1: lea dx, MESS2

mov ah, 09h

int 21h ;Приглашение к вводу позиции удаления

lea dx, N_BUFLEN

mov ah, 0Ah

int 21h ; ввод позиции удаления

call VAL ; вызов процедуры перевода в число

jc LLL1 ; ошибка, повторить ввод

cmp al, 0 ; ноль?

jz LLL1 ; ошибка, повторить ввод

cmp AL, S_FACTLEN ; превышает длину строки?

jg LLL1 ; ошибка, повторить ввод

cbw ; расширить до слова

mov POSDEL, AX ; запомнить позицию удаления

; Ввод длины удаляемой части

LLL2: lea dx, MESS3

mov AH, 09h ; приглашение к вводу числа

int 21h ; удаляемых символов

lea dx, N_BUFLEN

mov ah, 0ah

int 21h ; ввод числа удаляемых символов

call VAL ; вызов процедуры перевода в число

jc LLL2 ; ошибка, повторить ввод

cbw ; расширить до слова

mov LENDEL, AX ; запомнить число удаляемых символов

;Занести в стек параметры и вызвать подпрограмму удаления

lea bx, S_INPBUF

mov al, S_FACTLEN ; дополняем до слова

cbw

push ax ; 4-й параметр длина строки

push LENDEL ; 3й параметр число удаляемых симв.

push POSDEL ; 2-й параметр позиция удаления

push bx ; 1й параметр адрес строки

call DELSUB ; вызов подпрограммы

; Вывод результата

lea dx, MESS4

mov ah, 09h

int 21h ; вывод заголовка вывода

lea bx, S_FACTLEN

xor cx, cx

mov cl, S_FACTLEN

LLL3: inc bx

cmp byte ptr [bx], 0

loopne LLL3 ; повторять до конца строки или первого нуля

LLL4: mov byte ptr [bx], "$"

lea DX, S_INPBUF

mov ah, 09h

int 21h

jmp LOP

QUIT: mov ax, 4c00h

int 21h

; Функция получения числа из его строкового представления

; Схема преобразования десятичного числа а2а1а0 в 16-ричную СС по ;схеме Горнера - N16=(a2*A+a1)*A+a0 , где A десятичное основание

VAL proc near

push bx ; сохранение

push cx ; регистров

push dx ; в стеке

lea bx, N_INPBUF ; адрес начала числа

mov cl, N_FACTLEN ; фактическая длина числа

xor ch, ch ; расширить до сх

xor ax, ax

mov dl, 10 ; основание системы счисления

VAL1: imul dl ; умножаем на основание

mov dh, [bx]

sub dh, "0" ; преобразуем его в цифру

add al, DH ; добавляем к результату

inc bx ; на следующий символ

loop VAL1

cmp ax, 255

clc ;сброс флага CF

jle VAL2

stc ; если результат больше 255 установить флаг CF=1

VAL2: pop dx ; восстановить

pop cx ; регистры

pop bx ; из стека

ret

VAL endp

; Подпрограмма удаления подстроки

; Параметры:

;адрес строки BP+2, позиция удаления BP+4, число удаляемых символов ; BP+6, длина строки BP+8

DELSUB proc near

push bp

mov bp, SP

push es

push ax

push si

push di

push cx

mov ax, ds

mov es, ax

mov di, [bp+4] ; адрес начала строки

add di, [bp+6] ; адрес позиции удаления +1

dec di ; адрес позиции удаления

mov si, di

add si, [bp+8] ; адрес остающейся части строки

mov cx, [bp+4] ; адрес начала строки

add cx, [bp+10] ; адрес конца строки + "$"

sub cx, si ; число перемещаемых символов - 1

inc cx ; число перемещаемых символов

cld ; продвигаться от начала к концу

rep movsb ; переслать (cx) символов

pop bp

pop cx ; восстановить

pop di ; регистры

pop si ; из

pop ax ;стека

pop es

ret 8 ; вернуться с очищением стека

DELSUB endp

code ends

end START

Варианты заданий

· В приведённых ниже вариантах заданий способ передачи параметров в процедуру выбирать произвольно. Зациклить программу по вводу строки, а признаком окончания работы считать ввод пустой строки.

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

Разработать две подпрограммы, одна из которых преобразует любую заданную букву в заглавную (в том числе для русских букв), а другая преобразует букву в строчную. Разработать программу, которая вводит с клавиатуры строку и замещает первые буквы всех слов заглавными, а остальные строчными буквами.

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

Разработать две подпрограммы, одна из которых сравнивает две строки по лексикографическому порядку, а другая обменивает значения двух строк. Разработать программу, которая вводит с клавиатуры несколько строк (конец ввода пустая строка) и сортирует их в лексикографическом порядке.

Разработать подпрограмму, которая разбивает заданную строку на две части: первое слов (до первого пробела) и остальная часть строки (пробелы в начале строки убираются). Разработать программу, которая вводит с клавиатуры строку и выводит каждое слово с новой строки.

Разработать подпрограмму, которая переставляет символы заданной строки в обратном порядке. Разработать программу, которая вводит с клавиатуры строку и переставляет в обратном порядке символы в каждом слове.

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

Разработать подпрограмму, которая подсчитывает, сколько раз заданный символ встречается в строке. Разработать программу, которая вводит с клавиатуры строку и число N и выдаёт список символов, которые встречаются в строке не менее N раз.

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

Разработать подпрограмму, которая преобразует заданное шестнадцатеричное число в десятичную систему. Разработать программу, которая вводит с клавиатуры строку шестнадцатеричных цифр и выводит на экран её эквивалент в десятичной системе. Если строка не является числом, то сообщает об этом.

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

Разработать подпрограмму, которая разбивает заданную строку на слова (слово считается от пробела до пробела, но в состав слова не входят). Разработать программу, которая вводит с клавиатуры строку и выводит каждое слово с новой строки.

Разработать две подпрограммы, одна из которых преобразует любую заданную букву в заглавную (в том числе для русских букв), а другая преобразует букву в строчную. Разработать программу, которая вводит с клавиатуры строку и заменяет первые буквы после точки на заглавные, а остальные на прописные.

Разработать подпрограмму, которая определяет, содержится ли одна строка в другой и если да то с какой позиции. Разработать программу, которая вводит с клавиатуры две строки и определяет содержится ли вторая строка в первой и с какой позиции.

Разработать подпрограмму, которая каждой букве ставит в соответствие число равное её порядковому номеру в алфавите. Разработать программу, которая вводит с клавиатуры строку и выводит через пробел числа, кодирующие введённую строку символов.

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

Разработать две подпрограммы, одна из которых преобразует любую заданную букву в заглавную (в том числе для русских букв), а другая преобразует букву в строчную. Разработать программу, которая вводит с клавиатуры строку и замещает первые буквы всех слов заглавными, а остальные строчными буквами.

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

Разработать две подпрограммы, одна из которых сравнивает две строки по лексикографическому порядку, а другая обменивает значения двух строк. Разработать программу, которая вводит с клавиатуры несколько строк (конец ввода пустая строка) и сортирует их в лексикографическом порядке.

Разработать подпрограмму, которая разбивает заданную строку на две части: первое слов (до первого пробела) и остальная часть строки (пробелы в начале строки убираются). Разработать программу, которая вводит с клавиатуры строку и выводит каждое слово с новой строки.

Разработать подпрограмму, которая переставляет символы заданной строки в обратном порядке. Разработать программу, которая вводит с клавиатуры строку и переставляет в обратном порядке символы в каждом слове.

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

Разработать подпрограмму, которая подсчитывает, сколько раз заданный символ встречается в строке. Разработать программу, которая вводит с клавиатуры строку и число N и выдаёт список символов, которые встречаются в строке не менее N раз.

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

Разработать подпрограмму, которая преобразует заданное шестнадцатеричное число в десятичную систему. Разработать программу, которая вводит с клавиатуры строку шестнадцатеричных цифр и выводит на экран её эквивалент в десятичной системе. Если строка не является числом, то сообщает об этом.

Вопросы по теме

Что такое “ближние” и “дальние” подпрограммы?

Как определить “ближний” или “дальний” вариант команды call использован в программе?

Какие способы используются для передачи параметров в подпрограммы?

Может ли массив быть параметром подпрограммы?

Можно ли использовать для чтения из стека параметров регистр sp вместо bp?

Что означает операнд команды ret?

Какой последовательностью команд можно заменить команду “ret 8”?

Обработка прерываний

· В MS-DOS различают аппаратные и программные прерывания. Первые возникают по запросу периферийных устройств. Вторые позволяют использовать предоставляемые системой MS-DOS и BIOS большой набор подпрограмм, выполняющих различные полезные действия и оформленные как программные прерывания. В некоторых случаях стандартные программы обработки как аппаратных, так и программных прерываний могут не удовлетворять программиста. Поэтому появляется необходимость заменить существующую программу обработки прерывания иной или внести новые функции в уже имеющуюся программу.

Обработка прерывания

Рассмотрим подробно действия, которые называются обработкой прерывания. Эти действия выполняются независимо от того вызвано ли прерывание аппаратно или программно. При получении сигнала на прерывание (при аппаратном прерывании от программируемого контроллера прерываний, при программном командой процессора int) процессор содержимое CS, IP и регистра флагов сохраняет в стеке. В CS и IP помещается адрес подпрограммы обработки прерывания, которая и выполняется, после чего восстанавливаются из стека содержимое CS, IP и регистра флагов, и процессор продолжает выполнение программы.

Двойное слово, в котором хранится адрес подпрограммы обработки прерывания, называется вектором прерывания. Всего допустимо иметь 256 различных векторов прерываний. Для хранения векторов прерываний в DOS выделен первый килобайт памяти. Адрес вектора прерывания с номером N вычисляется как N*4. В младшем слове хранится значение IP, а в старшем CS.

Пример. Определить адрес прерывания 21h. Получим 21h * 4h =84h. Просмотр содержимого четырёх байтов, начиная с 0084h в сегменте 0000h

Показывает, что там храниться число

0000:0084 0DDE:048B,

где 0DDE – адрес сегмент, а 048B – адрес смещения подпрограммы обработки прерывания с номером 21h.

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

Каждая подпрограмма обработки прерывания, в отличие от обычно подпрограммы, завершается командой iret, которая похожа на команду ret, но восстанавливает из стека кроме CS и IP ещё и регистр флагов.

Наши рекомендации