Структуры

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

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

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

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

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

    Если программа 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 Структуры                              Page   1-1

 

                                         PAGE    ,132

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

 

                                   FCB     STRUC

            0000  00                     DRIVE       DB      0               ; Номер устройства

            0001  20 20 20 20 20 20 20     FILE_NAME       DB      '        '      ; Имя файла

                20

            0009  20 20 20               FILE_EXT          DB      '   '           ; Тип файла

            000C  0000             CURRENT_BLOCK   DW      0                 ; Номер текущего блока

            000E  0080             RECORD_SIZE     DW      80H         ; Логический размер записи

            0010  00000000               FILE_SIZE         DD      0               ; Размер файла в байтах

            0014  0000             DATE       DW      0               ; Дата последнего изменения

 

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

            0016  000A[            RESERVED          DB      10 DUP (?)      ; Зарезервировано ДОС

                   ??

                              ]

            0020  00                     SEQ_NUMBER      DB      0                 ; Номер текущей записи

            0021  00000000               RANDOM_NUMBER   DD      0                 ; Номер записи при прямом

                                                                 ;      доступе

            0025                   FCB     ENDS

 

            0000                   STACK   SEGMENT STACK

            0000  0040[                  DW      64      DUP (?)

                  ????

                              ]

            0080                   STACK   ENDS

 

            0000                   CODE    SEGMENT

                                         ASSUME  CS:CODE

 

            0000  01                     INPUT   FCB     <1,'FIG6-14','INP'>

            0001  464947362D313420

            0009  494E50

            000C  0000

            000E  0080

            0010  00000000

            0014  0000

            0016  000A[

                   ??

                              ]

            0020  00

            0021  00000000

 

            0025  02                     OUTPUT  FCB     <2,'EXAMPLE','TST'>

            0026  4558414D504C4520

            002E  545354

            0031  0000

            0033  0080

            0035  00000000

            0039  0000

            003B  000A[

                   ??

                              ]

            0045  00

            0046  00000000

 

 

            004A                   STRUCTURES      PROC    FAR

            004A  1E                           PUSH    DS              ; Установка адреса возврата

            004B  B8 0000                      MOV     AX,0

            004E  50                           PUSH    AX

            004F  0E                           PUSH    CS              ; Установка DS на сегмент CODE

            0050  1F                           POP     DS

                                         ASSUME  DS:CODE

            0051  8D 16 0000 R                 LEA     DX,INPUT             ; Открытие вводимого файл

 

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

            0055  B4 0F                  MOV     AH,0FH

            0057  CD 21                  INT     21H

 

            0059  8D 16 0025 R                 LEA     DX,OUTPUT            ; Создание выводимого файла

            005D  B4 16                  MOV     AH,16H

            005F  CD 21                  INT     21H

 

            0061  8D 1E 0000 R                 LEA     BX,INPUT

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

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

 

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

                                                                 ;      вывода

            0074  8D 16 0000 R                 LEA     DX,INPUT             ; Чтение второй записи из файла

            0078  B4 14                  MOV     AH,14H

            007A  CD 21                  INT     21H

 

            007C  8D 16 0025 R                 LEA     DX,OUTPUT            ; Вывод введенной записи

            0080  B4 15                  MOV     AH,15H

            0082  CD 21                  INT     21H

 

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

            0086  CD 21                  INT     21H

 

            0088  CB                           RET

            0089                   STRUCTURES      ENDP

            0089                   CODE    ENDS

                                         END

 

            Microsoft (R) Macro Assembler  Version 4.00             4/16/89 23:15:19

 

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

 

            Structures and Records:

 

                        N a m e                 Width   # fields

                                          Shift   Width   Mask    Initial

 

            FCB  . . . . . . . . . . . . . .          0025    000A

            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. Этот способ

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

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

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

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

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

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

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

    понятной.

Hosted by uCoz