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

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

.pdf
Скачиваний:
32
Добавлен:
18.03.2015
Размер:
1.63 Mб
Скачать

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

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 дальний. Например: