Jazik_Assemblera_dlja_IBM_PC_i_programmir
.pdfэлемента по имени CUSTHAN для файлового номера, б) создание файла, в) записи файла из области CUSTOUT (128 байт) и г) закрытия файла. Обеспечьте проверку на ошибки.
17.4.Для файла (п.17.3) напишите команды а) открытия файла и б) чтения файла в область CUSTIN. Обеспечьте контроль ошибок.
17.5.В каких случаях необходимо закрывать файл, который был открыт только для чтения ?
17.6.Измените программу на рис.17.4 так, чтобы пользователь мог вводить с клавиатуры имя файла, который необходимо выдать на экран. Обеспечьте возможность любого числа запросов и завершение программы только по пустому запросу, т.е. простому нажатию клавиши Return.
ГЛАВА 18 Дисковая память IV: Функции BIOS
__________________________________________________________________________
Ц е л ь: Показать основные требования к программированию функций BIOS для создания и чтения дисковых файлов.
ВВЕДЕНИЕ
________________________________________________________________
Для дисковых операций можно программировать непосредственно на уровне BIOS, хотя BIOS и не обеспечивает автоматически использование оглавления или блокирование/деблокирование записей. Дисковая операция BIOS INT 13H рассматривает все "записи", как имеющие размер сектора, а адресацию диска осуществляет в терминах действительных номера дорожки и номера сектора.
Для дисковых операций чтения, записи и верификации необходима инициализация следующих регистров:
AH Определяет тип операции: чтение, запись, верификация или форматирование.
AL Определяет число секторов.
CH Определяет номер дорожки.
CL Определяет номер начального сектора.
DH Номер головки (стороны) : 0 или 1 для дискеты. DL Номер дисковода: 0=A, 1=B и т.д.
ES:BX Адрес буфера ввода/вывода в области данных (за исключением операции верификации).
ДИСКОВЫЕ ОПЕРАЦИИ В BIOS
________________________________________________________________
Для указания необходимой дисковой операции необходимо перед INT 13H загрузить в регистр AH соответствующий код.
AH = 00: Сброс системы контролера дисковода
---------------------------------------------
Данная операция осуществляет полный сброс контролера дисковода и требует для выполнения INT 13H загрузку в регистр AH значение шест.00. Операция используется в случаях, когда после других дисковых операций возвращается код серьезной ошибки.
AH = 01: Определить состояние дисковода
-----------------------------------------
Данная операция возвращает в регистре AL состояние дисковода после
последней операции ввода/вывода (см.Байт состояния в следующем разделе). Операция требует только загрузки значения 01 в регистр AH.
AH = 02: Чтение секторов
--------------------------
Данная операция выполняет чтение в память определенного числа секторов на одной дорожке. Число секторов обычно 1, 8 или 9. Адрес памяти
для области ввода должен быть |
загружен в регистр BX, причем следует |
||
помнить, что реальный адрес зависит от содержимого регистра EX, так как в |
|||
данном случае используется регистровая пара ES:BX. В следующем |
примере |
||
выполняется чтение |
сектора |
в область INSECT, которая должна |
быть |
достаточно большой, |
чтобы вместить все данные: |
|
|
MOV |
AH,02 |
;Запрос на чтение |
|
MOV |
AL,01 |
; один сектор |
|
LEA |
BX,INSERT |
;Буфер ввода в ES:BX |
|
MOV |
CH,05 |
;Дорожка 05 |
|
MOV |
CL,03 |
;Сектор 03 |
|
MOV |
DH,00 |
;Сторона (головка) 00 |
|
MOV |
DL,01 |
;Дисковод 01 (B) |
|
INT |
13H |
;Вызов BIOS |
|
Число действительно прочитанных секторов возвращается в регистре AL. Регистры DS, BX, CX и DX сохраняют свои значения.
В большинстве случаев программа указывает только один сектор или все сектора на дорожке. Для последовательного чтения секторов программа должна увеличивать содержимое регистров CH и CL. Заметьте, что когда номер
сектора достигает максимального значения, его необходимо сбросить в 01, а |
|
номер дорожки увеличить на 1 или изменить сторону 0 на 1 |
(для |
двухсторонних дискет). |
|
AH = 03: Запись секторов
--------------------------
Данная операция записывает данные из указанной области памяти (обычно 512 байтов или кратное 512) в один или несколько определенных секторов. Управляющая информация загружается в регистры аналогично операции чтения диска (код 02). Операция записи возвращает в регистре AL число секторов, которые действительно были записаны. Регистры DX, BX, CX и DX сохраняют свои значения.
AH = 04: Верификация сектора
------------------------------
Данная операция проверяет, может ли быть найден указанный сектор, и выполняет своего рода контроль на четность. Операцию можно использовать после записи (код 03) для гарантии более надежного вывода, на что потребуется дополнительное время ввода/вывода. Значения регистров устанавливаются аналогично операции записи (код 03), за исключением регистровой пары ES:BX - их инициализация не требуется. Операция возвращает в регистре AL число обработанных секторов. Регистры DX, BX, CX и DX сохраняют свои значения.
AH = 05: Форматирование дорожек
---------------------------------
Данная операция используется для форматирования определенного числа дорожек в соответствии с одним из четырех размеров (стандарт для системы PC - 512). Операции чтения и записи для локализации требуемого сектора требуют информацию о формате. Для форматирования регистровая пара ES:BX должна содержать адрес, который указывает на группу адресных полей для дорожки. Для каждого сектора на дорожке должен быть четырехбайтовый элемент в виде T/H/S|B, где
T номер дорожки,
H номер головки,
S номер сектора,
B число байт на секторе, (00-128, |
01-256, |
02-512, 03-1024). |
||||
Например, для форматирования 03 |
дорожки, на |
стороне |
00 |
и |
512 |
байтов |
на сектор, первый элемент должен иметь значение |
шест.03000102 |
и |
за ним |
|||
должны быть описаны элементы для |
остальных |
секторов |
на |
|
дорожке. |
|
Техническое руководство по AT содержит ряд дополнительных операций |
BIOS. |
|||||
БАЙТ СОСТОЯНИЯ
________________________________________________________________
Для всех рассмотренных выше операций (02, 03, 04 и 05) в случае нормального завершения флаг CF и регистр AH содержит 0. В случае ошибки флаг CF устанавливается в 1, а регистр AH содержит код состояния, идентифицирующий причину ошибки. Код состояния аналогичен значению в регистре AL после выполнения операции 01.
AH |
Причина |
0000 0001 Ошибка команды для дискеты
0000 0010 Не найден адресный маркер на диске
0000 0011 Попытка записи на защищенный диск
0000 0100 Не найден сектор
0000 1000 Выход за границы DMA (памяти прямого доступа) 0000 1001 Попытка доступа через границу 64K
0001 0000 Чтение сбойный участок на диске
0010 0000 Ошибка контролера дисковода
0100 0000 Ошибка установки (поиска)
1000 0000 Ошибка оборудования
В случае возникновения ошибки, обычным действием является сброс диска (AH=00) и троекратное повторение операции. Если таким образом ошибка не устраняется, то на экран выводится соответствующее сообщение и пользователь может сменить дискету.
ПРОГРАММА: ИСПОЛЬЗОВАНИЕ BIOS ДЛЯ ЧТЕНИЯ СЕКТОРОВ
________________________________________________________________
__________________________________________________________________________
TITLE |
BIOREAD |
(COM) Чтение дискового сектора через BIOS |
||
CODESG |
SEGMENT |
PARA 'Code' |
|
|
|
ASSUME |
CS:CODESG,DS:CODESG,SS:CODESG,ES:CODESG |
||
BEGIN |
ORG |
100H |
|
|
JMP |
MAIN |
|
||
; --------------------------------------------------------- |
DB |
512 DUP(' ') |
;Область ввода |
|
RECDIN |
||||
ENDCDE |
DB |
00 |
;Начало (дорожка/сектор) |
|
CURADR |
DW |
0304H |
||
ENDADR |
DW |
0501H |
;Конец (дорожка/сектор) |
|
READMSG |
DB |
'*** Read error ***$' |
||
SIDE |
DB |
00 |
|
|
; --------------------------------------------------------- |
PROC |
NEAR |
|
|
MAIN |
;Функция прокрутки экрана |
|||
A20LOOP: |
MOV |
AX,0600H |
||
CALL |
Q10SCR |
;Очистить экран |
||
|
||||
|
CALL |
Q20CURS |
;Установить курсор |
|
|
CALL |
C10ADDR |
;Определить адрес на диске |
|
|
MOV |
CX,CURADR |
|
|
MOV |
DX,ENDADR |
;Последний сектор? |
|
CMP |
CX,DX |
|
|
JE |
A90 |
; да - выйти |
|
CALL |
F10READ |
;Получить дисковую запись |
|
CMP |
ENDCDE,00 |
;Ошибка чтения? |
|
JNZ |
A90 |
; да - выйти |
|
CALL |
G10DISP |
;Вывести сектор на экран |
A90 |
JMP |
A20LOOP |
;Повторить |
RET |
|
;Завершить программу |
|
MAIN |
ENDP |
|
|
;Вычислить следующий адрес на диске:
; |
|
---------------------------------- |
||
C10ADDR PROC |
NEAR |
;Последняя дорожка/сектор |
||
|
MOV |
CX,CURADR |
||
|
CMP |
CL,10 |
;Последний сектор? |
|
|
JNE |
C90 |
; нет - выйти |
|
|
CMP |
SIDE,00 |
;Обойти, если сторона = 0 |
|
|
JE |
C20 |
;Увеличить номер дорожки |
|
C20: |
INC |
CH |
||
XOR |
SIDE,01 |
;Сменить сторону |
||
|
||||
|
MOV |
CL,01 |
;Установить сектор = 1 |
|
C90: |
MOV |
CURADR,CX |
|
|
RET |
|
|
||
C10ADDR |
ENDP |
|
|
|
;Чтение дискового сектора:
; |
------------------------ |
|
F10READ PROC |
NEAR |
;Число секторов |
MOV |
AL,01 |
|
MOV |
AH,02 |
;Функция чтения |
LEA |
BX,RECDIN |
;Адрес буфера |
MOV |
CX,CURADR |
;Дорожка/сектор |
MOV |
DH,SIDE |
;Сторона |
MOV |
DL,01 |
;Дисковод B |
INT |
13H |
;Выполнить ввод |
CMP |
AH,00 |
;Ошибка чтения? |
JZ |
F90 |
; нет - выйти |
MOV |
ENDCDE,01 |
; да - |
CALL |
X10ERR |
; ошибка чтения |
F90: |
CURADR |
;Увеличить номер сектора |
INC |
||
RET |
|
|
F10READ ENDP |
|
|
;Вывод сектора на экран:
; |
---------------------- |
|
G10DISP PROC |
NEAR |
;Функция вывода на экран |
MOV |
AH,40H |
|
MOV |
BX,01 |
;Номер устройства |
MOV |
CX,512 |
;Длина |
LEA |
DX,RECDIN |
|
INT |
21H |
|
RET |
|
|
G10DISP ENDP |
|
|
;Очистка экрана:
; |
PROC |
-------------- |
|
Q10SCR |
NEAR |
;Полный экран |
|
|
MOV |
AX,0600H |
|
|
MOV |
BH,1EH |
;Установить цвет |
|
MOV |
CX,0000 |
;Функция прокрутки |
|
MOV |
DX,184FH |
|
|
INT |
10H |
|
Q10SCR |
RET |
|
|
ENDP |
|
|
;Установка курсора:
; |
----------------- |
|
Q20CURS PROC |
NEAR |
;Функция установки |
MOV |
AH,02 |
|
MOV |
BH,00 |
; курсора |
MOV |
DX,0000 |
|
INT |
10H |
|
RET |
|
|
Q20CURS ENDP |
|
|
;Вывод сообщения об ошибке на диске:
; |
PROC |
---------------------------------- |
|
X10ERR |
NEAR |
;Функция вывода на экран |
|
|
MOV |
AH,40H |
|
|
MOV |
BH,01 |
;Номер устройства |
|
MOV |
CX,18 |
;Длина сообщения |
|
LEA |
DX,READMSG |
|
|
INT |
21H |
|
X10ERR |
RET |
|
|
ENDP |
|
|
|
CODESG |
ENDS |
BEGIN |
|
|
END |
|
|
__________________________________________________________________________
Рис.18.1. Использование BIOS для чтения дискового файла.
Рассмотрим программу, приведенную на рис.18.1, в которой используется команда BIOS INT 13H для чтения секторов диска. Программа базируется на примере, приведенном на рис.16.3, со следующими изменениями:
1.Отсутствует описание FCB и подпрограмма открытия.
2.Программа расчитывает каждый дисковый адрес. После каждого чтения происходит увеличение номера сектора. При достижении номера сектора 10 процедура C10ADDR сбрасывает это значение в 01. Если номер стороны = 1, программа увеличивает номер дорожки; затем меняется номер стороны: 0 на 1 и 1 на 0.
3.Область CURADR содержит начальные значения номеров дорожки и сектора (их программа увеличивает), а область ENDADR - конечные значения. Один из способов улучшения программы - предоставить
пользователю возможность указать начальные и конечные номера |
дорожки |
|
и сектора с помощью соответствующего запроса. |
|
|
Выполните данную программу под управлением |
отладчика |
DEBUG. |
Проделайте трассировку команд, которые инициализируют сегментные регистры, и установите начальный и конечный номера секторов для файловой таблицы FAT (расположение таблицы FAT различно в разных версиях операционной системы). Используя команду G (до) для выполнения ввода с диска и проверки считанного содержимого таблицы FAT и элементов оглавления.
В качестве альтернативы отладчику DEBUG можно преобразовать ASCII-символы в области ввода в их шест. эквиваленты и выдать на экран эти значения, как это делает отладчик DEBUG (см. программу на рис.14.5). Таким образом можно проверить содержимое любого сектора (в том числе "спрятанного"), а также предоставить пользователю возможность внести
изменения и записать измененный сектор на диск. |
|
записи на |
Следует помнить, что при создании файла DOS может вносить |
||
любые доступные сектора, которые не обязательно будут смежными |
на диске. |
|
Следовательно, с помощью команды BIOS INT 13H |
нельзя |
выполнить |
последовательное чтение файла. |
|
|
ОСНОВНЫЕ ПОЛОЖЕНИЯ НА ПАМЯТЬ
________________________________________________________________
- Команда BIOS INT 13H обеспечивает прямой доступ к дорожкам и
секторам диска.
-Команда BIOS INT 13H не поддерживает операции с оглавлением, обнаружение конца файла, блокирование и деблокирование записей.
-Верификация сектора выполняет элементарную проверку записанных данных, что приводит к увеличению времени обработки.
-Проверяйте байт состояния после каждой дисковой операции через
BIOS.
ВОПРОСЫ ДЛЯ САМОПРОВЕРКИ
________________________________________________________________
18.1.Напишите команды для сброса дискового контролера.
18.2.Напишите команды для чтения байта состояния дискеты.
18.3.Напишите команды для BIOS INT 13H, выполняющие чтение одного сектора в область памяти INDISK, с дисковода A, головки 0, дорожки 6 и сектора 3.
18.4.Напишите команды для BIOS INT 13H, выполняющие запись трех секторов из области памяти OUTDISK, на дисковод B, головку 0, дорожку 8 и сектор 1.
18.5.При записи данных в вопросе 18.4, как можно распознать попытку записи на защищенный диск?
18.6.На основе вопроса 18.4 напишите команды контроля записи (операция верификации).
ГЛАВА 19 Печать
__________________________________________________________________________
Ц е л ь: Описать возможности программ на языке ассемблера для вывода информации на печатающее устройство (принтер).
ВВЕДЕНИЕ
________________________________________________________________
Вывод на принтер несколько проще операций с экраном и диском. Для печати существует несколько операций, выполняющихся через DOS INT 21H и BIOS INT 17H. Команды, посылаемые на принтер, включают коды "конец страницы", "конец строки" и "возврат каретки".
Принтеры классифицируются по качеству печати. Матричный принтер формирует символы в виде матрицы точек и обеспечивает нормальный, узкий и широкий форматы символов. Более совершенные матричные принтеры обеспечивают точечную графику, наклонный шрифт, жирную печать и двойную плотность, а также могут печатать, например, символы игральных карт и другие алфавитно-цифровые символы. Высококачественные печатающие устройства ограничены набором символов на сменной "ромашке" или барабане, но обеспечивают отличное качество печати и большое разнообразие принтеров. Многие высококачественные принтеры обеспечивают печать 10, 12 или 15 символов на дюйм, а также пропорциональное расположение пробелов, подчеркивание, теневую и полужирную печать. Лазерные принтеры обладают преимуществами как для матричной графики, так и для качественной печати текстов.
Другая классификация печатающих устройств связана с интерфейсами. Компьютеры IBM PC имеют параллельный интерфейс, позволяющий передавать
одновременно восемь битов из процессора на принтер. Кроме того, существует последовательный интерфейс, который выполняет побитовую передачу данных.
Многие принтеры имеют буфер памяти, объемом в несколько тысяч байтов. Принтеры также могут принимать биты контроля на четность (нечетность). Принтеры должны "понимать" специальные сигналы из процессора, например, для прогона листа, перевода строки или горизонтальной табуляции. В свою очередь, процессор должен "понимать" сигналы от принтера, указывающие на конец бумаги или состояние "занято".
К сожалению многие типы принтеров по разному реагируют на сигналы процессора и одной из наиболее сложных проблем для программистов - обеспечить соответствие собственных программ имеющимся печатающим устройством.
СИМВОЛЫ УПРАВЛЕНИЯ ПЕЧАТЬЮ
________________________________________________________________
Стандартными символами управления печатью являются следующие:
Десятичн. |
Шест. |
Назначение |
08 |
08 |
Возврат на шаг |
0909 Горизонтальная табуляция
100A Перевод строки
110B Вертикальная табуляция
120C Прогон страницы
130D Возврат каретки
Г о р и з о |
н т |
а л ь н а я |
т а б у л я ц |
и я. |
Горизонтальная |
табуляция (шест. |
09) |
возможна только |
на принтерах, |
имеющих соответствующее |
|
обеспечение, иначе символы табуляции игнорируются. В последнем случае можно имитировать табуляцию выводом соответствующего числа пробелов.
П е р е в о д с т р о к и. Символ перевода строки (шест.OA) используется для прогона листа на один интервал. Соответственно для печати через два интервала используется два символа перевода строки.
П р о г о н с т р а н и ц ы. Установка бумаги |
после включения |
|
принтера определяет начальную позицию печати страницы. |
Длина страницы по |
|
умолчанию составляет 11 дюймов. |
Ни процессор, ни принтер автоматически не |
|
определяют конец страницы. Если |
ваша программа продолжает печатать после |
|
конца страницы, то произойдет переход через межстраничную перфорацию на на чало следующей страницы. Для управления страницами необходимо подсчитывать число напечатанных строк и при достижении максимального значения (например, 55 строк) выдать код прогона страницы (шест.0C) и, затем, сбросить счетчик строк в 0 или 1.
Вконце печати необходимо выдать символ "перевода строки" или
"прогона страницы" для вывода на печать данные последней строки, находящиеся в буфере печатающего устройства. Использование последнего символа "прогон страницы" позволяет установить напечатанный последний лист в положение для отрыва.
ФУНКЦИИ ПЕЧАТИ В РАСШИРЕННОЙ ВЕРСИИ DOS
________________________________________________________________
В операционной системе DOS 2.0 имеются файловые указатели, которые были показаны в главах по управлению экраном дисплея и дисковой печати. Для вывода на печатающее устройство используется функция DOS шест.40 и стандартный файловый номер 04. Следующий пример демонстрирует печать 25 символов из области HEADG:
HEADG |
DB 'Industrial Bicycle Mfrs', 0DH, 0AH |
|
... |
MOV |
AH,40H |
;Запрос печати |
MOV |
BX,04 |
;Файловый номер принтера |
MOV |
CX,25 |
;25 символов |
LEA |
DX,HEADG |
;Область вывода |
INT |
21H |
;Вызов DOS |
В случае ошибки операция |
устанавливает флаг CF и возвращает код |
|
ошибки в регистре AX.
ПРОГРАММА: ПОСТРАНИЧНАЯ ПЕЧАТЬ С ЗАГОЛОВКАМИ
________________________________________________________________
__________________________________________________________________________
TITLE |
PRTNAME |
(COM) Ввод и печать имен |
|
||
CODESG |
SEGMENT |
PARA PUBLIC 'CODE' |
|
||
|
ASSUME |
CS:CODESG,DS:CODESG,SS:CODESG,ES:CODESG |
|||
BEGIN: |
ORG |
100H |
|
|
|
JMP |
SHORT MAIN |
|
|
||
; ----------------------------------------------------- |
|
BYTE |
;Список параметров |
||
NAMEPAR LABEL |
|||||
MAXNLEN DB |
20 |
; максимальная длина имени |
|||
NAMELEN DB |
? |
; длина введенного имени |
|||
NAMEFLD DB |
20 DUP(' ') |
; введенное имя |
|||
HEADG |
DB |
|
;Строка заголовка: |
||
'List of Employee Names |
Page ' |
||||
PAGECTR |
DB |
'01',0AH,0AH |
;Перевод страницы |
||
FFEED |
DB |
0CH |
|||
LFEED |
DB |
0AH |
;Перевод строки |
||
LINECTR |
DB |
01 |
|
|
|
PROMPT |
DB |
'Name? ' |
|
|
|
; ----------------------------------------------------- |
PROC |
NEAR |
|
|
|
MAIN |
;Очистить экран |
||||
|
CALL |
Q10CLR |
|||
A2LOOP: |
CALL |
M10PAGE |
;Установка номера страницы |
||
MOV |
DX,0000 |
;Установить курсор в 00,00 |
|||
|
|||||
|
CALL |
Q20CURS |
;Ввести имя |
|
|
|
CALL |
D10INPT |
|
||
|
CALL |
Q10CLR |
;Имя введено? |
||
|
CMP |
NAMELEN,00 |
|||
|
JE |
A30 |
; если нет - выйти, |
||
|
CALL |
E10PRNT |
; если да - подготовить |
||
|
JMP |
A20LOOP |
; печать |
|
|
A30: |
|
|
|||
MOV |
CX,01 |
;Конец работы: |
|||
|
|||||
|
LEA |
DX,FFEED |
; один символ |
||
|
CALL |
P10OUT |
; для прогона страницы, |
||
MAIN |
RET |
|
; возврат в DOS |
||
ENDP |
|
|
|
||
;Ввод имени с клавиатуры:
; |
----------------------- |
|
D10INPT PROC |
NEAR |
;Функция |
MOV |
AH,40H |
|
MOV |
BX,01 |
; вывода на экран |
MOV |
CX,05 |
; 5 символов |
LEA |
DX,PROMPT |
;Вызов DOS |
INT |
21H |
|
MOV |
AH,0AH |
;Функция ввода с клавиатуры |
LEA |
DX,NAMEPAR |
;Вызов DOS |
INT |
21H |
|
RET |
|
|
D10INPT ENDP
;Подготовка для печати:
; |
|
---------------------- |
|
E10PRNT PROC |
NEAR |
;Конец страницы? |
|
|
CMP |
LINECTR,60 |
|
|
JB |
E20 |
; нет - обойти |
E20: |
CALL |
M10PAGE |
; да - печатать заголовок |
MOV |
CH,00 |
;Число символов в имени |
|
|
MOV |
CL,NAMELEN |
|
|
LEA |
DX,NAMEFLD |
;Адрес имени |
|
CALL |
P10OUT |
;Печатать имя |
|
MOV |
CX,01 |
;Один |
|
LEA |
DX,LFEED |
; перевод строки |
|
CALL |
P10OUT |
;Увеличить счетчик строк |
|
INC |
LINECTR |
|
E10PRNT ENDP
;Подпрограмма печати заголовка:
; |
|
----------------------------- |
|||
M10PAGE PROC |
NEAR |
|
|
||
|
CMP |
WORD PTR PAGECTR,3130H ;Первая страница? |
|||
|
JE |
M30 |
; да - обойти |
||
|
MOV |
CX,01 |
; |
|
|
|
LEA |
DX,FFEED |
; нет -- |
||
|
CALL |
P10OUT |
; |
перевести страницу, |
|
M30: |
MOV |
LINECTR,03 |
; |
установить счетчик строк |
|
MOV |
CX,36 |
;Длина заголовка |
|||
|
|||||
M40: |
LEA |
DX,HEADG |
;Адрес заголовка |
||
CALL |
P10OUT |
|
|
||
|
;Увеличить счетчик страниц |
||||
|
INC |
PAGECTR+1 |
|||
|
CMP |
PAGECTR+1,3AH |
;Номер страницы = шест.xx3A? |
||
|
JNE |
M50 |
; нет - обойти, |
||
|
MOV |
PAGECTR+1,30H |
; да - перевести в ASCII |
||
M50: |
INC |
PAGECTR |
|
|
|
RET |
|
|
|
||
M10PAGE |
ENDP |
|
|
|
|
;Подпрограмма печати:
; |
PROC |
------------------- |
|
P10OUT |
NEAR |
;CX и DX установлены |
|
|
MOV |
AH,40H |
;Функция печати |
|
MOV |
BX,04 |
;Номер устройства |
|
INT |
21H |
;Вызов DOS |
P10OUT |
RET |
|
|
ENDP |
|
|
|
;Очистка экрана:
; |
PROC |
-------------- |
|
Q10CLR |
NEAR |
;Функция прокрутки |
|
|
MOV |
AX,0600H |
|
|
MOV |
BH,60H |
;Цвет (07 для ч/б) |
|
MOV |
CX,0000 |
;От 00,00 |
|
MOV |
DX,184FH |
; до 24,79 |
|
INT |
10H |
;Вызов BIOS |
Q10CLR |
RET |
|
|
ENDP |
|
|
;Установка курсора (строка/столбец):
; |
NEAR---------------------------------- |
;DX уже установлен |
Q20CURS PROC |
||
MOV |
AH,02 |
;Функция установки курсора |
MOV |
BH,00 |
;Страница № 0 |
INT |
10H |
;Вызов BIOS |
RET |
|
|
Q20CURS ENDP |
|
|
CODESG ENDS |
|
|
END BEGIN
__________________________________________________________________________
Рис.19.1. Постраничная печать с заголовком.
Программа, приведенная на рис.19.1, аналогична программе на рис.9.1, за исключением того, что после ввода имен с клавиатуры выводит их не на экран, а на печатающее устройство. Каждая напечатанная страница содержит заголовок и через двойной интервал список введенных имен в следующем виде:
List of Employee Names Page 01 Clancy Alderson
Ianet Brown David Christie
...
Программа подсчитывает число |
напечатанных строк и |
при |
достижении |
|||||
конца страницы выполняет прогон до начала следующей страницы. |
В программе |
|||||||
имеются процедуры: |
|
|
|
|
|
|
|
|
D10INPT |
Выдает на экран запрос и затем вводит имя с клавиатуры. |
|||||||
E10PRNT |
Выводит имя |
на |
печатающее |
устройство |
(длина имени берется из |
|||
|
вводного списка параметров); в конце страницы вызывает процедуру |
|||||||
M10PAGE |
M10PAGE. |
прогон |
на |
новую |
страницу, |
печатает |
заголовок, |
|
Выполняет |
||||||||
|
сбрасывает счетчик строк и увеличивает счетчик |
страниц на |
||||||
P100UT |
единицу. |
|
|
|
|
вывода |
на |
печатающее |
Общая подпрограмма для непосредственного |
||||||||
|
устройство. |
|
|
|
|
|
|
|
В начале выполнения необходимо напечатать заголовок, но не делать перед этим перевод страницы. Поэтому процедура M10PAGE обходит перевод страницы, если счетчик PAGECTR содержит 01 (начальное значение). Поле PAGECTR определено как
PAGECTR DB '01'
В начале выполнения необходимо напечатать заголовок, но не делать перед этим перевод страницы. Поэтому процедура M10PAGE обходит перевод страницы, если счетчик PAGECTR содержит 01 (начальное значение). Поле PAGECTR определено как
PAGECTR |
DB |
'01' |
|
|
В результате будет сгенерировано число в ASCII-коде - шест.3031. Процедура |
||||
M10PAGE увеличивает счетчик PAGECTR на |
1 так, |
что значение становится |
||
последовательно 3032, |
3033 |
и т.д. Эти значения корректны до 3039, далее |
||
следует 303A, что будет распечатано, |
как двоеточие (:). Поэтому, если в |
|||
правом байте поля PAGECTR появляется шест.3A, |
то это значение заменяется |
|||
на шест.30, а к левому байту прибавляется единица. Таким образом шест.303A перекодируется в шест.3130, т.е. в 10 в символьном представлении.
Проверка на конец страницы до (но не после) печати имени гарантирует, что на последней странице будет напечатано по крайней мере одно имя под заголовком.
ПЕЧАТЬ ASCII-ФАЙЛОВ И ТАБУЛЯЦИЯ
________________________________________________________________
Табуляция, обеспечиваемая, например, видеоадаптерами, заключается в замене одного символа табуляции (код 09) несколькими пробелами при выводе так, чтобы следующая позиция была кратна 8. Таким образом, стандартные позиции табуляции являются 8, 16, 24 и т.д. Многие принтеры, однако,
