Среда Турбо Паскаль 7.0 обладает весьма интересным новшеством: в ней введена поддержка длинных строк, т.е. строк, длина которых может превышать 255 байт. Как известно, тип String в Турбо Паскале имеет максимальную длину 255 байт. Это связано с тем, что истинная длина строки в этом типе указывается первым байтом, мощность которого не позволяет определять строки большей длины. В то же время в языке С используется другой подход к заданию текстовых строк: первый байт строки является ее первым символом, второй байт - вторым символом и т.д. пока не встретится байт с символом #0. Таким образом, длина строки не указывается явно, как в типе String, а определяется по замыкающему символу #0. Ясно, что такие строки могут иметь произвольную длину, ограничиваемую лишь объемом оперативной памяти или принятой схемой ее адресации: в MS-DOS такой границей является длина сегмента, поэтому максимально возможная длина С-строки для ПК составляет 65535 символов. Такие строки в дальнейшем будем называть ASCIIZ-строками.
Для реализации операций над ASCIIZ-строками в язык введен новый тип PChar, определяемый как указатель на символ:
type
PChar =^Char;
Однако такой обычный для Паскаля тип-указатель в рамках Турбо Паскаля 7.0 трактуется необычным способом: считается, что он указывает на цепочку символов, заканчивающуюся терминальным нулем, т.е. на ASCIIZ-строку. Более того, с этим типом совместим любой одномерный символьный массив с нулевой левой границей, а переменные типа PChar можно индексировать, как если бы они были массивами символов. Следующая программа напечатает все заглавные буквы английского алфавита:
{$Х+} {Включаем расширенный синтаксис}
var
Chars : array [0..26] of Char; {Массив символов}
PChars: PChar; {Указатель на символ}
k : Integer;
begin
for k := 0 to 25 do
Chars[k] := Chr(k+ord('A'); {Наполняем массив}
PChars := Chars; {Указателю присваиваем массив!}
PChars[26] := #0; {Индексируем указатель!}
WriteLn(PChars) {Печатаем указатель!}
end.
Три последние оператора программы недопустимы в стандартном Паскале и в ранних версиях Турбо Паскаля, но возможны в версии 7.0, если включен расширенный синтаксис (директивой {$Х+} или опцией Options/Compiler/Extended syntax). Обратите внимание: процедура WriteLn этой версии умеет работать с ASCIIZ-строками.
Для поддержки ASCIIZ-строк разработан модуль Strings, в котором реализованы необходимы процедуры и функции.
Функция StrCat. Объединяет строки. Заголовок:
Function StrCat(Dest, Source: PChar): PChar;
Копирует строку Source в конец строки Dest и возвращает указатель на начало Dest.
Функция StrComp. Сравнивает строки. Заголовок:
Function StrComp(Strl, Str2: PChar): Integer;
Побайтно сравнивает строку Strl со строкой Strl и возвращает следующий результат:
=0 Strl=Str2;
>0 Strl>Str2;
<0 Strl<Str2.
Функция StrCopy. Копирует строку. Заголовок:
Function StrCopy(Dest, Source: PChar): PChar;
Копирует строку Source в строку Dest и возвращает указатель на Dest. StrCopy не проверяет реальный размер памяти, связанный с Dest (он должен быть не меньше StrLen(Source)+1).
Процедура StrDispose. Удаляет строку из кучи. Заголовок:
Procedure StrDispose(Str: PChar);
Строка Str должна быть предварительно помещена в кучу функцией StrNew. Если Str=NIL, процедура ничего не делает.
Функция StrECopy. Объединяет строки. Заголовок:
Function StrECopy(Dest, Source: PChar): PChar;
Эта функция работает в точности как StrCat, но возвращает указатель на конец сцепленных строк, т.е. на терминальный ноль.
Функция StrEnd. Возвращает конец строки. Заголовок:
Function StrEnd(Str: PChar): PChar;
Функция возвращает указатель на терминальный ноль ASCIIZ-строки Str.
Функция StrlComp. Сравнивает строки. Заголовок:
Function StrlComp(Strl, Str2: PChar): PChar; .
Функция сравнивает строки, игнорируя возможную разницу в высоте букв. Возвращает такой же результат, как и StrComp. Замечу, что функция правильно работает лишь с латиницей. Для кириллицы ее нужно модифицировать (см. ниже).
Функция StrLCat. Объединяет строки. Заголовок:
Function StrLCat(Dest, Source: PChar; MaxLen: Word): PChar;
Копирует символы строки Source в конец строки Dest до тех пор, пока не будут скопированы все символы или когда длина сцепленной строки Dest не достигнет MaxLen. Возвращает указатель на сцепленную строку.
В отличие от StrCopy эта функция блокирует возможное переполнение области памяти, связанной с Dest. Обычно в качестве MaxLen используется выражение SizeOf (Dest) -1. Например:
{$Х+}
Uses Strings;
var
S: array [0..9] of Char;
begin
StrCopy(S, 'Turbo');
StrLCat(S, ' ', SizeOf(S)-1);
StrLCat(S, 'Pascal', SizeOf(S)-1);
WriteLn(S) {Напечатает "Turbo Pas"}
end;
Функция StrLComp. Сравнивает строки. Заголовок:
Function StrLComp(Dest, Source: PChar; MaxLen: Word): PChar;
В отличие от StrComp сравнивает не более MaxLen символов строк. Возвращаемый результат такой же, как и у StrComp.
Функция StrLCopy. Заголовок:
Function StrLCopy(Dest, Source: PChar; MaxLen: Word): PChar;
Копирует символы из строки Source в строку Dest до тех пор, пока не будет скопирована вся строка или пока не будет скопировано MaxLen символов. В отличие от StrCopy блокирует возможное переполнение области памяти, связанной с Dest. В качестве MaxLen обычно используется выражение SizeOf (Dest) -1. Например:
{$Х+}
Uses Strings;
var
S: array [0..9] of Char;
begin
StrLCopy(S, 'Turbo Pascal', SizeOf(S)-1);
WriteLn(S) {Напечатает "Turbo Pas"}
end;
Функция StrLen. Возвращает длину строки. Заголовок:
Function StrCattStr: PChar): Word;
Функция StrLIComp. Сравнивает строки с учетом регистра. Заголовок:
Function StrLIComp(Str1, Str2: PChar; MaxLen: Word): PChar;
Сравнивает не более MaxLen символов строк, проверяя точное соответствие высоты букв. Возвращаемый результат см. StrComp. Функция правильно работает только с латиницей.
Функция StrLower. Преобразует в строчные буквы. Заголовок:
Function StrLower(Str: PChar): PChar;
Преобразует заглавные буквы строки Str к строчным и возвращает указатель на результат. Функция правильно работает только с латиницей.
Функция StrMove. Копирует строку. Заголовок:
Function StrMove(Dest, Source: PChar; Count: Word): PChar;
Копирует точно Count символов строки Source в строку Dest и возвращает указатель на результат. Функция игнорирует действительные размеры строк и может выйти за их пределы.
Функция StrNew. Помещает строку в кучу. Заголовок:
Function StrNew(Str: PChar): PChar;
Функция Str Pas. Преобразует ASCHZ-строку в строку String. Заголовок:
Function StrPas(Str: PChar,) : String;
Функция StrPCopy. Преобразует строку String в ASCIIZ-строку. Заголовок:
Function StrPCopy(Str: PChar; S: String): PChar;
Возвращает указатель на Str.
Функция StrPos. Ищет подстроку. Заголовок:
Function StrPos(Strl, Str2: PChar): PChar;
Ишет подстроку Str2 в строке Strl и возвращает указатель на первое вхождение Str2 или NIL, есди подстрока не найдена.
Функция StrRScan. Ищет последний символ. Заголовок:
Function StrRScan(Str: PChar; Ch: Char): PChar;
Ищет символ Ch в строке Str и возвращает указатель на последний обнаруженный символ Ch или NIL, если символ не найден.
Функция StrScan. Ищет первый символ. Заголовок:
Function StrScan(Str: PChar; Ch: Char): PChar;
Ищет символ Ch в строке Str и возвращает указатель на первый обнаруженный символ Ch или NIL, если символ не найден.
Функция StrUpper. Заголовок:
Function StrLower(Str: PChar): PChar;
Преобразует строчные буквы строки Str к заглавным и возвращает указатель на результат. Функция правильно работает только с латиницей.
Четыре функции модуля Strings (StrLower, StrUpper, StrlComp и StrLIComp) используют преобразование высоты букв и работают корректно только для букв латинского алфавита (латиницы). Для русских букв эти функции можно изменить следующим образом:
{Этот модуль содержит модификацию функций стандартного модуля Strings для работы с кириллицей (альтернативный вариант кодировки}
{$Х+}
Unit StringsR;
INTERFACE
Function LoCase(Ch: Char): Char;
Function UpCase(Ch: Char): Char;
Function StrLower(Str: PChar): PChar;
Function StrUpper(Str: PChar): PChar;
Function StrlComp(Strl, Str2: PChar): Integer;
Function StrLIComp(Strl, Str2: PChar; MaxLen: Word): Integer;
IMPLEMENTATION
Uses Strings;
Function LoCase(Ch: Char): Char;
{Преобразует латинскую или русскую букву Ch к строчной}
{Разницы нет. Если проверено MaxLen символов, строки считаются равными, в противном случае результат зависит от совпадения длин строк}
if Max=MaxLen then
StrLIComp := 0
else
StrLIComp := StrLen(Str1)-StrLen(Str2)
end;
end.
Если Вы будете использовать этот модуль, ссылайтесь на него в предложении Uses после ссылки на стандартный модуль Strings:
Uses Strings, StringsR, ...
· Глава 12. ВСТРОЕННЫЙ АССЕМБЛЕР
o 12.1. Общее описание МП 8086/8088
§ 12.1.1. Регистры
§ 12.1.2. Адресация
§ 12.1.3. Система команд
o 12.2. Специфика встроенного ассемблера
§ 12.2.1. Оператор ASM
§ 12.2.2. Синтаксис ассемблерных команд
§ 12.2.3. Директивы ассемблера
§ 12.2.4. Ассемблерные подпрограммы
Глава 12
ВСТРОЕННЫЙ АССЕМБЛЕР
Ассемблером называется машинно-зависимый компилятор, преобразующий специальным образом составленные текстовые строки в машинные инструкции. Как и любой другой компилятор, ассемблер упрощает разработку программ за счет того, что предоставляет пользователю доступ к кодам машинных инструкций и операндам с помощью символьных имен.
В этой главе рассматриваются приемы программирования с помощью ассемблера, встроенного в компилятор Турбо Паскаля. Встроенный ассемблер имеется в версиях 6.0 и 7.0 Турбо Паскаля и в руках опытного программиста представляет собой мощный инструмент, позволяющий «выжать» из ПК все возможное.