Записи: дополнительные возможности обработки 


Мы поможем в написании ваших работ!



ЗНАЕТЕ ЛИ ВЫ?

Записи: дополнительные возможности обработки



Понимая важность для эффективного программирования такого типа данных, как запись, разработчики транслятора TASM, начиная с версии 3.0, включили в систему его команд две дополнительные команды на правах директив.
Последнее означает, что эти команды внешне имеют формат обычных команд ассемблера, но после трансляции они приводятся к одной или нескольким машинным командам.
Введение этих команд в язык TASM повышает наглядность работы с записями, оптимизирует код и уменьшает размер программы.
Эти команды позволяют скрыть от программиста действия по выделению и установке отдельных полей записи (мы их обсуждали выше).

Для установки значения некоторого поля записи используется команда setfield с синтаксисом:

setfield имя_элемента_записи назначение,регистр_источник

Для выборки значения некоторого поля записи используется команда getfield с синтаксисом:

getfield имя_элемента_записи регистр_назначение, источник

Работа команды setfield заключается в следующем. Местоположение записи определяется операндом назначение, который может представлять собой имя регистра или адрес памяти.
Операнд имя_элемента_записи определяет элемент записи, с которым ведется работа (по сути, если вы были внимательны, он определяет смещение элемента в записи относительно младшего разряда). Новое значение, в которое необходимо установить указанный элемент записи, должно содержаться в операнде регистр_источник. Обрабатывая данную команду, транслятор генерирует последовательность команд, которые выполняют следующие действия:

  • сдвиг содержимого регистр_источник влево на количество разрядов, соответствующее расположению элемента в записи;
  • логическую операцию or над операндами назначение и регистр_источник. Результат операции помещается в операнд назначение.

Важно отметить, что setfield не производит предварительной очистки элемента, в результате после логического сложения командой or возможно наложение старого содержимого элемента и нового устанавливаемого значения. Поэтому требуется предварительно подготовить поле в записи путем его обнуления.

Действие команды getfield обратно setfield. В качестве операнда источник может быть указан либо регистр либо адрес памяти.
В регистр, указанный операндом регистр_назначение, помещается результат работы команды — значение элемента записи.
Интересная особенность связана с регистр_назначение. Команда getfield всегда использует 16-битный регистр, даже если вы укажете в этой команде имя 8-битного регистра.

В качестве примера применения команд setfield и getfield рассмотрим листинг 9.

Листинг 9. Работа с полями записи;prg_12_8.asmmasmmodel smallstack 256iotest recordi1:1,i2:2=11,i3:1,i4:2=11,i5:2=00.dataflag iotest <>.codemain: mov ax,@data mov ds,ax mov al,flag mov bl,3 setfield i5 al,bl xor bl,bl getfield i5 bl,al mov bl,1 setfield i4 al,bl setfield i5 al,blexit: mov ax,4c00h;стандартный выход int 21hend main;конец программы

Результат работы команд setfield и getfield удобнее всего изучать в отладчике.
При установке значений полей не производится их предварительная очистка. Это сделано специально. Для такого рода операций лучше использовать некоторые универсальные механизмы, иначе велик риск внесения ошибок, которые трудно обнаружить и исправить. В качестве такого механизма можно предложить механизм макросредств.

В заключение хотелось бы привести еще один пример использования записей.
Это описание регистра eflags. Для удобства мы разбили это описание на три части:

  • eflags_1_7 — младший байт eflags/flags;
  • eflags_8_15 — второй байт eflags/flags;
  • eflags_h — старшая половина eflags.
eflags_l_7 record sf7:1=0,zf6:1=0,c5:1=0,af4:1=0,c3:1=0,pf2:1=0,c1:=1,cf0:1=0eflags_l_15 record c15:1=0,nt14:1=0,iopl:2=0,of11:1=0,df10:1=0,if9:1=1,tf8:1=0eflags_h record c:13=0,ac18:1=0,vm17:1=0,rf16:1=0

