Справочник по языку Ассемблера IBM PC

     

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


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

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

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

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



    mov al,width i2 ... mov ax,width iotest

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

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

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


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


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

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


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

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


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

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


  • В качестве примера рассмотрим листинг 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 ;конец программы

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




    Содержание раздела