Что такое low и high паскаль

Что такое low и high паскаль

Для обработки ЭВМ данные представляются в виде величин и их совокупностей. С понятием величины связаны такая важная характеристика, как ее тип.

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

Простые типы данных

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

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

Дополнительные сведения о типах данных..

В Турбо Паскаль ограничения на совместимость типов можно обойти с помощью приведения типов. Приведение типов позволяет рассматривать одну и ту же величину в памяти ЭВМ как принадлежащую разным типам. Для этого используется конструкция Имя_Типа(переменная или значение)

Напрмер, Integer(‘Z’) представляет собой значение кода символа ‘Z’ в двухбайтном представлении целого числа, а Byte(534) даст значение 22, поскольку целое число 534 имеет тип Word и занимает два байта, а тип Byte занимает один байт, и в процессе приведения старший байт будет отброшен.

Волгоградский государственный педагогический университет
Кафедра алгебры, геометрии и информатики

Источник

Функции Low и High

Функции Low и High предназначены для работы с массивами. Функция Low возвращает нижнюю, а функция High – верхнюю границу индексов массива :

X, I, Lower, Upper : Integer;

MyArray : array[10..20] of Integer;

Begin

for I := Lower to Upper do

Применение функций Low и High для работы с массивами – хороший способ избежать ошибок, связанных с выходом индекса за допустимые пределы.

Динамические массивы

При объявлении динамического массива достаточно указать только тип его элементов. Память для размещения его элементов на этом этапе не выделяется. Фактически массив создается только во время выполнения программы. Для этого используется функция SetLength. Как только необходимость в массиве отпадает, следует освободить память вызовом процедуры Finalize. Рассмотрим пример:

BigArray : array of Integer;

Begin

Новый термин. Динамический массив размещается в оперативной памяти во время выполнения программы.

Размер динамического массива можно увеличивать или уменьшать во время выполнения. программы

По окончании использования его следует уничтожить.

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

Для изменения размеров массива используют функцию Copy. Рассмотрим такой пример. Пусть динамический массив BigArray содержит 100 элементов. Нам необходимо увеличить его размер до 200 элементов. Для этого обращаемся к функции Copy:

Предыдущее содержимое (значения элементов) массива остается неизменным, а его размер увеличен до 200 элементов.

Двумерные динамические массивы создаются аналогично. Объявление двумерного динамического массива имеет вид:

BigArray : array of array of Integer;

Begin

SetLength(BigArray, 20, 20);

Строки

Строки в программах используются весьма интенсивно. Object Pascal дает нам три различных строковых типа: длинная строка, короткая строка и расширенная строка. Кроме того, есть строки с терминальным нулем.

Короткая строка

Короткая строка – это строка фиксированной длины с числом символов не более 255. Имеются два способа объявления строк фиксированной длины. В первом случае используется предопределенный тип ShortString, который объявляет строку длиной 255 байт. Во втором случае – ключевое слово string со спецификацией длины:

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

Begin

В этом примере для определения длины строки используется значение S[0]. Можно также воспользоваться функцией Length.

ПРИМЕЧАНИЕ. Для преобразования значения типа Char в целую величину используется функция Ord. Функция Ord также применяется к перечислимым типам.

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

Длинная строка

Строки этого типа относятся к объектам, которые размещаются в памяти динамически. Размер такой строки ограничен лишь доступным объемом оперативной памяти. Object Pascal выделяет и освобождает память для строк рассматриваемого типа по мере необходимости. Длинные строки – очень гибкий тип данных, но операции над ними требуют большего времени. Это объясняется необходимостью перераспределения памяти когда размер строки изменяется. Несмотря на это, в программах следует использовать строки именно этого типа.

Для объявления длинной строки используется ключевое слово string без спецификации длины:

S : string;

Длинные строки не содержат 0–го элемента длины. Попытка прочитать нулевой элемент, обратившись к нему как S[0], будет пресечена на этапе компиляции. Вместо этого надо пользоваться функцией Length чтобы узнать длину строки, или процедурой SetLength – чтобы установить требуемую длину строки. Более подробно об этом – в разделе «Строковые функции».

Источник

Что такое low и high паскаль

Написание любой большой программы невозможно как без разбиения задачи на менее сложные подзадачи, которые мы можем решать независимо, так и без повторного использования ранее написанного кода (представим, что каждая новая программа писалась бы «с нуля»?!). Решить эти важнейшие задачи позволяет механизм подпрограмм, имеющийся в любом языке программирования, в том числе, и в Паскале.

Итак, использование подпрограмм позволяет решить следующие задачи:

· уменьшение размеров кода и экономия памяти за счет возможности неоднократного вызова одной и той же подпрограммы в рамках одной программы;

· лучшее структурирование программы за счет разбиения задачи на более простые подзадачи;

· эффективное повторное использование однажды написанного кода.

Рассмотрим общую структуру сложной программы, содержащей две подпрограммы:

описана вне всех подпрограмм>

описана после заголовка подпрограммы>

Описанная перед телом подпрограммы локальная переменная i не имеет никакого отношения к одноименной переменной, описанной выше. На время выполнения подпрограммы локальная переменная i вытесняет глобальную, делая значение последней недоступной. После завершения подпрограммы значение локальной i будет утеряно, а значение глобальной i никак от этого не изменится. Итак, глобальные переменные видимы (доступны) от точки их определения до конца файла. Локальные переменные доступны только в том блоке операторных скобок, в котором они описаны и во вложенных в него блоках.

18.1. Процедуры

Общий вид подпрограммы-процедуры следующий:

(Список формальных параметров);

var описания локальных переменных;

procedure Equation (a,b,c:real;

Здесь мы попытались решить уравнение ax 2 +bx+c=0, значения a, b, c, ввел пользователь, ответы, если они вычислялись, будут помещены в переменные x1 и x2. При вызове вида

Equation (1,4,-3.5, x 3, x 4);

мы решили уравнение x 2 +4x-3.5=0, а ответы поместили в переменные x3 и x4. Еще один вызов

Equation (4,1,-3.5, x 3, x 4);

позволяет решить уравнение 4x 2 +x-3.5=0, записав ответы в переменные x1 и x2. Наконец, четвертое обращение к процедуре

решает уравнение x 2 +bx=0, помещая ответы в переменные x1 и x3.

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

Табл. 18.1. Соответствие формальных и фактических параметров

Формальный параметр в заголовке процедуры

Соответствующий фактический параметр при вызове процедуры

Переменная некоторого типа данных без ключевого слова var

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

Переменная некоторого типа данных с ключевым словом var

Переменная или элемент массива того же типа данных

procedure p1 (x:integer);

по значению, x по-прежнему равно 3>

procedure p1 (var x:integer);

переданной в качестве x>

оно было изменено процедурой p1>

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

Перейдем к примерам.

Источник

Типы данных Паскаль

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

Что определяют типы данных Паскаль?

Во-первых, возможные значения переменных, функций, выражений, констант принадлежащих к исходному типу; во-вторых, он определяет внутреннюю форму представления данных в ЭВМ; и, в-третьих, определяет функции и операции, выполняющиеся над величинами, которые принадлежат тому или иному типу.

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

Типы данных Паскаль:

В Паскале различают следующие типы данных:

Что такое low и high паскаль. Смотреть фото Что такое low и high паскаль. Смотреть картинку Что такое low и high паскаль. Картинка про Что такое low и high паскаль. Фото Что такое low и high паскаль

В таблице ниже представлены разновидности простых типов данных в Паскале и их характеристики:

Что такое low и high паскаль. Смотреть фото Что такое low и high паскаль. Смотреть картинку Что такое low и high паскаль. Картинка про Что такое low и high паскаль. Фото Что такое low и high паскаль

Для порядковых типов, входящих в группу простых, характерны следующие свойства:

Эквивалентность и совместимость типов данных:

Немаловажное значение в языке Паскаль имеют понятия эквивалентности и совместимости типов. Дадим определения этим понятиям. Два типа TIP1 и ТIP2 называются эквивалентными в случае выполнения одного из условий:

Теперь введем понятие совместимости типов. Типы называются совместимыми, если:

Ограничения на совместимость типов можно обойти при помощи приведения типов:

Что такое low и high паскаль. Смотреть фото Что такое low и high паскаль. Смотреть картинку Что такое low и high паскаль. Картинка про Что такое low и high паскаль. Фото Что такое low и high паскаль

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

После операции приведения типа переменной можно указать один или несколько квалификаторов, если это допускается указанным типом, например, integer(‘Z’) есть значение кода символа ‘Z’ в двух-байтном представлении целого числа, а byte(534) впоследствии даст значение 22, так как целое число 534 обладает типом word и занимает 2 байта, а тип byte занимает 1 байт, и в процессе приведения старший байт окажется отброшенным.

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

Источник

Что такое low и high паскаль

— 12.1. Общее описание МП 8086/8088
— 12.1.1. Регистры
— 12.1.2. Адресация
— 12.1.3. Система команд
— 12.2. Специфика встроенного ассемблера
— 12.2.1. Оператор ASM
— 12.2.2. Синтаксис ассемблерных команд
— 12.2.3. Директивы ассемблера
— 12.2.4. Ассемблерные подпрограммы

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

В этой главе рассматриваются приемы программирования с помощью ассемблера, встроенного в компилятор Турбо Паскаля. Встроенный ассемблер имеется в версиях 6.0 и 7.0 Турбо Паскаля и в руках опытного программиста представляет собой мощный инструмент, позволяющий «выжать» из ПК все возможное.

12.1. ОБЩЕЕ ОПИСАНИЕ МП 8086/8088

Чтобы использовать средства ассемблера, необходимо ясно представлять себе детали архитектуры микропроцессоров Intel 80×86. К этому семейству относятся микропроцессоры:

Микропроцессоры этого семейства наращивают свои возможности в перечисленном порядке, но строго совместимы от младших моделей к старшим: все, что может 8086/8088, реализует и Pentium, но не наоборот. Ниже обсуждается архитектура (внутреннее устройство, способы адресации и система команд) МП 8086/8088.

12.1.1. Регистры

В МП 8086/8088 имеется 14 регистров. В функциональном отношении они делятся на группы:

— регистры общего назначения (АХ, ВХ, СХ, DX); предназначены для хранения операндов и выполнения основных команд; любой из них может использоваться как совокупность двух независящих друг от друга 8-разрядных регистров: старшего байта регистра (АН, ВН, СН, DH) и младшего байта (AL, BL, CL, DL); например, АХ состоит из АН и AL;
— сегментные регистры (CS, DS, SS, ES); используются для указания сегмента при адресации памяти;
— регистры-указатели (SP, BP, IP); используются для указания смещения при адресации памяти;
— индексные регистры (SI, DI); применяются для индексной адресации;
— регистр флагов; используется для хранения признаков состояния процессора.

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

Регистр АХ. Является основным сумматором. Используется во всех арифметических операциях (сложить, умножить и т.п.). Только с помощью АХ и его полурегистров AHIAL возможен обмен данными с портами ввода/вывода.

Регистр ВХ. Используется как сумматор в арифметических операциях, а также как базовый регистр при индексной адресации.

Регистр СХ. В основном используется как счетчик при выполнении операций повторения и сдвига. Может также участвовать в арифметических операциях.

Регистр DX. Используется как регистр данных в операциях ввода/вывода, а также как сумматор при обработке длинных целых чисел (32-разрядных).

Регистр CS. Содержит номер сегмента памяти (сегмента кода), в котором располагается текущая машинная инструкция. Для получения полного адреса следующей команды его содержимое сдвигается влево на 4 разряда и складывается с регистром-указателем IP. Содержимое CS автоматически изменяется в командах дальнего (межсегментного) перехода и вызова процедур.

Регистр IP. Определяет смещение относительно начала сегмента кода CS очередной исполняемой машинной инструкции. Содержимое IP автоматически изменяется в ходе исполнения инструкции, обеспечивая правильный порядок выборки команд из памяти.

Регистр DS. Содержит номер сегмента памяти (сегмента данных), в котором располагаются данные (константы и переменные). Все глобальные переменные и типизированные константы программы Турбо Паскаля всегда располагаются в единственном сегменте, адресуемом этим регистром.

Регистр SP. Указывает на вершину стека, т.е. совместно с регистром 55 адресует ячейку памяти, куда будет помещаться операнд или откуда он будет извлекаться. Содержимое этого регистра автоматически уменьшается после размещения в стеке очередного операнда и увеличивается после извлечения операнда из стека.

Регистр ВР. Так называемый указатель базы. Облегчает создание и использование локального стека (т.е. стека для использования внутри процедуры).

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

Регистр SI. Определяет адрес источника информации при индексной адресации данных (например, при обработке массивов). Обычно используется в паре с регистром DS.

Регистр флагов. Отдельные разряды (биты) этого регистра имеют следующее назначение.

Флаг переноса CF. Содержит 1, если произошел перенос единицы при сложении или заем единицы при вычитании. Используется также в циклических операциях и операциях сравнения.

Флаг внешнего переноса AF. Контролирует перенос из 3-го бита данных. Полезен при операциях над упакованными десятичными числами.

Флаг нуля ZF. Равен 1, если в результате операции получен ноль, и равен 0 в противном случае.

Флаг знака SF. Равен 1, если в результате операции получено отрицательное число (с единицей в старшем разряде).

Флаг трассировки TF. Равен 1, если программа исполняется по шагам, с передачей управления после каждой выполненной команды по прерыванию с вектором 1.

Флаг прерываний IF. Содержит 1, если микропроцессору разрешена обработка прерываний.

Флаг переполнения OF. Устанавливается в единицу, если в результате операции получено число, выходящее за разрядную сетку микропроцессора.

12.1.2. Адресация

Архитектура МП позволяет использовать семь различных способов адресации.

Извлекает операнд из регистра или помещает его в регистр. Примеры:

Операнд (8- или 16-разрядная константа) содержится непосредственно в теле команды. Примеры:

Смещение операнда задается в теле программы и складывается с регистром DS; например:

Исполнительный адрес операнда (точнее, его смещение) содержится в одном из регистров ВХ, ВР, SI или DI. Для указания косвенной адресации этот регистр должен заключаться в квадратные скобки, например:

Каждый из регистров BX. DI по умолчанию работает со своим сегментным регистром:

DS:BX, SS:BP, DS:SI, ES:DI

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

Базовый регистр ВХ (или ВР) содержит базу (адрес начала некоторого фрагмента памяти), относительно которой ассемблер вычисляет смещение, например:

Адресация по базе с индексированием

Вариант индексной адресации для случая, когда индексируемая область памяти задается своей базой. Например:

Этот тип адресации удобен при обработке двумерных массивов. Если, например, АОВ есть массив из 10×10 байт вида

АОВ: array [0..9,0..9] of Byte;

то для доступа к элементу АОВ [2,3] можно использовать такой фрагмент

12.1.3. Система команд

Детальный анализ всех команд МП 8086/8088 занял бы слишком много места, поэтому в идущих за таблицами пояснениях рассматриваются лишь наиболее популярные команды. Исчерпывающее описание всех команд Вы найдете в [1], [20].

Команды пересылки данных

МнемоникаФорматПояснение
Команды общего назначения
MOVMOV приемник, источникПереслать значение
PUSHPUSH источникПоместить в стек
POPPOP приемникИзвлечь из стека
XCHGXCHG приемник, источникОбменять значения
XLATXLAT таблицаЗагрузить в AL байт из таблицы
Команды ввода-вывода
ININ аккумулятор, портЧитать из порта
OUTOUT порт, аккумуляторЗаписать в порт
Команды пересылки адреса
LEALEA регистр 16, память 16Загрузить исполнительный адрес
LDSLDS регистр 16, память32Загрузить в DS:регистр16 полный адрес
LESLES регистр 16, память32Загрузить в ES:регистр16 полный адрес
Команды пересылки флагов
LAHFLAHFЗагрузить флаги в АН
SAHFSAHFУстановить флаги из АН
PUSHFPUSHFПоместить флаги в стек
POPFPOPFИзвлечь флаги из стека

С помощью MOV нельзя пересылать:

— из памяти в память, например, вместо

— константу или переменную в DS, например, нельзя

— один сегментный регистр в другой, например, нельзя

— в регистр CS; значение этого регистра (сегмента кода) автоматически меняется при выполнении дальних команд CALL и JMP; кроме того, он загружается из стека при выполнении команды RETF (выход из дальней процедуры).

Команда загрузки адреса LEA загружает в регистр адрес (смещение) нужного участка памяти. Этого же можно достичь с помощью зарезервированного слова OFFSET, стоящего перед именем переменной. Например:

Разница состоит в том, что в случае команды LEA разрешается использовать индексную адресацию, что особенно удобно при пересылке массивов данных.

МнемоникаФорматКомментарий
Команды сложения
ADDADD приемник, источникСложить
ADCADC приемник, источникСложить, добавить перенос
ААААААСкорректировать сложение для таблицы ASCII
DAADAAСкорректировать сложение для двоично-десятичных чисел
INCINC приемникУвеличить на единицу
Команды вычитания
SUBSUB приемник, источникВычесть
SBBSBB приемник, источникВычесть с заемом
AASAASСкорректировать вычитание для таблицы ASCII
DASDASСкорректировать вычитание для двоично-десятичных чисел
DECDEC приемникУменьшить на единицу
NEGNEG приемникОбратить знак
СМРСМР приемник, источникСравнить
Команды умножения
MULMUL источникУмножить без знака
IMULIMUL источникУмножить со знаком
AАМААМСкорректировать умножение для таблицы ASCII
Команды деления
DIVDIV источникДелить без знака
IDIVIDIV источникДелить со знаком
AADAADСкорректировать деление для таблицы ASCII
Команды расширения знака
CBWCBWПреобразовать байт в слово
CWDCWDПреобразовать слово в двойное слово
МнемоникаФорматКомментарий
Логические команды
ANDAND приемник, источникВыполнить AND
OROR приемник, источникВыполнить OR
XORXOR приемник, источникВыполнить XOR
NOTNOT приемникВыполнить NOT
TESTTEST приемник, источникПроверить
Сдвиговые команды
SAL/SHLSAL приемник, счетчикСдвинуть влево
SAR/SHRSAR приемник, счетчикСдвинуть вправо
ROLROL приемник, счетчикСдвинуть влево циклически
RORROR приемник, счетчикСдвинуть вправо циклически
RCLRCL приемник, счетчикСдвинуть влево с переносом
RCRRCR приемник, счетчикСдвинуть вправо с переносом

Битовые команды используются при исчислении логических выражений, а также в тех случаях, когда необходимо изменить отдельные разряды операнда. Логические команды AND, OR, XOR и NOT эквивалентны соответствующим операциям Турбо Паскаля в случае, когда операндами являются целочисленные выражения. Команда TEST выполняет целочисленную операцию поразрядного суммирования AND, но не изменяет значения операндов, а лишь устанавливает флаги в соответствии со значением результата сравнения: обнуляет CF и OF, изменяет PF, ZF, SF и не меняетAF (флаг ZF установится в 1 в том случае, когда оба операнда содержат по единице хотя бы в одном соответствующем разряде). Команды сдвига SHL/SHR эквивалентны одноименным операциям Турбо Паскаля и отличаются от команд циклического сдвига ROLIROR тем, что вытесненные в ходе их выполнения значащие разряды теряются, в то время как при циклическом сдвиге эти разряды появляются «с другой стороны». Например, если выполнить фрагмент

Заметим, что счетчиком в командах сдвига может быть цифра 1 или количество сдвигов, указываемое в регистре CL.

Команды передачи управления

МнемоникаФорматКомментарий
Безусловные переходы
CALLCALL имяВойти в процедуру
RETRET [количество параметров]Вернуться из процедуры
JUMPJUMP имяПерейти
Условные переходы

Перейти, если выше (после сравнения беззнаковых операндов)

Перейти, если больше (после сравнения знаковых операндов)

JA/JNBEJA близкая_метка
JAE/JNBJAE близкая_меткаПерейти, если выше или равно
JB/JBAE/JCJB близкая_меткаПерейти, если ниже
JBE/JNAJBE близкая_меткаПерейти, если ниже или равно
JCXZJCXZ близкая_меткаПерейти, если СХ=0
JE/JZJE близкая_меткаПерейти, если равно
JG/JNLEJG близкая_метка
JGE/JNLLGE близкая_меткаПерейти, если больше или равно
JL/JNGEJL близкая_меткаПерейти, если меньше
JLE/JNGJLE близкая_меткаПерейти, если меньше или равно
JNCJNC близкая_меткаПерейти, если нет переноса
JNE/JNZJNE близкая_меткаПерейти, если не равно
JNOJNO близкая_меткаПерейти, если нет переполнения
JNP/ JPOJNP близкая_меткаПерейти, если нечетный
JOJO близкая_меткаПерейти, если перенос
JP/JPEJP близкая_меткаПерейти, если четный
JSJS близкая_меткаПерейти, если отрицательный
Команды управления циклами
LOOPLOOP близкая_меткаПовторить цикл
LOOPE/LOOPZLOOPE близкая_меткаПовторять, пока равны
LOOPNE/LOOPNZLOOPNE близкая_меткаПовторять, пока не равны

Procedure MyProc; Far;

При выходе из дальней процедуры команда RET извлекает из стека оба 16-разрядных слова и помещает первое в IP, а второе в CS, а при выходе из ближней извлекает из стека только смещение и помещает его в IP.

Команды условных переходов способны передавать управление на метку, расположенную в пределах ближайших плюс-минус 128 байт от самой команды. Если нужно передать управление на метку, расположенную дальше в том же сегменте, или на метку в другом сегменте, сразу за командой условной передачи располагают безусловную команду JMP или CAL, например:

УсловиеДля беззнаковых чиселДля чисел со знаками
Приемник больше источникаJAJG
Приемник и источник равныJEJE
Приемник меньше источникаJBJL
Приемник не меньше источникаJAEJGE
Приемник не больше источникаJBEJLE
Приемник и источник не равныJNEJNE

С точки зрения Турбо Паскаля пара asm. end считается операторными скобками, ограничивающими единственный оператор Паскаля, например:

Тело ассемблерного оператора asm. end может быть пустым или содержать несколько ассемблерных команд. Каждая ассемблерная команда должна располагаться на отдельной строке или отделяться от следующей за ней команды символом «;». Ниже приводятся два разных способа написания одной и той же последовательности ассемблерных команд:

В конце строки, содержащей единственную ассемблерную команду, или между двумя командами, располагающимися на одной строке, разрешается вставлять комментарий, который должен оформляться по обычным правилам Турбо Паскаля, т.е. ограничиваться символами «<», «>» или «(*», «*)». Таким образом, комментарии разрешены между ассемблерными командами, но не внутри них. Например, такой оператор будет правильным:

lea di,Y; mov ex,100 <и направление>eld

В пределах ассемблерного оператора допускаются любые команды, но Турбо Паскаль требует выполнения следующего соглашения:

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

12.2.2. Синтаксис ассемблерных команд

Здесь и далее ассемблерными командами называются команды на языке встроенного ассемблера, вставляемые в тело ассемблерного оператора asm. end. Структура ассемблерной команды такова:

[Метка] [Префикс] [Код [Операнд [,Операнд]]]

В квадратных скобках указываются необязательные элементы структуры.

Локальные метки объявляются непосредственно в теле ассемблерного оператора. Эти метки обязаны начинаться символом «@». Поскольку этот символ нельзя использовать в именах Турбо Паскаля, он позволяет отличить локальную метку от глобальной. Локальная метка не известна нигде вне ассемблерного оператора, поэтому на нее нельзя передать управление оператором GOTO. По этой же причине в разных ассемблерных операторах можно использовать одноименные локальные метки.

Встроенный ассемблер поддерживает следующие префиксы команд:

REP/REPE/REPNE Повтор строковой команды

REPZ/REPNZ Синоним REPE/REPNE

SEGCS Перекрытие CS

SEGDS Перекрытие DS

SEGSS Перекрытие SS

SEGES Перекрытие ES

Префиксы LOCK/REP/REPE/REPNE описаны в п. 12.1.3. Префиксы SEGxx определяют сегментный регистр, который должен использоваться вместо умалчиваемого, и распространяются только на следующие за ними ассемблерные команды.

Если префикс указан без кода инструкции, он распространяет свое действие на следующую ассемблерную команду.

Замечу, что если при обработке строковой команды произошло аппаратное прерывание, МП 8086/8088 «забывает» префиксы LOCK и SEGxx, которые, возможно, определены в той же команде, так что использовать сложные префиксные конструкции не рекомендуется.

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

Во встроенном ассемблере используется мнемоника регистров, указанная в п. 12.1.1, а также имя ST для ссылки на регистры арифметического сопроцессора.

Ассемблер поддерживает строковые и числовые константы.

Строковые константы заключаются в апострофы или кавычки. Если константа объявлена с помощью кавычек, внутри нее символ апостроф рассматривается наравне с другими символами, т.е. не считается ограничителем константы, точно так же внутри константы, обрамленной апострофами, не считается ограничителем символ кавычки. Если внутри константы необходимо указать ограничивающий ее символ, он удваивается. Примеры:

‘Символ » не считается ограничителем’

‘внутри строки, обрамленной кавычками «. «‘

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

— 2 147 483 648. + 4 294 967 295.

Во встроенном ассемблере могут использоваться три предопределенных имени:

Имена @Code и @Data могут использоваться только в сочетании с директивой SEG для ссылки на нужный сегмент. Например:

Имя @Result используется для присвоения результата функции. Например:

Function Min(X,Y: Integer): Integer;

db ‘Турбо Паскаль’,13,10

dw 0,$ FFFF, NearProc

dd ‘ABCD1,999999999, FarProc

В качестве константных выражений разрешается использовать любые ассемблерные константы со значением, не выходящим из диапазона байта (DB), слова (DW) или двойного слова (DD). В любой директиве можно определять строковую константу, которая приводит к побайтовому заполнению памяти ASCII-кодами символов. Поскольку слово (двойное слово) размещается в памяти, начиная со своего младшего байта, старший (старшие) байт в директивах DW и DD при размещении строкой константы может остаться неопределенным и заполняется нулем. Например, два следующих объявления эквивалентны:

db ‘Текстовая строка,13,10,’$’

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

12.2.4. Ассемблерные подпрограммы

Function LongMul(X,Y:Integer):LongInt; Assembler;

При компиляции ассемблерных подпрограмм выполняется ряд оптимизаций кода, в том числе:

— параметры-значения строкового типа, а также длиной в 1, 2 и 4 байта не копируются во временную память, т.е. внутри подпрограммы они считаются параметрами-переменными ;
— компилятор не создает переменную @Result для результата функции, и ссылка на эту переменную в ассемблерной функции недопустима; исключением являются функции, возвращающие значения строкового типа, для них разрешается использовать ссылку на @Result;
— генерируются следующие команды на входе в подпрограмму и на ее выходе:

Все локальные переменные Турбо Паскаль размещает в стеке. Это относится как к обычным, так и к ассемблерным подпрограммам. Для ссылки на локальные переменные используется адресация по базе, задаваемой парой DS: ВР, поэтому при входе в процедуру всегда создается так называемый локальный стек: в регистр ВР помещается текущая граница стека, а сама эта граница смещается вверх на суммарную длину всех локальных переменных, чтобы работа со стеком внутри подпрограммы не разрушила локальные переменные. Например:

Ассемблерные функции должны следующим образом возвращать результат своей работы:

Источник

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *