Файл: jourdain_spravochnik_programmista.docx

ВУЗ: Не указан

Категория: Не указан

Дисциплина: Не указана

Добавлен: 04.07.2020

Просмотров: 3068

Скачиваний: 1

ВНИМАНИЕ! Если данный файл нарушает Ваши авторские права, то обязательно сообщите нам.

точки между строками символов. Символы псевдографики должны печа-

таться и в этом поле, а в некоторых случаях они занимают в высоту

12 точек. Поскольку большинство печатающих головок имеет только 8

иголок, то единственным решением проблемы является печать таких

символов за два прохода, продвигая бумагу вперед перед вторым

проходом. В этом случае символ перевода строки (ASCII 10) вообще

не используется. Вместо этого, принтер попеременно делает интер-



валы высотой то в 8, то в 4 точки. При втором проходе часть иго-

лок будут на том месте, где уже имеются отпечатанные точки, поэ-

тому надо чтобы биты для этих иголок были сброшены в 0, чтобы они

не работали.

Чтобы продвинуть бумагу на высоту четырех точек надо послать

код 27, 65, 4, 27, 50, а на высоту восьми точек - 27, 65, 8, 27,

50. При этом вызывается автоматический возврат каретки. В то

время когда выполняется первый проход, готовится временная строка

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

символ обычный, то в соответствующую позицию временной второй

строки символов надо поместить пробел (ASCII 32). Но если

встречается специальный графический символ, который должен печа-

таться в четырехточечном поле, то надо поместить его код ASCII в

соответствующюю позицию второй строки. Например:


Позиция символа 1 2 3 4 5 6 7 8 9 10


Код ASCII 205 32 98 111 114 105 110 103 32 205

Код 2-й строки 205 32 32 32 32 32 32 32 32 205


В памяти должна храниться отдельная таблица цепочек битов этих

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

содержимое таблицы для первого прохода будет 0, 255, 0, 255, 0,

0, а для второго - 0, 15, 0, 15, 0, 0. Отметим, что во втором и

четвертом байте для второго прохода верхние 4 бита сброшены,

чтобы не было надпечатки.

Короче, когда начинается печать, то в первую очередь прове-

ряется является ли данный символ пседографическим, и если нет, то

он посылается на печать, как обычный код ASCII. Во временную

строку, используемую для печати второго прохода вставляется про-

бел. Затем обрабатывается следующий символ. Когда встречается

символ псевдографики, то 6 кодирующих его байтов берутся из таб-

лицы, принтер переводится в графический режим для вывода 6 байтов

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

текстовый режим. В соответствующую позицию строки для второго

прохода помещается код ASCII этого символа псевдографики. Этот

процесс продолжается до конца строки, после чего делается прогон

бумаги на высоту четырех точек. При повторном проходе надо опять

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

печатать символ пробела (т.е. не печатать ничего, а просто прод-

винуть головку к следующему символу). Если же это графический

символ, то надо найти соответствующий ему данные для второго

прохода в отдельной таблице и напечатать его таким же образом,


как и при первом проходе. Повторно используйте строку для второго

прохода с каждой печатаемой строкой. На рис. 6-3 показана эта

процедура.


Высокий уровень.


В данном примере текст разделен на две колонки, при этом неп-

рерывная линия разделяет страницу посредине. Для простоты печа-

тается только одна строка, однако этот пример может печатать и

целую страницу, если вставить цикл FOR/NEXT в строках 325 и 505.



Для демонстрации двух подходов при первом проходе печатается по

одному символу, в то время как при втором проходе печатается

целая строка.


100 '''таблица данных для первого прохода (только коды 178 и 179)

110 DATA 0, 0, 255, 0, 0, 0

120 DATA 4, 4, 255, 0, 0, 0

130 '''аналогичная таблица для второго прохода

140 DATA 0, 0, 15, 0, 0, 0

150 DATA 0, 0, 15, 0, 0, 0