Запомните это описание. Когда вы освоите работу с макрокомандами и в дальнейшей своей работе столкнетесь с необходимостью работать с регистром флагов, то у вас буквально “зачешутся” руки, чтобы написать соответствующую макрокоманду. Эта макрокоманда, если вы не забудете хорошо ее оттестировать, избавит вас от многих трудно обнаруживаемых ошибок.

Объединения

Представим ситуацию, когда мы используем некоторую область памяти для размещения некоторого объекта программы (переменной, массива или структуры). Вдруг после некоторого этапа работы у нас отпала надобность в использовании этих данных. Обычно память останется занятой до конца работы программы. Конечно, в принципе, ее можно было бы использовать для хранения других переменных, но при этом без принятия специальных мер нельзя изменить тип и имя. Неплохо было бы иметь возможность переопределить эту область памяти для объекта с другим типом и именем. Язык ассемблера предоставляет такую возможность в виде специального типа данных, называемого объединением.

Объединение — тип данных, позволяющий трактовать одну и ту же область памяти как имеющую разные типы и имена.

Описание объединений в программе напоминает описание структур, то есть сначала описывается шаблон, в котором с помощью директив описания данных перечисляются имена и типы полей:

имя_объединения UNION <описание полей>имя_объединения ENDS

Отличие объединений от структур состоит, в частности, в том, что при определении переменной типа объединения память выделяется в соответствии с размером максимального элемента.
Обращение к элементам объединения происходит по их именам, но при этом нужно, конечно, помнить о том, что все поля в объединении накладываются друг на друга.
Одновременная работа с элементами объединения исключена. В качестве элементов объединения можно использовать и структуры.

Листинг 7, который мы сейчас рассмотрим, примечателен тем, что кроме демонстрации использования собственно типа данных “объединение” в нем показывается возможность взаимного вложения структур и объединений.
Постарайтесь внимательно отнестись к анализу этой программы. Основная идея здесь в том, что указатель на память, формируемый программой, может быть представлен в виде:

  • 16-битного смещения;
  • 32-битного смещения;
  • пары из 16-битного смещения и 16-битной сегментной составляющей адреса;
  • в виде пары из 32-битного смещения и 16-битного селектора.

Какие из этих указателей можно применять в конкретной ситуации, зависит от режима адресации (use16 или use32) и режима работы микропроцессора.
Так вот, описанный в листинге 7 шаблон объединения позволяет нам облегчить формирование и использование указателей различных типов.

Листинг 7 Пример использования объединенияmasmmodel smallstack 256.586Ppnt struc;структура pnt, содержащая вложенное объединениеunion;описание вложенного в структуру объединенияoffs_16 dw?offs_32 dd?ends;конец описания объединенияsegm dw?ends;конец описания структуры.datapoint union;определение объединения, содержащего вложенную структуруoff_16 dw?off_32 dd?point_16 pnt <>point_32 pnt <>point endstst db "Строка для тестирования"adr_data point <>;определение экземпляра объединения.codemain: mov ax,@data mov ds,ax mov ax,seg tst;записать адрес сегмента строки tst в поле структуры adr_data mov adr_data.point_16.segm,ax;когда понадобится, можно извлечь значение из этого поля обратно, к примеру, в регистр bx: mov bx,adr_data.point_16.segm;формируем смещение в поле структуры adr_data mov ax,offset tst;смещение строки в ax mov adr_data.point_16.offs_16,ax;аналогично, когда понадобится, можно извлечь значение из этого поля: mov bx,adr_data.point_16.offs_16exit: mov ax,4c00h int 21hend main

Когда вы будете работать в защищенном режиме микропроцессора и использовать 32-разрядные адреса, то аналогичным способом можете заполнить и использовать описанное выше объединение.



Поделиться:


Последнее изменение этой страницы: 2017-02-05; просмотров: 325; Нарушение авторского права страницы; Мы поможем в написании вашей работы!

infopedia.su Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав. Обратная связь - 3.144.212.145 (0.007 с.)