4499

Записи в языке ассемблер

Лекция

Информатика, кибернетика и программирование

Записи в языке ассемблер Наша хозяйка-программист становится все более экономной. Она уже хочет работать с продуктами на молекулярном уровне, без любых отходов и напрасных трат. Подумаем, зачем тратить под некоторый программный индикатор со значение...

Русский

2012-11-21

40.08 KB

5 чел.

Записи в языке ассемблер

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

Подумаем, зачем тратить под некоторый программный индикатор со значением “включено-выключено” целых восемь разрядов, если вполне хватает одного? А если таких индикаторов несколько, то расход оперативной памяти может стать весьма ощутимым.

Когда мы знакомились с логическими командами, то говорили, что их можно применять для решения подобной проблемы. Но это не совсем эффективно, так как велика вероятность ошибок, особенно при составлении битовых масок.

TASM предоставляет нам специальный тип данных, использование которого помогает решить проблему работы с битами более эффективно. Речь идет о специальном типе данных — записях.

Запись — структурный тип данных, состоящий из фиксированного числа элементов длиной от одного до нескольких бит.

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

Суммарный размер записи определяется суммой размеров ее полей и не может быть более 8, 16 или 32 бит.

Если суммарный размер записи меньше указанных значений, то все поля записи “прижимаются” к младшим разрядам.

Использование записей в программе, так же, как и структур, организуется в три этапа:

  1.  Задание шаблона записи, то есть определение набора битовых полей, их длин и, при необходимости, инициализация полей.
  2.  Определение экземпляра записи. Так же, как и для структур, этот этап подразумевает инициализацию конкретной переменной типом заранее определенной с помощью шаблона записи.
  3.  Организация обращения к элементам записи.

Компилятор TASM, кроме стандартных средств обработки записей, поддерживает также и некоторые дополнительные возможности их обработки.

Описание записи

Описание шаблона записи имеет следующий синтаксис (рис. 6):

имя_записи RECORD <описание элементов>

Здесь:

<описание элементов> представляет собой последовательность описаний отдельных элементов записи согласно синтаксической диаграмме (см. рис. 6):

Рис. 6. Синтаксис описания шаблона записи

При описании шаблона память не выделяется, так как это всего лишь информация для транслятора ассемблера о структуре записи.

Так же, как и для структур, местоположение шаблона в программе может быть любым, но при этом необходимо учитывать логику работы однопроходного транслятора.

Определение экземпляра записи

Для использования шаблона записи в программе необходимо определить переменную с типом данной записи, для чего применяется следующая синтаксическая конструкция (рис. 7):

Рис. 7. Синтаксис описания экземпляра записи

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

Если инициализировать поля не требуется, то достаточно указать ? при определении экземпляра записи:

...

iotest record

i1:1,i2:2=11,i3:1,i4:2=11,i5:2=00

 ...

flag iotest ?

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

Если требуется частичная инициализация элементов, то они заключаются в угловые (< и >) или фигурные ({ и }) скобки.

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

К примеру, согласиться со значениями по умолчанию можно так:

iotest record

i1:1,i2:2=11,i3:1,i4:2=11,i5:2=00

...

flag iotest <> ;согласились со значением по умолчанию

Изменить значение поля i2 можно так:

iotest record

i1:1,i2:2=11,i3:1,i4:2=11,i5:2=00

...

flag iotest <,10,> ; переопределили i2

Применяя фигурные скобки, также можно указать выборочную инициализацию полей, но при этом необязательно обозначать запятыми поля, со значениями по умолчанию которых мы согласны:

iotest record

i1:1,i2:2=11,i3:1,i4:2=11,i5:2=00

...

flag iotest {i2=10} ;переопределили i2, не обращая внимания на порядок

;следования других компонентов записи

Работа с записями

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

Прежде всего для понимания проблемы нужно усвоить несколько моментов:

  1.  Каждому имени элемента записи ассемблер присваивает числовое значение, равное количеству сдвигов вправо, которые нужно произвести для того, чтобы этот элемент оказался “прижатым” к началу ячейки. Это дает нам возможность локализовать его и работать с ним. Но для этого нужно знать длину элемента в битах.
  2.  Сдвиг вправо производится с помощью команды сдвига shr.
  3.  Ассемблер содержит оператор width, который позволяет узнать размер элемента записи в битах или полностью размер записи. Варианты применения оператора width:

width имя_элемента_записи ;значением оператора будет размер элемента в битах.

width имя_экземпляра_записи

или

width имя_типа_записи ;значением оператора будет размер всей записи в битах.

 mov al,width i2

...

mov ax,width iotest

  1.  Ассемблер содержит оператор mask, который позволяет локализовать биты нужного элемента записи. Эта локализация производится путем создания маски, размер которой совпадает с размером записи. В этой маске обнулены биты на всех позициях, за исключением тех, которые занимает элемент в записи.
  2.  Сами действия по преобразованию элементов записи производятся с помощью логических команд.

Теперь у вас есть вся информация о средствах ассемблера для работы с записями.

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

Ваша задача — закодировать эти алгоритмы тем или иным способом в соответствии с требованиями задачи.

Выделение элемента записи:

  1.  Поместить запись во временную память — регистр (8, 16 или 32-битный в зависимости от размера записи).
  2.  Получить битовую маску, соответствующую элементу записи, с помощью оператора mask.
  3.  Локализовать биты в регистре с помощью маски и команды and.
  4.  Сдвинуть биты элемента к младшим разрядам регистра командой shr. Число разрядов для сдвига получить с использованием имени элемента записи.

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

Работа с элементом записи:

Как мы уже выяснили, с элементами записи производятся любые действия, как над обычной двоичной информацией.

Единственное, что нужно отслеживать, — это размер битового поля. Если, к примеру, размер поля увеличится, то впоследствии может произойти случайное изменение соседних полей битов. Поэтому желательно исключить изменение размера поля.

Помещение измененного элемента на его место в запись:

  1.  Используя имя элемента записи в качестве счетчика сдвигов, сдвинуть влево биты элемента записи.
  2.  Если вы не уверены в том, что разрядность результата преобразований не превысила исходную, можно выполнить “обрезание” лишних битов, используя команду and и маску элемента.
  3.  Подготовить исходную запись к вставке измененного элемента путем обнуления битов в записи на месте этого элемента. Это можно сделать путем наложения командой and инвертированной маски элемента записи на исходную запись.
  4.  С помощью команды or наложить значение в регистре на исходную запись.

В качестве примера рассмотрим листинг 8, который обнуляет поле i2 в записи iotest.

Листинг 8. Работа с полем записи

;prg_12_7.asm

masm

model small

stack 256

iotest record i1:1,i2:2=11,i3:1,i4:2=11,i5:2=00

.data

flag iotest <>

.code

main:

mov ax,@data

mov ds,ax

mov al,mask i2

shr al,i2 ;биты i2 в начале ax

 and al,0fch ;обнулили i2

;помещаем i2 на место

 shl al,i2

mov bl,[flag]

xor bl,mask i2 ;сбросили i2

or bl,al ;наложили

exit:

 mov ax,4c00h ;стандартный выход

int 21h

end main  ;конец программы

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

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

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

Последнее означает, что эти команды внешне имеют формат обычных команд ассемблера, но после трансляции они приводятся к одной или нескольким машинным командам.

Введение этих команд в язык TASM повышает наглядность работы с записями, оптимизирует код и уменьшает размер программы.

Эти команды позволяют скрыть от программиста действия по выделению и установке отдельных полей записи (мы их обсуждали выше).

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

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

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

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

Работа команды setfield заключается в следующем. Местоположение записи определяется операндом назначение, который может представлять собой имя регистра или адрес памяти.

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

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

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

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

В регистр, указанный операндом регистр_назначение, помещается результат работы команды — значение элемента записи.

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

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

Листинг 9. Работа с полями записи

;prg_12_8.asm

masm

model small

stack 256

iotest record

i1:1,i2:2=11,i3:1,i4:2=11,i5:2=00

.data

flag iotest <>

.code

main:

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,bl

exit:

mov ax,4c00h ;стандартный выход

int 21h

end main ;конец программы

Результат работы команд setfield и getfield удобнее всего изучать в отладчике.

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

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