160 '''помещаем первую таблицу в массив

170 DIM FIRSTPASS$(45) 'описываем массив

180 FOR N = 1 TO 2 'заполняем его

190 Y$ = "" 'Y$ хранит 6 байтов на символ

200 FOR M=1 TO 6: READ X: Y$ = Y$+CHR$(X): NEXT

210 FIRSTPASS$(N) = Y$: NEXT 'помещаем в массив

220 '''помещаем в массив вторую таблицу

230 DIM SECONDPASS$(45) '

240 FOR N = 1 TO 2 '

250 Y$ = "" '

260 FOR M=1 TO 6: READ X: Y$ = Y$+CHR$(X): NEXT

270 SECONDPASS$(N) = Y$: NEXT '

280 '''печатаем текст следующей строки

290 TEXT$ = "Here is one column"+CHR$(179)+"Here is the

second column"


300 TEMP$ = STRING$(80,32) 'создаем строку для 2-го прохода

310 GRAPH$ = CHR$(27)+CHR$(75)+CHR$(6)+CHR$(0)

320 OPEN "LPT1:" AS #1 'открываем принтер

330 FOR N = 1 TO LEN(TEXT$) 'для каждого символа текста

340 C$ = MID$(TEXT$,N,1) 'берем символ и проверяем его

350 IF C$ < CHR$(128) THEN PRINT #1,C$;: GOTO 400

360 '''предполагаем, что все остальные символы - псевдографика

370 PRINT #1,GRAPH$; 'входим в графический режим

380 PRINT #1,FIRSTPASS$(ASC(C$) - 178);выводим 1-й проход

390 MID$(TEMP$,N) = C$ 'маркер в строке 2-го прохода

400 NEXT

