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

Анотация

Здесь приводятся описание макросов для работы с кучей heap.mac.



Данный файл содержит описания макросов для работы со списковыми структурами данных (выделение из кучи и возврат в неё памяти, переход к предыдущему и последующему элементам и др.). Списки могут быть кольцевыми или линейными, одно- или двунаправленными, состоящими из элементов фиксированного или переменного размера. Элементы списков помимо прочего могут содержать указатели на динамически выделяемые блоки памяти и подсписки, подобно головной структуре.

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


Перед началом работы создаётся «головной элемент», содержащий информацию о размере области, отводимой под кучу, указатели на некоторые (обычно первые) элементы списков и др. К головному элементу может добавляться дополнительная область памяти содержащая какую-либо специфическую информацию, которую неудобно размещать в структуре.

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

Рис. 1. Структура памяти в куче.

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

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

LInitHeap MainStruc, ebx, 10240 ; Установить кучу размером 10 кБ, в месте, на кторое
; указывает ebx, с основной структурой MainStruc
LInitHeap MainStruc, MainAddr, ebx, , 4 ; Установить по метке MainAddr кучу с головной структурой
; MainStruc, в которой первые четыре указателя устанав-
; ливаются пустыми. Размер кучи указан в ebx

Следующий макрос формирует головной элемент в памяти, устанавливает список свободных элементов, и устанавливает пустые ссылки в первых Fnill элементах структуры SN.

При использовании Fnill ES и DS должны указывать на один и тот же сегмент.

LInitHeap macro SN, LBMN:REQ, SHeap:REQ, SizExt:=<0>, Fnill, SFree:=<0>

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

mov [указатель_на_головной_элемент].LUsD.поле_структуры_пользователя, данные

указатель_на_головной_элемент — метка или ссылка в базовом регистре.


Элемент списка в общем случае выглядит так

Здесь SN — некоторая структура данных, её имя используется как имя типа; reg — один из РОНов. «Размер данного элемента списка» включает размер заголовка, размер структуры элемента и размер памяти, выделенной после структуры.

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

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

mov [Reg].поле_структуры, данные

Обращение к пользовательской части заголовка элемента списка или блока:

mov [Reg-L?&SN&?ExtHd].поле_структуры, данные

Перед использованием операций над элементами списков и подсписков (переходы от одного элемента к другому, выделение и возврат памяти и т. п.), должны быть определены типы списков и подсписков с помощью макросов LDefType и LDefSubType.

Примеры вызова этих макросов

LDefType StrucName1, 1,, Circle ; Определяет однонаправленный циклический список со структурой
; фиксированного размера StrucName1
LDefType StrucName2, 2, variable ; Определяет двунаправленный линейный список со структурой StrucName2.
; Отдельные элементы этого списка могут иметь различный размер.
LDefSubType StrucName2, FldPoint, 1,, ItsTable ; Указывает, что поле FldPoint структуры
; StrucName2 — таблица ссылок на элементы (тип Б или В),
; образующие однонаправленные линейные списки.

Макросы, описанные в данном файле, предполагают, что каждый список состоит из однотипных элементов, имеющих заголовок, структуру данных SN, и (необязательно) дополнительную область памяти, размер которой может меняться от элемента к элементу. Тип описывается с помощью макроса LDefType. SN является и именем структуры данных, используемых программистом, и именем типа списка. Если требуется создать списки с разным способом доступа к отдельным элементам (например, циклический однонаправленный и линейный двунаправленный) с одинаковой структурой данных, то следует описать её в двух разных структурах данных SN. При описании можно использовать директиву equ:

SN1 struc
.
.
ends
SN2 equ SN1

Далее, можно описать два разных типа SN1 и SN2. В памяти может создаваться несколько списков с одинаковой структурой данных SN и одинаковым методом доступа. Заголовок элемента формируется на основе значений числа направлений в списке dir и величины дополнительной неструктурированной памяти Addmem.

Вход:

LDefType macro SN:Req, Direct:Req, Addmem:=<0>, Circle, ExtHd:=<0>

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

LDeclareBegin SN:req, ListN:req

LDeclare ListN1

LDeclareEnd

Вход:

LDeclareBegin macro SN:req, ListN:req

LDeclare macro ListN1

LDeclareEnd macro

В ряде случаев целесообразно создавать список ещё на этапе трансляции программы. Например, если разрабатывается интерпретатор, то на момент начала работы ему уже должен быть известен определённый набор имён функций, который по мере обработки текста программы может постепенно пополняться новыми терминами. Формирование списков на этапе трансляции обеспечивается макросами LDeclareBegin, LDeclare и LDeclareEnd.

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

Пример испльзования макросов

LDeclareBegin    SN, L1 ; Объявление начала списка
; SN — тип списка, определённый ранее макросом LDefType
; L1 — метка начала списка
LDeclare ; Объявление начала первого элемента
dd ; Заполнение структуры пользовательской части заголовка (если
. ; она предусмотрена в определении типа)
. ; Заполнение структуры данных SN
.
dd ; Заполнение дополнительного блока памяти (если он предусмотрен
; в определении типа элемента)
LDeclare ; Объявление начала следующего элемента
dd ; Заполнение пользовательской части заголовка
. ; Заполнение структуры и дополнительной области памяти
.
dd
LDeclare L2; Объявление начала следующего элемента
; L2 — метка, по которой можно обращаться к данному элементу
dd ; Заполнение пользовательской части заголовка
. ; Заполнение структуры и дополнительной области памяти
.
dd
LDeclareEnd ; Объявление окончания списка

Вложенность и пересечение списков LDeclareBeginLDeclareEnd не допускается. Если между двумя вызовами LDeclareBegin не стоит LDeclareEnd, то выдаётся сообщение об ошибке. Метки L1 и L2 относятся к началу области пользовательских данных элемента, поэтому записи

mov ebx, offset L1
LGetNext ebx, SN
mov ebx, offset L2
LGetNext ebx, SN

дадут правильный результат.

Ниже приведён макрос выделения памяти заданного размера.

Важно! В принципе макрос позволяет выделить память объёмом в один байт, но возвращать в кучу память объёмом менее восьми (8) байт опасно, т. к. при этом велика вероятность (около 100 %) разрушения списковой структуры.

Вход:

Выход: EBX — указатель на выделенный блок памяти.

Портятся регистры EAX, EDX.

Данный макрос должен быть оформлен в программе как процедура LGetmem для использования макросов выделения памяти и в простейшем случае может выглядеть следующим образом

LGetmem proc ; вход: ECX — требумый размер блока памяти
; выход: EBX — указывает на начало выделенного участка памяти
; CF=0 — всё в порядке, CF=1 — блок памяти не выделен.
          LGetm LBMN, ErGet, OKget
OKget:
          clc
          ret
ErGet:
          stc
          ret
endp
Следующий макрос освобождает блок памяти объёмом ECX с начальным адресом, указанным в EBX. Важно! Возвращать в кучу память объёмом менее 8 байт опасно, т. к. при этом велика вероятность разрушения списковой структуры. Вход: eсx-высвобождаемый объём ОЗУ ds-сегмент кучи ebx-адрес, высвобождаемой озу LBMN — метка или индексный регистр (любой, кроме edx), в котором находится ссылка на головной элемент. Выход: Нет Используется: eax, ebx, ecx, edx, edi, eflags

LGetm macro LBMN:Req, exer:Req, OK:Req

Данный макрос очень объёмен и потому должен быть оформлен как процедура LFreemem, например, так

LFreemem proc ; Вход: ECX — размер возвращаемого блока ОЗУ
; EBX — указатель на начало возвращаемого блока ОЗУ
          LFreem LBMN
          ret
endp

LFreem macro LBMN:Req

Макрос выделяет память под элемент типа SN Вход: SN — тип списка, для которого выделяется память AddSize — дополнительная память, используется, если элемент требует её наличия желательно указывать в ecx Выход: ebx — указатель на элемент, если память была выделена, или переход по метке ExErr, если память не была выделена. Портит ecx (содержит размер элемента).

LGetEl macro SN:Req, AddSize, ExErr:Req

Макрос выделяет память для блока типа TypeBlock Вход: BlockName — Имя типа блока, может быть опущено. BlockSize — требуемый размер блока. Указывается для блоков переменного размера или нетипизированных блоков. В последнем случае он ДОЛЖЕН БЫТЬ НЕ МЕНЕЕ 8 байт. Для корреции размера можно пользоваться макросом LCorrectSize. Выход: ebx — указатель на элемент, если память была выделена, или переход по метке ExErr, если память не была выделена. Портит ecx (содержит размер элемента).

