На главную Назад
Добро пожаловать, уважаемый посетитель!

Структура данных - это организация данных, которая имеет для

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

структуры данных когда одна и та же совокупность данных

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

Благодаря определению, обе стороны имеют четкий образ этих данных.

Если программа A передает некотрые данные программе B, то

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

ищет данные в одном и том же месте.

У нас уже был хороший пример структуры данных. Блок управления

файлом FCB является структурой данных. Блок FCB используется

программами для обмена информацией о файле с DOS. В блоке FCB

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

текущей записи, длина файла и т.д. Кроме того, в блоке FCB имеется

зарезервированное поле, которое содержит информацию, используемую

только DOS. В блоке FCB находится вся информация, необходимая для

DOS и прикладных программ. Эта структура данных служит для передачи

параметров файла между DOS и прикладной программой.

 

Теперь нужно найти такой способ определения структур данных,

чтобы программа могла с удобством ими пользоваться. В

Макроассемблере фирмы IBM имеется оператор STRUC, позволяющий

определять структуру данных. С точки зрения программиста структура

данных выглядит как еще один сегмент. Определение данных

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

структуры, как и описание сегмента, заканчивается оператором ENDS.

Однако в действительности структура не генерирует данные. Оператор

STRUC определяет структуру данных для ассемблера. В дальнейшем имя

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

генерации соответствующей области данных.

Если рассматривать оператор STRUC описанным выше образом, то он

больше похож на оператор MACRO. Программа определяет структуру

данных в одном месте, а ее вызов осуществляет позднее. Фактическая

генерация данных происходит при вызове структуры. Фиг. 6.14 поможет

понять работу оператора STRUC.

Microsoft (R) Macro Assembler Version 5.00 1/1/80 04:03:36

Фиг. 6.14 Структуры Page1-1

 

PAGE,132

TITLEФиг. 6.14 Структуры

 

FCBSTRUC

000000DRIVEDB0; Номер устройства

000120 20 20 20 20 20 20FILE_NAMEDB''; Имя файла

20

000920 20 20FILE_EXTDB''; Тип файла

000C0000CURRENT_BLOCKDW0; Номер текущего блока

000E0080RECORD_SIZEDW80H; Логический размер записи

001000000000FILE_SIZEDD0; Размер файла в байтах

00140000DATE DW0; Дата последнего изменения

 

Фиг. 6.14 Структуры (начало)

0016000A[RESERVEDDB10 DUP (?); Зарезервировано ДОС

??

]

002000SEQ_NUMBERDB0; Номер текущей записи

002100000000RANDOM_NUMBERDD0; Номер записи при прямом

;доступе

0025FCBENDS

 

0000STACKSEGMENT STACK

00000040[DW64DUP (?)

????

]

0080STACKENDS

 

0000CODESEGMENT

ASSUMECS:CODE

 

000001INPUTFCB<1,'FIG6-14','INP'>

0001464947362D313420

0009494E50

000C0000

000E0080

001000000000

00140000

0016000A[

??

]

002000

002100000000

 

002502OUTPUTFCB<2,'EXAMPLE','TST'>

00264558414D504C4520

002E545354

00310000

00330080

003500000000

00390000

003B000A[

??

]

004500

004600000000

 

 

004ASTRUCTURESPROCFAR

004A1EPUSHDS ; Установка адреса возврата

004BB8 0000MOVAX,0

004E50PUSHAX

004F0EPUSHCS ; Установка DS на сегмент CODE

00501FPOPDS

ASSUMEDS:CODE

00518D 16 0000 RLEADX,INPUT; Открытие вводимого файл

 

Фиг. 6.14 Структуры (продолжение)

0055B4 0FMOVAH,0FH

0057CD 21INT21H

 

00598D 16 0025 RLEADX,OUTPUT; Создание выводимого файла

005DB4 16MOVAH,16H

005FCD 21INT21H

 

00618D 1E 0000 RLEABX,INPUT

0065C7 47 0E 0010MOV[BX].RECORD_SIZE,16; Установка размера записи для ввода

006AC6 47 20 01 MOV[BX].SEQ_NUMBER,1; Пропуск первой записи

 

006EC7 06 0033 R 0010MOVOUTPUT.RECORD_SIZE,16; Установка размера записи для

;вывода

00748D 16 0000 RLEADX,INPUT; Чтение второй записи из файла

0078B4 14MOVAH,14H

007ACD 21INT21H

 

007C8D 16 0025 RLEADX,OUTPUT; Вывод введенной записи

0080B4 15MOVAH,15H

0082CD 21INT21H

 

0084B4 10MOVAH,10H; Закрытие выводимого файла

0086CD 21INT21H

 

0088CBRET

0089STRUCTURESENDP

0089CODEENDS

END

 

Microsoft (R) Macro AssemblerVersion 4.004/16/89 23:15:19

 

Фиг. 6.14 СтруктурыSymbols-1

 

Structures and Records:

 

N a m eWidth# fields

ShiftWidthMaskInitial

 

FCB. . . . . . . . . . . . . .0025000A

DRIVE. . . . . . . . . . . .0000

FILE_NAME. . . . . . . . . .0001

FILE_EXT . . . . . . . . . . .0009

CURRENT_BLOCK. . . . . . . .000C

RECORD_SIZE. . . . . . . . .000E

FILE_SIZE. . . . . . . . . .0010

DATE . . . . . . . . . . . . .0014

RESERVED . . . . . . . . . . .0016

SEQ_NUMBER . . . . . . . . . .0020

RANDOM_NUMBER. . . . . . . .0021

 

Фиг. 6.14 Структуры (продолжение)

 

На Фиг. 6.14 приведена очень простая программа, которая

использует файлы системы DOS. Эта программа открывает файл DOS на

носителе в дисководе A:, считывает вторую запись этого файла и

записывает ее в файл на носителе в дисководе B:. Маловероятно,

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

что-либо существенное, но сейчас она дает нам возможность

использовать структуру данных для блока FCB.

 

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

FCB. Оператор языка ассемблера STRUC отмечает начало определения

структуры. Метка FCB является здесь именем данной конкретной

структуры. В примере определяется каждое поле структуры данных FCB.

Обратите внимание, что в столбцах слева ассемблер генерирует

объектный код данной структуры. Однако, при редактировании связей

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

отсутствует. Ассемблер распечаьываеь данную структуру данных в

оттранслированном виде исключительно для вашего сведения.

 

Точно так же, как и вслучае макрокоманды, имя FCB становится

как бы новым оператором языка ассемблера. Первым оператором в

сегменте CODE является вызов структуры данных FCB. В примере этой

структуре данных присваивается имя INPUT. Данная структура FCB

идентифицирует входной набор данных. Заметьте, что в этом операторе

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

которые были включены в исходное определение структуры данных.

 

Если мы сравним объектный код определения структуры FCB с

объектным кодом структуры INPUT, то увидим, что они различаются по

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

DRIVE равно 0, в структуре INPUT - 1. Первый операнд в угловых

скобках определения структуры INPUT равен 1. Это значение заменяет

исходно определенное значение 0. Аналогично в данном примере

изменяются значения второго и третьего полей, относящихся к имени

файла. Закрывающая угловая скобка в определении структуры INPUT

завершает процедуру замены значений полей структуры данных.

Оставшаяся часть структуры INPUT идентична определеной в структуре

данных FCB.

 

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

определение этого поля содержит только один элемент. В

рассматриваемом примере программа может изменять любое поле

структруыр FCB, за исключением поля RESERVED. Мы определили это

поле поле как 10 отдельных элементов, и оно не может быть изменено.

Аналогично, если поле определено оператором

 

DB 10,20

 

то его нельзя перекрыть. При вызове структуры можно изменять только

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

включающая несколько символов, рассматривается ассемблером как один

элемент. В данном примере поле FILE_NAME содержит несколько

символов, но является одним элементом, значение которого можно

изменить.

 

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

входящие в определение, по позиционному принципу, как и в

макрокоманде. Если вы не хотите модифицировать заданное в

определении значение, но желаете изменить следующее за ним поле, то

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

модификации полей FILE_NAME и CURRENT_BLOCK, оставляя в то же время

по умолчанию заданные значения полей DRIVE и FILE_EXT, структуру

FCB следует вызвать оператором:

 

EXAMPLE FCB <,NEWNAME,,12>

 

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

значение по умолчанию. В следующем поле NEWNAME заменяет строку

пробелов. Для значения поля FILE_EXT по умолчанию используется

строка пробелов, и наконец, нулевое значение поля CURRENT_BLOCK

заменяется на 12.

 

В следующей исходной программной строке на Фиг. 6.14 программа

определяет структуру FCB под именем OUTPUT для выходного файла.

Здесь снова модифицируются первые три поля определения данных путем

включения новых значений в поля операндов оператора FCB.

 

Выигрыш от использования структур данных проявляется в

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

имена INPUT и OUTPUT так же, как и на любые другие метки в

программе. Вы можете видеть это, в том участке программы, где

открывается входной файл INPUT и оператор

 

LEA DX,INPUT

 

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

 

В программе можно использовать каждое из указанных полей

структуры данных. Значению каждого имени соответствует смещение

какого-либо поля в структуре данных. Например, программа помещает в

регистр BX адрес FCB INPUT. После этого программа обращается к

полям RECORD_SIZE и SEQ_NUMBER в режиме адресации по базе. Так как

регистр BX уже указывает на структуру данных FCB, то нужно задать

смещение относительно этой базы. Способ адресации

 

[BX].RECORD_SIZ

 

указывает ассемблеру, что в команде, которую он должен

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

базы, хранящимся в регистре BX. Если вы рассмотрите соответствующие

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

смещения для полей RECORD_SIZE (0EH) и SEQ_NUMBER (20H). Символ "."

идентифицирует имена полей как смещения в структуре данных.

 

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

структуру данных и для прямой адресации. Следующий участок

программы непосредственно изменяет поле RECORD_SIZE в FCB OUTPUT.

Программа именует это поле OUTPUT.RECORD_SIZE. Имя OUTPUT

определяет конкретную структуру данных, а RECORD_SIZE - имя поля в

этой структуре данных.

 

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

информацией о структуре данных располагает ассемблер. Фиг. 6.14

включает в себя фрагмент таблицы символических имен. Ассемблер

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

Ассемблер показывает вам всю информацию о структуре данных, которой

располагает. Этот раздел имеет заголовок "Structures and records"

("Структуры и записи"). В первой строке этого раздела для структуры

FCB из нашего примера указано, что эта структура имеет длину 25H

байт и содержит 0AH полей. Далее ассемблер перечисляет все эти

поля, печатая их с отступом по отношению к имени структуры. Для

каждого из полей приводится значение соответствующего смещения. Для

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

(ширина) и "#dfields" (число полей). Вторая строка в меток колонок

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

интерпретирует как записи, будут рассмотрены в следующем разделе.

 

Программа, приведенная на Фиг. 6.14, не делает ничего

полезного. Кроме того, в ней нет никакой обработки ошибок. Однако

она хорошо иллюстрирует применение оператора STRUC. Этот способ

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

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

смещений очень удобно при модификации структур данных на этапе

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

то ассемблер автоматически изменит значения смещений при повторном

ассемблировании программы. Кроме того, использование структур

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

понятной.


 

Mail.ru