Это описание регистра eflags. Для удобства мы разбили это описание на три части:

  1.  eflags_1_7 — младший байт eflags/flags;
  2.  eflags_8_15 — второй байт eflags/flags;
  3.  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=0

eflags_l_15 record

c15:1=0,nt14:1=0,iopl:2=0,of11:1=0,df10:1=0,if9:1=1,tf8:1=0

eflags_h record

c:13=0,ac18:1=0,vm17:1=0,rf16:1=0

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


 

А также другие работы, которые могут Вас заинтересовать

52134. Дидактичний матеріал для рівневого навчання 520.5 KB
  Опрацювавши матеріали розділу учні зможуть упізнавати функції встановлювати умови при яких вони мають певні властивості за однією властивістю “бачити †інші зводити розв’язування задач до розв’язування відомих.
52135. ЗАСТОСУВАННЯ РІЗНИХ СПОСОБІВ ДО РОЗКЛАДУ МНОГОЧЛЕНА НА МНОЖНИКИ 37 KB
  Ще 2400 років тому Конфуцій сказав: Слайд 1. Тема нашого журналістського розслідування : Слайд 2. Слайд 3. Запитання для інтерв'ю: Що таке многочлен Що означає розкласти многочлен на множники Які є способи розкладу многочленна на множники Які формули скороченого множення ви знаєте В чому суть способу винесення спільного множника за дужки В чому суть способу групування Слайд 4.
52136. Розвязування задач за допомогою систем лінійних рівнянь з двома невідомими 68.5 KB
  Учащиеся объединены в три группы По команде учителя ученики из каждой группы по одному подходят к соответствующей доске и составляют формулу какая команда быстрее. Ответьте на вопросы предварительно обсудив в группах прием вертушка учащиеся могут переходить из одной группы в другую: Приведите пример линейного уравнения с двумя переменными. Для 1й группы: Дефицит железа сказывается на росте и устойчивости к инфекциям. Для 2й группы: Таблица: Курение – одна из вреднейших привычек...
52137. Застосування властивостей степеня з натуральним показником 179.5 KB
  Тема уроку: Застосування властивостей степеня з натуральним показником Очікувані результати: Після цього уроку учні зможуть: застосовувати властивості степеня з натуральним показником при спрощенні виразів і розв’язуванні рівнянь; користуватися властивостями степеня при визначенні значень числових виразів та при порівнянні чисел; застосовувати властивості степеня з натуральним...
52138. Використання формул квадрата двочлена при розвязуванні вправ 96.5 KB
  Обладнання: карта походу карткизавдання портрет Евкліда. Тож завдання наступне виконуємо в парах. До кожного завдання вказані чотири відповіді одна з яких правильна. Ваше завдання скласти це слово.
52139. Розвязування квадратних рівнянь 139.5 KB
  Мета уроку. Навчальна складова мети формування предметних компетенцій: удосконалювати вміння застосовувати набуті раніше знання до розв’язування вправ. Розвивальна складова мети розвиток навичок мислення високого рівня: розвивати навички розуміння використання аналізу синтезу оцінювання.
52140. Розвязування рівнянь 120.33 KB
  Мета уроку: Розв’язувати найрізноманітніші рівняння, що відрізняються за тематикою і аналіз ситуації у яких припускаються найбільш поширені помилки; підвищення строгості математичних міркувань; виховувати увагу культуру математичного мовлення кмітливість. В історії розвитку математичних софізмі зіграли суттєву роль. Корекція вмінь та навичок учнів з теми через розв’язування рівнянь.
52141. Квадратные уравнения. Решение квадратных уравнений 325 KB
  Тема урока: Решение квадратных уравнений. Квадратные уравнения находят широкое применение при решении тригонометрических показательных иррациональных уравнений и неравенств используются при решении задач по химии и физике. Мы изучили с вами формулы корней квадратных уравнений с помощью которых можно решить любое квадратное уравнение. Однако имеются и другие приемы решения квадратных уравнений которые позволяют очень быстро и рационально решать их.
52142. Найпростіші перетворення графіків функцій 61.5 KB
  Учні самі розподіляються хто яку роботу виконує. Один учень виконує роботу на листі А4. Один учень виконує роботу на листі А4. Один учень виконує роботу на листі А4.