410 '''смещаемся на 8 точек вниз и делаем второй проход

420 PRINT #1,CHR$(27)+CHR$(65)+CHR$(4)+CHR$(141);

430 Z$ = "" 'Z$ содержит строку для 2-го прохода

440 FOR N = 1 TO LEN(TEXT$) 'для каждого символа текста

450 C$ = MID$(TEMP$,N,1) 'берем символ и обрабатываем его

460 IF C$ = CHR$(32) THEN Z$ = Z$+" ": GOTO 480

470 Z$ = Z$+GRAPH$+SECONDPASS$(ASC(C$) - 178)

480 NEXT

490 PRINT #1,Z$ 'печатаем всю строку сразу

500 PRINT #1,CHR$(10); 'добавляем в конце перевод строки


Низкий уровень.


Программа на ассемблере использует тот же самый алгоритм, что

и приведенная программа на Бейсике. Когда используется только

несколько символов, то Вы можете сэкономить место, сжав таблицу,

с тем чтобы их положение в таблице не было пропорционально их



позиции в наборе ASCII. Затем подготовьте небольшую таблицу ин-

дексов с помощью инструкции XLAT, с помощью которой можно быстро

искать данные в этой таблице.



6.3.5 Копирование экрана на принтер (дамп экрана).




Дамп текстового экрана сделать достаточно просто, если все

используемые символы содержатся в ПЗУ принтера и ни один из них

не выводится со специальными атрибутами, такими как подчеркивание

или негативное изображение. В этом простейшем случае программе

нужно лишь установить ширину принтера равной 80 символам, а затем

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


рерывный поток данных на принтер. Если в ПЗУ принтера отсутствуют

специальные символы, такие как символы псевдографики, то програм-

ма должна подготовить свою таблицу данных для этих символов и

выводить их на принтер в графическом режиме. Поскольку эти симво-

лы могут заходить в межстрочные интервалы, то может потребоваться

специальное программирование [6.3.4].

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

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

видеобуфера (в [4.1.3] обсуждается значение битов, соответствую-

щее различным атрибутам). Когда символ выделен с помощью подчер-

кивания или повышенной интенсивности, то надо включать подчерки-

вание или печать жирным шрифтом на принтере. Однако если символ

выводится в негативном изображении, то возникают те же проблемы,

что и с некоторыми графическими символами: область негативного

изображения должна простираться до верхнего края следующей стро-

ки. В этом случае надо следуя указаниям [6.3.4] заполнить черным

всю область при втором проходе. В зависимости от принтера, Вам

может понадобиться создать специальную таблицу данных для вывода

символов в негативе, поскольку когда они будут печататься, то

окружающие точки могут находиться слишком близко одна к другой,

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

о печати в два прохода. Простым решением проблемы с негативным

изображением является использование графического режима экрана

для вывода текста, а затем сделать дамп графического экрана.

Графические дампы создают свои проблемы. Байт данных принтера

соответствует восьми вертикальным точкам, в то время как на экра-

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

процедура преобразования, показанная на рис. 6-4. Надо сразу

получать по 8 байтов памяти экрана, выбирая такие, которые соот-

ветствуют области точек 8*8. Затем надо использовать логические

операции для перестановки битов, как показано в примерах.

Имейте ввиду, что большинство матричных принтеров искажают

экранное изображение. Это происходит потому, что они используют

масштабный коэффициент 1:1, в то время как экран использует коэф-

фициент 5:6 (масштабный коэффициент сравнивает число горизонталь-

ных точек на дюйм с числом вертикальных точек на дюйм). Точнее

говоря, искажение изображения на самом деле возникает из-за масш-

табного коэффициента экрана, поскольку программы должны специаль-

но менять данные для изображения, чтобы оно выглядело так, как

нам хочется (например, изображение окружности на экране создается

выводом на него эллипса). Когда данные с экрана выводятся на



принтер, то эти искажение должны обращаться. Некоторые графичес-

кие принтеры имеют специальные режимы, в которых можно выводить

копию экрана без искажения, а цветной принтер IBM может менять


масштабный коэффициент в любом из своих графических режимов.


Высокий уровень.


Приводимая процедура на Бейсике делает копию текстового экра-

на, игнорируя специальные атрибуты:


10 OPEN "LPT1:" AS #1 'открываем принтер

20 DEF SEG = &HB000 'указываем на видеобуфер

30 PRINT #1,CHR$(13) 'сдвигаем головку влево

40 FOR G = 0 TO 3998 STEP 2 'для каждого байта буфера

50 PRINT #1,CHR$(PEEK(G)); 'читаем его и выводим на принтер

60 NEXT 'обрабатываем следующий байт


Переброска цепочек битов для графического дампа требует в Бейсике

слишком много времени. Поместите в массив (здесь, BYTE$) восемь

байтов, отвечающих области экрана 8*8 точек. Создайте второй

массив (VERTICAL$) и обнулите его элементы, а затем поочередно

перебрасывайте биты элементов этих массивов следующим образом:


500 FOR M = 0 TO 7 'для каждого бита

510 FOR N = 0 TO 7 'для каждого байта

520 X = ASC(BYTES(N)) 'получаем значение байта

530 Y = 2*(7 - M) 'маска для одного включенного бита

540 Z = X AND Y 'проверка этого бита в байте

550 IF Z <> 0 THEN VERTICAL$(M) = CHR$(ASC(VERTICAL$(M) OR 2*N)

'если он включен, то устанавливаем бит

'в соответствующей позиции 2-го массива

560 NEXT N 'следующий бит

570 NEXT M 'следующий байт


Низкий уровень.


Язык ассемблера делает битовые преобразования намного быстрее.

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

поскольку она держит все в микропроцессоре (она немного великова-

та, но Вы можете использовать взамен алгоритм, показанный в Бей-

сике). Процедура работает, храня 8 результирующих байтов в ре-

гистрах CX, DX, BP и DI. Байт экранных данных помещается в AL, а

затем в AH передвигаются последовательно CL, CH, DL и DH. Каждый

раз из AL в AH сдвигается один бит и когда сделаны 4 сдвига, то

CX и DX обмениваются с DX и BP, после чего все это повторяется

снова. Этот процесс повторяется для каждого из 8-ми экранных

байтов и когда он завершен, то преобразованное изображение хра-

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

для печати в CL. Содержимое регистров выводится на принтер и

обнуляется, после чего процесс повторяется для следующих восьми

байтов экрана. Сначала получите 8 байтов из видеобуфера и помес-



тите их в буфер с именем BUFFER. Поместите 0 в AX, CX, DX, BP и

DI. Затем:


LEA BX,BUFFER ;указываем на буфер видеоданных

MOV SI,0 ;смещение в этом буфере

GET_BYTE: MOV AL,[BX][SI] ;берем байт

DO_HALF: XCNG AH,CL ;получаем CL, CH, DL и DH

SHL AX,1 ;сдвигая бит из AL

XCNG AH,CL ;

XCNG AH,CH ;

SHL AX,1 ;


XCNG AH,CH ;

XCNG AH,DL ;

SHL AX,1 ;

XCNG AH,DL ;

XCNG AH,DH ;

SHL AX,1 ;

XCNG AH,DH ;

;---начинаем вторую половину перемещения битов

XCNG CX,BP ;обмениваем содержимое CX и DX

XCNG DX,DI ;

CMP SI,7 ;если все байты преобразованы, то печатаем

JE PRINT_BYTES ;

INC SI ;иначе переходим к следующему байту

JMP SHORT GET_BYTE ;

;---печатаем байты

PRINT_BYTES: PUSH DX ;сохроаняем DX

MOV AH,5 ;функция вывода на принтер


MOV DL,27 ;код Esc

INT 21H ;посылаем его

MOV DL,75 ;код графического режима

INT 21H ;посылаем его

MOV DL,6 ;будет послано 6 байтов

INT 21H ;

MOV DL,0 ;

INT 21H ;

CALL PRINT_2_BYTES ;посылаем содержимое CX

POP CX ;

CALL PRINT_2_BYTES ;посылаем содержимое DX

MOV CX,BP ;

CALL PRINT_2_BYTES ;посылаем содержимое BP

MOV DX,DI ;

CALL PRINT_2_BYTES ;посылаем содержимое DI

.

(идем к следующей группе из восьми байтов)

.

PRINT_2_BYTES: PROC NEAR

MOV AH,5 ;функция печати

MOV DL,CL ;сначала CL

INT 21H ;печатаем

MOV DL,CH ;затем CH

INT 21H ;печатаем

RET

PRINT_2_BYTES ENDP



Глава 7. Ввод/вывод.





Раздел 1. Доступ к последовательному порту.




При асинхронной связи машина посылает или принимает байты

информации по одному биту. Временные интервалы между байтами при

этом несущественны, но времена между отдельными битами байта

очень важны. Сигнал на линии может быть высокого или низкого

уровня, что соответствует логическим нулю и единице, и говорят,

что линия отмечена (marking), когда уровень высокий, и пустая

(spacing), когда уровень низкий.

Линия поддерживается в отмеченном состоянии, когда по ней нет

передачи данных. При начале передачи байта данных сигнал падает в

0, отмечая стартовый бит. Затем следуют восемь битов данных

(иногда меньше) в виде набора высоких и низких уровней. Последний

бит данных может сопровождаться битом четности, используемым для

обнаружения ошибок, а затем в последовательность включаются 1 или

более стоп-битов, которым соответствует высокий уровень. Эти

стоп-биты начинают отмеченное состояние, которое будет сохранять-

ся до тех пор, пока не начнется передача следующего байта данных;

число используемых стоп-битов существенно, поскольку они устанав-

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

стартовым битом. На рис. 7-1 показана эта последовательность.

Конечно, передающая и приемная станции должны использовать

один и тот же протокол для этих цепочек битов и они должны рабо-

тать с одной и той же скоростью обмена (измеряемой в битах в

секунду, называемых также бодами). При обмене могут легко возни-

кать ошибки, поэтому коммуникационное оборудование предоставляет

разнообразную информацию о статусе как самого порта, так и при-

соединенного к нему модема. Задачей модема является преобразова-

ние сигнала, генерируемого портом коммуникации, в акустический

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

Большинство модемов предоставляют также дополнительные коммуника-

ционные возможности, такие как автоматический вызов и ответ,

которые не поддерживаются самим портом коммуникации.



7.1.1 Программирование микросхемы UART 8250.




Последовательная связь настолько сложна, что были разработаны

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

синхронизации строк битов, составляющих последовательные данные.