LGetBlock macro BlockName, BlockSize, ExErr:Req

Макрос возвращает память, занятую элементом типа TypeEl в кучу Вход: TypeEl — тип элемента ebx — указатель на элемент, который нужно вернуть в кучу. Выход: Нет Портит: ebx, ecx.

LFreeEl macro SN:Req

Макрос возвращает память, занятую элементом типа TypeBlock в кучу Вход: BlockName — имя типа блока, если отсутствует, значит блок не типизированный и должен быть указан параметр BlockSize. BlockSize — Размер блока памяти, который надо освободить, используется, только для нетипизированных блоков ebx — указатель на элемент, который нужно вернуть в кучу. Выход: Нет Портит: ebx, ecx.

LFreeBlock macro BlockName, BlockSize

Память выделяется под элемент списка (или блок динамической памяти) по вызову макроса LGetEl (или LGetBlock) и в дальнейшем изменяться не может, только, если элемент удаляется макросом LFreeEl (или для блоков LFreeBlock. Эти макросы вызывают процедуры LGetmem и LFreemem, которые должны быть описаны в программе пользователя. В простейшем случае описание должно выглядеть следующим образом

LGetmem proc LFreemem proc
push eax push eax
push edx push edx
LGetm LBMN, ErGet,OKget push edi
OKget: clc ; Память выделена LFreem LBMN
pop edx pop edi
pop eax pop edx
ret pop eax
ErGet: add esp, 8 ret
stc ; Сообщить об ошибке endp
ret
endp

где LGetm, LFreem — макросы, уже описанные в данном файле. Примеры использования некоторых макросов:

Выделить память под элемент.
LGetEl StrucName1
LGetEl StrucName2, SizeStrucName ; где SizeStrucName — размер дополнительной
; ОЗУ, выделяемой после структуры списка

Следующие ниже обозначения являются общими для всех приводимых ниже макросов

Размер блока с учётом заголовка (если есть) должен быть не меньше 8 байт! Иначе при его возврате в кучу может быть нарушена структура списков. Блоки могут быть типизированными и нетипизированными. Для типизированных блоков фиксированного размера, размер увеличивается до 8 байт автоматически, для нетипизированных блоков и блоков переменного размера, он должен корректироваться программистом, например, с помощью макроса LCorrectSize. Типизированные блоки, в отличие от нетипизированных, определяются с помощью макроса LDefBlockType, и к типизированным блокам может быть применён макрос LDefSubType, а к нетипизированным — нет.

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

Рис. Примерные виды списков: P — указатель; D — к-л данные.
Рис. Типы элементов, поддерживаемые данным файлом макросов.

Здесь P— указатель на элемент подсписка; PN— Указатель на следующий элемент подсписка, PP— указатель на предыду- щий элемент списка; Fld — поле, являющееся ссылкой или массивом ссылок; IReg— один из РОНов, содержащий номер ин- тересующей ссылки в массиве ссылок, на начало которого указывает Fld. Размер одной ссылки 4 байта. Если использует- ся двунаправленный список, то все ссылки сдвоенные (т. е. размер одного вхождения — 8 байт), указывают на сле- дующий и на предыдущий элементы. Перед таблицей ссылок может размещаться необязательное однобайтовое поле, содержа- щее количество ссылок в таблице (при этом количество ссылок (одно- или двунаправленных) должно лежать в пределах от 1 до 256 иначе они не поместятся в поле). Поле LapTabl должно быть описано в структуре SN в байте, пред- шествующем началу таблицы ссылок. Использовать поле имеет смысл только при динамическом определении количества ссы- лок. При статическом определении можно использовать более 256 ссылок. Проверка, выходит ли индекс за размер таблицы осуществляется макросом LChckInd, который должен указываться перед макросами, обращающимися к таблицам ссылок.

Пример:

LDefType SN1, 1
LDefSubType SN1, Fld1, 2, No, ItsTable, variable
.
.
.
LChckInd SN1, Fld1, ebx, ExErr_OutOfRange, edx, dl ; Проверка границы
LGetSubNext SN1, Fld1, ebx, ExErr_NoSubItem, edx ; Переход к вхождению

Данный макрос определяет тип ссылок на элементы подсписков для типов подсписков Б и В.

Вход:

LDefSubType macro SN:Req, Fld:Req, Direct:Req, Circle, ItsTable, LapTablS

Макрос предназначен для определения типа блока, чтобы можно было использовать ссылки на другие подсписки (при совместном использовании с LDefSubType) и для автоматизации выделения памяти

LDefBlockType macro BlockName:REQ, BlockSize:=<variable>, ExtHd:=<0>

Переходы от одного элемента к другому осуществляются с помощью макросов LGetNext и LGetPred (последний может использоваться только для двунаправленных списков):

LGetNext ebx, StrucName1 ; ebx указывает на элемент StrucName1. Макрос осуществляет
; переход к следующему элементу StrucName1
LGetPred ebx, StrucName2, ErrHeap ; ebx указывает на элемент StrucName2. Макрос осуществляет переход к предыдущему
; элементу StrucName2, или, если предыдущий элемент не существует, выход по метке ErrHeap

Переходы от одного элемента к другому в многомерных и ветвящихся подсписках, а также вход в иерархические подсписки осуществляются с помощью макросов LGetSubNext и LGetSubPred (последний может использоваться только для двунаправленных подсписков):

LGetSubNext ebx, StrucName2, FldPoint, ErrHeap, edx ; ebx указывает на элемент StrucName2.
; Макрос осуществляет переход к элементу подсписка,
; на который указывает FldPoint, или, если предыдущий
; элемент не существует, выход по метке ErrHeap

Следующие макросы описывают переходы к следующему элементу списка типа А (LGetNext), а также к входу в подсписок типа Б и к переходу к следующему элементу многомерного списка типа В (LGetSubNext).

Для макроса LGetSubNext должны дополнительно указываться следующие параметры

IReg — индексный регистр, содержащий номер интересующей ссылки в таблице ссылок Fld. Необходим и используется только в том случае, когда Fld является не единичной ссылкой, а таблицей ссылок. Может быть также смещением ссылки в Fld (числом).

LGetNext macro SN:Req, Reg:=<ebx>, exer:Req ; Переход к следующему элементу списка типа А

LGetSubNext macro SN:Req, Fld:Req, Reg:=<ebx>, exer:Req, IReg ; Переход к следующему

Следующие макросы осуществляют переход к предыдущему элементу, могут применяться только к двунаправленным спискам (LGetPred) и к двунаправленным многомерным спискам типа В (LGetSubPred).

Для макроса LGetSubPred должны дополнительно указываться следующие параметры

IReg — индексный регистр, содержащий номер интересующей ссылки в таблице ссылок Fld. Необходим и используется только в том случае, когда Fld является не единичной ссылкой, а таблицей ссылок. Может быть также смещением ссылки в Fld (числом).

LGetPred macro SN:Req, Reg:=<ebx>, exer ; Переход к предыдущему элементу

LGetSubPred macro SN:Req, Fld:Req, Reg:=<ebx>, exer, IReg ; Переход к предыдущему элементу подсписка

Следующие макросы описывают загрузку указателей на следующий элемент списка типа А (LLoadNext) в регистр, а также на элемент подсписка типа Б или на следующий элемент многомерного списка типа В (LLoadSubNext).

Вход:

Выход:

Для макроса LGetSubNext должны дополнительно указываться следующие параметры

IReg — индексный регистр, содержащий номер интересующей ссылки в таблице ссылок Fld. Необходим и используется только в том случае, когда Fld является не единичной ссылкой, а таблицей ссылок. Может быть также сме- щением ссылки в Fld.

LLoadnext macro SN:Req, LReg:Req, Reg:Req, NoEl ; Переход к следующему элементу списка типа А

LLoadSubNext macro SN:Req, Fld:Req, LReg:Req, Reg:Req, NoEl, IReg ; Переход к следующему

Следующие макросы осуществляют загрузку указателя на предыдущий элемент в регистр, могут применяться только к двунаправленным спискам (LGetPred) и к двунаправленным многомерным спискам типа В (LGetSubPred).

Для макроса LGetSubPred должны дополнительно указываться следующие параметры

LLoadPred macro SN:Req, LReg:Req, Reg:Req, NoEl ; Переход к предыдущему элементу

LLoadSubPred macro SN:Req, Fld:Req, LReg:Req, Reg:Req, NoEl, IReg ; Переход к предыдущему

Включение и исключение элементов из списка выполнют, соответственно, макросы LIncEl и LExcEl.

LIncEl StrucName1 ; StrucName1 — имя типа элемент, ebx — вставляемый элемент
; ecx — элемент списка, после которого нужно вставить элемент ebx

Включение и исключение элементов из многомерных списков (тип В) выполнют, соответственно, макросы LIncSubEl и LExcSubEl

LExcSubEl StrucName2, FldPoint, edi ; StrucName2 — имя типа элемент
; ebx — исключаемый элемент
; edx — элемент списка, после которого нужно исключить элемент ebx
; FldPoint — Имя поля, которое является массивом ссылок
; edi — регистр, содержащий индекс интересующей ссылки в массиве FldPoint.

Макросы вставки элементов в списки (LIncEl) и многомерные подсписки типа В (LIncSubEl)

В списке (подсписке) до вставки должно присутствовать не меньше одного элемента.

Портит регистр EAX

Для макроса LIncSubEl должны дополнительно указываться следующие параметры

IReg — индексный регистр, содержащий номер интересующей ссылки в таблице ссылок Fld. Необходим и используется только в том случае, когда Fld является не единичной ссылкой, а таблицей ссылок. Может быть также смещением ссылки в Fld (числом).

Данный макрос не предназначен для работы с обычными подсписками (тип Б). Подсписки могут быть только многомерными (тип В). Портит eax

LIncEl macro SN:Req ; Вставка элемента в список

LIncSubEl macro SN:Req, Fld:Req, IReg ; Вставка элемента в подсписок

Макросы вставки элементов в списки (LExcEl) и многомерные подсписки типа В (LExcSubEl) В списке (подсписке) до вставки должно присутствовать не меньше 1 элемента.
  • [EBX] — указатель на исключаемый элемент
  • [EDX] — указатель на предыдущий элемент списка. Необходим, если только список не является двунаправленным, иначе загружается в edx из элемента, на который указывает ebx.
  • Если список — циклический, и элемент в нём — последний, то элемент исключён не будет. Портится EAX, при работе с двунаправленными списками EDI в списке должно быть минимум два элемента. Предыдущий элемент обязательно должен существовать, т. к. проверка его существования макросом не производится.

    Для макроса LExcSubEl должны дополнительно указываться следующие параметры.

    LExcEl macro SN:Req ; Исключить элемент из списка

    LExcSubEl macro SN:Req, Fld:Req, IReg ; Исключить элемент из подсписка

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

    Вход:

    LIncFirst macro SN:req, Reg1:=<ebx>, Reg2:req

    LIncSubFirst macro SN:req, Fld:req, Reg1:=<ebx>, Reg2:req, IReg:=<0>

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

    Вход:

    1. Reg1 — Элемент, который должен быть вставлен, по умолчанию [ebx];
    2. Reg2 — Последний элемент списка;
    3. IReg — индексный регистр, содержащий номер интересующей ссылки в таблице ссылок Fld. Необходим и используется только в том случае, когда  ld является не единичной ссылкой, а таблицей ссылок. Может быть также смеще- нием ссылки в Fld.

    LIncLast macro SN:req, Reg1:=<ebx>, Reg2:req

    LIncSubLast macro SN:req, Fld:req, Reg1:=<ebx>, Reg2:req, IReg:=<0>

    Выполняет исключение первого элемента из линейного списка.

    Вход:  eg1 — Указатель на исключаемый элемент. Обязателен. Reg2 — Регистр, в который будет занесён указатель на второй элемент. Обязателен. Если второй элемент не существует, то Reg2=Nill Skp — Метка, по которой может быть осуществлён переход, если второй элемент не существует. Необязательный параметр. IReg — индексный регистр, содержащий номер интересующей ссылки в таблице ссылок Fld. Необходим и используется только в том случае, когда Fld является не единичной ссылкой, а таблицей ссылок. Может быть также сме- щением ссылки в Fld. Выход: Reg2 указатель на следующий элемент, если он существует. Если элемент отсутствует, то Reg2=Nill, если при этом указана метка Skp, то о ней будет выполнен переход.

    LExclFirst macro SN:Req, Reg1:Req, Reg2:Req, Skp

    LExclSubFirst macro SN:Req, Fld:req, Reg1:Req, Reg2:Req, Skp, IReg:=<0>


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

    mov [reg_1].имя_поля, reg_2

    где reg_2 — указывает на элемент подсписка, который надо включить.

    Для контроля попадания

    LChckInd StrucName2, FldPoint, ebx, edx, dl, ExErr

    Замечание. После входа в подсписок (тип Б) перемещения внутри него должны происходить с помощью макросов LGetNext и LGetPred. В списках типа "В" — с помощью LGetSubNext и LGetSubPred.

    Проверка попадания индекса в пределы таблицы ссылок

  • PReg — регистр, указывающий на элемент;
  • IReg — индекс (регистр) в таблице ссылок;
  • LIReg — младший байт индексного регистра, нужен только когда массив ссылок имеет переменный размер;
  • ExErr — метка, по которой должен осуществляться переход, если индекс выходит за границу таблицы.
  • Изменяемые регистры: Flags

    Особенности работы: Если ExErr не указан, то после выполнения макроса флаги установлены таким образом, что по ко- манде 'ja xxx' будет выполнен переход в том случае, если индекс выходит за пределы таблицы, а по команде 'jbe xxx', если не выходит. Если размер памяти, отводимой под таблицу ссылок, выделяется динамически, т. е. перед таблицей имеется поле размера, и метка ExErr не указана, то проверке подвергается только младший байт регистра, что может быть использовано в тех случаях, когда заведомо известно, что индекс помещённый в IReg не превышает 255 (например, когда индекс заносится командой movzx).

    LChckInd macro SN:REQ, Fld:REQ, Reg:=<ebx>, ExErr, IReg:REQ, LIReg:REQ

    Макрос устанавливает ссылки в элементе списка так, как если бы он был первым и единственным элементом в списке

    1. Reg — регистр, указывающий на элемент
    2. IReg — индексный регистр, содержащий номер интересующей ссылки в таблице ссылок Fld. Необходим и используется только в том случае, когда Fld является не единичной ссылкой, а таблицей ссылок. Может быть также смещением ссылки в Fld.

    LMakeFirstEl macro SN:Req, Reg:=<ebx>

    LMakeSubFirstEl macro SN:Req, Fld:Req, Reg:=<ebx>, IReg:Req

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

    Вход:

    Выход: Flags — Если элемент последний, то флаги установлены так, что по команде "je xxx", выданной после макроса, будет выполнен переход по метке "xxx".

    LChckLast macro SN:REQ, Reg:=<ebx>

    LChckSubLast macro SN:REQ, Fld:req, Reg:=<ebx>, IReg:=<0>

    Проверяет, является ли элемент первым в списке (подсписке). Используется только для линейных двунаправленных списков. Если ссылка на предыдущий элемент пустая, то элемент — первый.

    Вход: Reg — регистр, указывающий на элемент, по умолчанию [ebx] IReg — индексный регистр, содержащий номер интересующей ссылки в таблице ссылок Fld. Необходим и используется только в том случае, когда Fld является не единичной ссылкой, а таблицей ссылок. Может быть также сме- щением ссылки в Fld. Выход: Flags — Если элемент первый, то флаги установлены так, что по команде "je xxx", выданной после макроса, будет выполнен переход по метке "xxx".

    LChckFirst macro SN:REQ, Reg:=<ebx>

    LChckSubFirst macro SN:REQ, Fld:req, Reg:=<ebx>, IReg:=<0>

    Проверяет размер затребованной ОЗУ и, если надо, корректирует его. Если размер запрашиваемой ОЗУ меньше 8 байт, то он приравнивается 8 байтам.

    Вход: ReqSize — регистр или память, содержащий затребованный объём ОЗУ

    Выход:

    LCorrectSize macro ReqSize:req, JNoCorrect




    ©   Жуков И. Б.

    e-mail:

    При использовании материалов, пожалуйста,

    ставьте индексируемую ссылку на сайт https://ibzh.eko3.ru/





    Число посетителей


    Яндекс.Метрика

    Число посетителей