Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

лабораторные на Pasca (Кудрявцев)l

.pdf
Скачиваний:
40
Добавлен:
18.03.2015
Размер:
2 Мб
Скачать
☆

Встроенный ассемблер

343

 

 

Операнды

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

Регистры

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

Константы

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

'Строковая константа' "ЭТО - ТОЖЕ СТРОКОВАЯ КОНСТАНТА"

'Символ '' не считается ограничителем' 'внутри строки, обрамленной кавычками "..." '

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

внутри диапазона

-2 147 483 648 … +4 294 967 295.

По умолчанию при записи числовых констант используется деся- тичная нотация, но ассемблер поддерживает также двоичные, вось- меричные и шестнадцатеричные константы. Двоичная константа составляется как комбинация единиц и нулей, заканчивающаяся символом В (от Binary – двоичный); при записи восьмеричной кон- станты используются символы 1...7, а в ее конце ставится символ О (Octal – восьмеричный); шестнадцатеричная константа записывает- ся по правилам Турбо Паскаля (начинается с символа #) либо по правилам Турбо Ассемблера: начинается с цифры, в конце ставится символ Н (от Hexadecimal – шестнадцатеричный).

344

Приложение

 

 

Имена

Локальные метки – это единственные имена, которые разрешается определять внутри ассемблерного оператора. Имена остальных объектов программы – констант, переменных, подпрограмм – должны определяться только с помощью средств Турбо Паскаля.

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

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

@Code

– текущий сегмент кода

@Data

– начальный сегмент данных

@Result

– ссылка внутри функции на ее результат

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

asm

mov ax, SEG @Data mov ds, ax

end;

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

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

{Эта функция сравнивает два целых числа и

Begin

возвращает наименьшее из них}

 

Asm

{Помещаем Х в АХ}

mov ах, Х

cmp ax, Y

{X<Y ?}

jl @

{Да - на выход}

mov ax, Y

{Нет - помещаем Y в АХ}

@: mov @Result, ax

{AX содержит результат}

End

 

end;

 

Для доступа к полям записей разрешается использование составных имен. Например:

Type

Point = record

Встроенный ассемблер

345

 

 

X,Y: Integer end;

Rect = record

A, B: Point end;

Var

P: Point;

R: Rect; Begin

Asm

mov ax, P .X add ax, P.Y mov R.A.X, ax

End

End.

Идентификаторы типов можно применять к операндам для уточне- ния данных, о которых идет речь. Каждая из следующих команд реализует одно и то же действие: загружает в регистр АХ слово по

адресу ES:[DI+4]:

mov ax, (Rect PTR es:[di]).B.X mov ax, Rect (es: [di]).B.X mov ax, es:Rect[di].B.X

mov ax, Rect[es:di].B.X mov ax, es:[di].Rect.B.X

Следующие имена не могут использоваться в операндах встроенно- го ассемблера:

−стандартные процедуры и функции (например, WriteLn, Chr);

−предопределенные массивы Mem, MemW, MemL, Port, PortW;

−константы с плавающей точкой, строковые и множественного типа;

−макросы (процедуры и функции, полностью реализуемые одним InLine – оператором);

−символ ©Result вне функции.

Выражения

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

346

Приложение

 

 

Регистровое выражение – это выражение, состоящее из имени реги- стра. Все следующие команды содержат только регистровые выра- жения:

push ds pop es mov ah, bl add ex,ax

Непосредственные выражения – это нетипизированные константы и имена типов. Примеры непосредственных выражений:

Const

dec = 10;

……

asm

mov ax, dec mov bx, 0

add cx, 2*dec+l sub dh,-5

end;

Все остальные выражения относятся к ссылкам на память. Напри-

мер

Const

dec: Word = 10; Step = 12;

Var

X, Y: Byte; Asm

mov ax, dec mov ex,[Step] add ah, X mov Y, bl mov ax,[bx]

end;

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

Если выражение может быть полностью вычислено к моменту его трансляции, т.е. если оно состоит только из регистровых или непо-

Встроенный ассемблер

347

 

 

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

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

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

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

Х+10

ВПаскале означает: «к содержимому переменной Х прибавить 10».

Вассемблерной команде это означает: «к адресу (смещению) пере-

менной Х прибавить 10». Однако команда

mov ах, Х

означает: «поместить в регистр АХ первые два байта переменной X». Если бы нам понадобилось загрузить в АХ адрес переменной X,

мы должны были бы написать

mov ax, OFFSET X

Заметим, что попытка «перехитрить» ассемблер командами типа

mov ах, Х+0 mov ах, Х+1-1

348

Приложение

 

 

и т.п. не дает желаемого результата: ассемблер просто загружает в АХ содержимое переменной X.

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

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

Тип

Длина в памяти

 

 

BYTE

1

 

 

WORD

2

 

 

DWORD

4

 

 

QWORD

8

 

 

TBYTE

10

 

 

NEAR

–

 

 

FAR

–

 

 

Имена предопределенных типов можно использовать для приведе- ния типов выражений. Например, если определены переменные

Var

Flag: Boolean; X: Word;

то такие ассемблерные выражения недопустимы:

mov Flag, bx mov ah, X

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

mov ah, BYTE PTR X mov ah, Byte(X) mov ah, X.Byte

Во всех случаях в АН будет загружен первый (младший) байт пере- менной Х.

Встроенный ассемблер поддерживает операции, перечисленные в следующей таблице (в порядке убывания приоритета).

Встроенный ассемблер

349

 

 

Операции встроенного ассемблера

Операция

Комментарий

 

 

&

Перекрытие идентификатора

( )

Подвыражение

[ ]

Ссылка на память

. (точка)

Селектор структуры

HIGH LOW

Доступ к байту в слове

+ -

Унарные операции задания знака

:

Перекрытие сегмента

OFFSET SEG TYPE PTR *

 

/ MOD SHL SHR

 

+ -

Бинарные операции

NOT AND OR XOR

Операции над битами

 

 

Операция &

Осуществляет перекрытие идентификатора: следующий за знаком & идентификатор считается определенным в программе, даже если он не совпадает с зарезервированным словом. Например:

Var

Ch: Byte;

……

mov ch, 0

{Посылаем 0

в регистр CH}

mov &Ch, 0

{Посылаем 0

в переменную Ch}

Операция ( )

Круглые скобки используются обычным для Паскаля образом – для изменения порядка исчисления выражения (подвыражение, ограни- ченное скобками, вычисляется в первую очередь). Если перед скоб- ками стоит имя типа, все выражение приобретает указанный тип. Например:

mov ах, ( (1+2)*3+4)*5

{АХ = 65}

mov bx,1+2*3+4*5

{ВХ = 27}

Операция [ ]

Определяет ссылку на память. Выражение внутри скобок вычисля- ется в первую очередь. Обычно оно связывается с регистрами BX, BP, SI, DI и может использовать операции + и – для указания индек- сации. Например:

350

Приложение

 

 

mov ah,100

{АН = 100}

mov ah, [100]

{Загружаем в АН содержимое байта по адресу DS:100}

Операция . (точка)

Селектор элемента структуры. Результат– сумма выражений до по- сле точки с типом второго выражения. Например:

Var

R:record

X:Word; Y: Byte

end;

……

mov ax, R.X mov R.A, ai

Операции HIGH и LOW

HIGH возвращает старший, a LOW – младший байт выражения типа слова, следующего за символами операции. Выражение должно иметь абсолютное непосредственное значение. Например:

mov al, High $1000

{AL = $10}

Операция : (двоеточие)

Указывает ассемблеру, что выражение после операции должно от- носиться к сегменту, указанному до операции. Результат – ссылка на память со значением второго выражения. Например:

Mov ах, [10]

{AX = слово по адресу DS:10}

Mov ax, BS:[10]

{АХ = слово по адресу BS:10}

 

Операция OFFSET

Возвращает смещение выражения, следующего за операцией. Ре- зультатимеет непосредственное значение. Например:

mov ах, Х

{АХ = слово по адресу переменной X}

mov ax, offset Х

{АХ = смещение адреса X}

 

Операция SEG

Возвращает сегмент выражения, следующего за операцией. Резуль- тат имеет непосредственное значение.

Операция PTR

Осуществляет приведение типа. Результат – ссылка на память со значением выражения после операции и типом выражения до опе- рации. Например:

Встроенный ассемблер

351

 

 

Function SwapfX: Integer): Integer;

{Меняет местами байты в слове X}

begin

 

asm

 

mov ax, X

 

mov BYTE PTR @Result, ah

 

mov BYTE PTR @Result+l, al

 

end;

 

end;

 

Операции * и /

* – умножение, / – целочисленное деление. Оба выражения должны иметь непосредственные абсолютные значения, такое же значение имеет и результатоперации. Например:

mov ах, 2*2

{АХ = 4}

mov ах, 17/3

{АХ = 5}

 

Операция MOD

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

mov ax, 17 mod 3

{AX = 2}

 

Операции SHL и SHR

Осуществляют логический сдвиг влево (SHL) или вправо (SHR) вы- ражения, стоящего до операции, на количество разрядов, опреде- ляемое выражением после операции. Оба выражения должны иметь непосредственные абсолютные значения, такое же значение имеет и результатоперации. Например:

mov ah, 1 shl 7

{Ah = $80 = 128}

 

Бинарная операция +

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

Бинарная операция –

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

352

Приложение

 

 

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

Побитовые операции NOT, AND, OR, XOR

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

Директивы ассемблера

Встроенный ассемблер не поддерживает никакие директивы, обыч- но используемые в других ассемблерах, за исключением DB, DW, DD. Структура директив такова:

Dx <константа> [,<константа>,...,<константа>]

Здесь Dx – DB, DW или DD; <константа> – ассемблерная константа или константное выражение.

DB определяет цепочку байт, DW – слов, DD – двойных слов. На- пример:

db

'Турбо Паскаль',13,10

dw

0,$ FFFF, NearProc

dd'ABCD',999999999, FarProc

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

ленным и заполняется нулем. Например, два следующих объявле- ния эквивалентны:

dw

'5'

 

dw

$35

{$35 - ASCII-код символа '5'}

В директивах DW и DD разрешается также указывать имена, кото-

рые в этом случае интерпретируются как адреса соответствующих объектов, причем для DW это – ближний адрес (смещение), а для DD – дальний. Например: