<p>14.2. Доступ к памяти ПЭВМ. Массивы Mem, MemW, MemL</p>

Для простого доступа к любой физической ячейке памяти Турбо Паскаль вводит три предопределенных массива: Mem, MemW, MemL. Они как бы наложены на всю память ПЭВМ. Можно условно считать, что эти массивы известны по системному определению:

VAR

Mem : Array of Byte absolute 0:0;

MemW : Array of Word absolute 0:0;

MemL : Array of Longlnt absolute 0:0;

- 298 -

Но отличие их от обычных массивов — в задании индексов. Они должны задаваться не номером, а адресом интересующей нас ячейки памяти в формате СЕГМЕНТ:СМЕЩЕНИЕ. Так,

Mem [$B000:$0000] — значение байта (Byte) по данному адресу;

MemW[$B000:$0000] — значение слова (Word) по данному адресу;

MemL[$B000:$0000] — значение двойного слова (LongInt).

Во всем остальном массивы Mem очень похожи на обычные массивы. Если Mem [] стоит справа в операторе присваивания, то это — значение байта (слова, двойного слова), начинающегося с данного индекса-адреса. Но Mem[] может стоять и слева. Это будет означать модификацию байта (слова или двойного слова) по данному адресу, например:

Mem[ $50 : 0 ] := Mem [ $50: 0 ] xor 1;

{ вкл/выкл реакции на Shift+PrtScr }

Элементы массивов Mem могут подставляться как фактические параметры при вызовах процедур и функций. Наиболее часто массивы Mem, MemW и MemL используются для доступа к системным областям памяти, как в примере на рис. 14.3.

| PROGRAM Devices; { Анализ байта конфигурации }

| VAR

| CFG : Word; { сюда запишется значение ячейки памяти }

| BEGIN

| CFG := MemW[ $0000:$0410 ];

| WriteLn( #10, 'Текущая конфигурация:', #10 );

| WriteLn('Макс. число принтеров -->', CFG shr 14 );

| WriteLn('Число серийных портов -->', (CFG shr 9) and 7);

| WriteLn('Число НГМД --> ',

| ( CFG and 1 )*( 1 + ( CFG shr 6 ) and 3 ) );

| WriteLn('Наличие игрового порта-—>',(CFG and 4096)=1);

| WriteLn;

| ReadLn

| END.

Рис. 14.3

<p>14.3. Доступ к портам ввода-вывода. Массивы Port и PortW</p>

Массивы Port и PortW аналогичны массивам Mem, с той лишь разницей, что проиндексированы они не адресами, а номерами портов ввода-вывода. С помощью предопределенного массива Port можно обмениваться данными с 8-битовыми портами, а с помощью PortW — с 16-битовыми. Под поротом понимается нумерованный канал ввода-вывода, подсоединенный к процессору. Все взаимодействие с периферией ПЭВМ осуществляется через порты (в том числе работа дисплея, серийных портов, динамика, клавиатуры и т.п.). Если  ссылка на Port или PortW стоит справа в присваивании, например:

PostStatusVar := PortW[$61]; {чтение из порта}

то это означает чтение из порта с данным номером. Но если Port или PortW стоит слева, то это имеет смысл записи (посылки) в порт значения:

Num := $64;

Port[ Num ] := ByteVar {запись в порт}

Имена Port и PortW могут стоять только в операторах присваивания. Будет ошибкой обращение к Port или PortW без указания индекса. Не имеет смысла взятие адреса массивов Port или их отдельных элементов. Максимальное значение номера порта равно $3FFF.

<p>14.4. Процедура заполнения FillChar</p>

Эта процедура уже использовалась в предыдущих главах. Здесь мы обсудим ее подробно. Вызов процедуры содержит три параметра:

FillChar( VAR V; NBytes : Word; В : Byte )

или

FillChar( VAR V; NBytes : Word; С : Char )

Первый — переменная V любого типа, второй — число байтов переменной V, которые будут заполнены значением B или C. Процедура FillChar служит для заполнения участков памяти (ОЗУ) одним и тем же однобайтовым значением. Например, обнулить числовой массив A любой сложности можно одним вызовом:

FillChar( A, SizeOf( А ), 0 );

Если заполнение происходит числом, то третьим параметром должно быть значение, совместимое с типом Byte. Но если речь идет о заполнении символом, то последнее значение должно быть символьного типа. Самой процедуре FillChar этот момент безразличен, и можно для числового массива A записать

FillChar( A, SizeOf( А ), '0' );

- 300 -

но результатом здесь будет заполнение не нулем, а кодом Ord('0'), что равняется 48.

Следует также помнить, что заполняется заданным значением каждый байт блока с размером, заданным параметром NBytes. И если переменная A сконструирована не из однобайтных значений, а из более длинных (Word, Integer, Real и т.п.), то корректно работает лишь заполнение нулем. Например, заполнение переменной W типа Word вызовом

FillChar( W, SizeOf( Word ), 1 );

Перейти на страницу:

Поиск

Похожие книги