mov eax, -1 ; Заносим в регистр EAX предварительное значение результата
xor edx, edx ; Обнуляем регистр EDX
L1: mov dl, [ebx] ; Заносим в регистр DL очередной символ
test edx, edx ; Проверяем значение в регистре EDX
jz E1 ; Если EDX = 0, выходим из цикла
inc ebx ; Меняем адрес символа
cmp dl, '(' ; Сравниваем символ с открывающей круглой скобкой
je L2 ; Если равно, ...
cmp dl, '[' ; Сравниваем символ с открывающей квадратной скобкой
je L2 ; Если равно, ...
cmp dl, ')' ; Сравниваем символ с закрывающей круглой скобкой
je L3 ; Если равно, переходим к сравнению со скобкой из стека
cmp dl, ']' ; Сравниваем символ с закрывающей квадратной скобкой
je L4 ; Если равно, переходим к сравнению с другой скобкой из стека
jmp L1 ; Если символ – не скобка, возвращаемся к началу цикла
L2: push dx ; ... заносим открывающую скобку в стек (один байт записать в стек нельзя)
jmp L1 ; Возвращаемся к началу цикла
L3: cmp ebp, esp ; Если была закрывающая скобка, прежде всего проверяем, есть ли скобки в стеке –
; если мы положили что-то в стек, значение регистра ESP будет отличаться от регистра EBP
je E2 ; Если значения регистров равны, выходим из процедуры
pop cx ; Извлекаем из стека последнюю открывающую скобку
cmp cl, '(' ; Сравниваем
jne E2 ; Если скобки не равны, выходим из процедуры
jmp L1 ; Иначе возвращаемся к началу цикла
L4: cmp ebp, esp ; При нахождении закрывающей квадратной скобки,
je E2 ; выполняем те же действия, что и при нахождении закрывающей круглой скобки,
pop cx ; только скобку из стека сравниваем с другим значением
cmp cl, '[' ; Дублирование сделано для того, чтобы уменьшить
jne E2 ; количество переходов
jmp L1
E1: cmp ebp, esp ; При достижении конца строки, сравниваем регистры ESP и EBP
je E3 ; Если значения равны, обходим обнуление регистра EAX
E2: xor eax, eax ; Если была несбалансированность, обнуляем регистр EAX
E3: mov esp, ebp ; Восстанавливаем значение регистра ESP
pop ebp
pop ebx
ret
Brackets endp
1 В защищённом режиме программе выделяется один сегмент размером 4 Гб для кода и один сегмент размером 4 Гб для данных (физически они обычно совпадают). Виртуальный адрес состоит из 16-битного значения, хранящегося в сегментном регистре, и 32-битного смещения. Однако преобразование виртуального адреса в физический осуществляется не путём сложения, а по более сложной схеме. Сначала процессор преобразует виртуальный адрес в линейный. При этом он обращается к таблицам дескрипторов, которые заранее строятся операционной системой. На втором этапе по линейному адресу определяется физический. В этом преобразовании участвует другой набор системных таблиц – таблицы страничной трансляции, которые также составляются операционной системой. Оба набора таблиц могут динамически меняться, обеспечивая максимальное использование оперативной памяти.
В сегментные регистры записываются не адреса сегментов, а селекторы, которые представляют собой номера ячеек специальной таблицы, содержащей дескрипторы сегментов программ. Каждый дескриптор хранит все характеристики, необходимые для обслуживания сегмента: базовый линейный адрес сегмента, границу сегмента (номер последнего байта), а также атрибуты сегмента, определяющие его свойства. Процессор с помощью селектора определяет индекс дескриптора адресуемого сегмента, извлекает из него базовый линейный 32-битный адрес сегмента и, сложив его с 32-битным смещением, получает линейный адрес адресуемой ячейки памяти. Получив линейный адрес адресуемого байта, процессор с помощью таблиц трансляции преобразует его в 32-битный физический адрес. Этот адрес зависит от объёма оперативной памяти, установленной на компьютере.
В 32-битной модели Windows предоставляет всем запущенным приложениям один и тот же селектор для сегмента кода и один и тот же селектор для сегмента данных. Базы обоих сегментов равны 0, а границы – FFFFFFFF. Другими слова, каждому приложению как бы предоставляется всё линейное пространство. Поскольку базовые линейные адреса сегментов программы равны 0, виртуальные смещения, с которыми работают приложения, совпадают с линейными адресами. Другими словами, плоское виртуальное адресное пространство программы совпадает с плоским линейным адресным пространством. При этом все приложения используют один и тот же диапазон линейных адресов. Для того чтобы при одинаковых линейных адресах приложения занимали различные участки физической памяти и не затирали друг друга, Windows при смене приложения изменяет таблицы страничной трансляции, с помощью которых как раз и происходит преобразование линейных адресов в физические.
2 Если говорить точнее, то относительный адрес перехода отсчитывается не от самой команды перехода, а от следующей за ней команды. Дело в том, что выполнение любой команды начинается с засылки в регистр EIP адреса следующей по порядку команды и только затем выполняется собственно команда. Поэтому в команде перехода относительный адрес будет прибавляться к значению регистра EIP, которое уже указывает на следующую команду, а потому от этой следующей команды и приходится отсчитывать относительный адрес перехода. Однако, в любом случае, программисту нет необходимости самому высчитывать относительный адрес перехода, это делает компилятор языка ассемблера.
3 Компьютерная программа в целом или её отдельная процедура называется реентерабельной (от англ. reentrant – повторно входимый), если она разработана таким образом, что одна и та же копия инструкций программы в памяти может быть совместно использована несколькими пользователями или процессами. При этом второй пользователь может вызвать реентерабельный код до того, как с ним завершит работу первый пользователь и это как минимум не должно привести к ошибке, а в лучшем случае не должно вызвать потери вычислений (то есть не должно появиться необходимости выполнять уже выполненные фрагменты кода).
Для обеспечения реентерабельности необходимо выполнение нескольких условий:
никакая часть вызываемого кода не должна модифицироваться;
вызываемая процедура не должна сохранять информацию между вызовами;
если процедура изменяет какие-либо данные, то они должны быть уникальными для каждого пользователя;
процедура не должна возвращать указатели на объекты, общие для разных пользователей.
В общем случае, для обеспечения реентерабельности необходимо, чтобы вызывающий процесс или функция каждый раз передавал вызываемому процессу все необходимые данные. Таким образом, функция, которая зависит только от своих параметров, не использует глобальные и статические переменные и вызывает только реентерабельные функции, будет реентерабельной. Если функция использует глобальные или статические переменные, необходимо обеспечить, чтобы каждый пользователь хранил свою локальную копию этих переменных.
СРО №2
Тема: Технология ADO.
Цель: Рассмотреть технологию ADО.
Рассматриваемые вопросы:
- Основа архитектуры ADО; Интерфейсы ADО; Компоненты расположенные на закладке ADO.
СРО №3
Тема: Наборы данных. Основные свойства, методы и события.
Цель: Рассмотреть основные свойства, методы и события наборов данных.
Рассматриваемые вопросы:
- Класс TDataSet; Основные механизмы, реализованные в наборе данных; Основные свойства, методы и события наборов данных.
СРО №4
Тема: Создание базы данных «Моя группа».
Цель: Используя приобретенные навыки работы с технологией ADО в Delphi создать базу данных.
Содержание задания:
Приложение базы данныз разработанный в среде Delphi.
|
Из за большого объема этот материал размещен на нескольких страницах:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |


