Выражения, которые означают положение памяти, - это ссылки на память; метки, переменные, типированные константы и функции Паскаля относятся к этой категории.
Выражения, которые не относятся к регистрам и не связаны с положением в памяти, - это непосредственные значения; эта группа включает нетипированные константы и типы Паскаля.
Непосредственные значения и ссылки к памяти приводят к генерации различного кода, когда используются как операнды.
Например:
const
Start = 10;
var
Count: Integer;
...
asm
mov ax,Start { MOV AX,xxxx }
mov bx,Count { MOV BX,[xxxx] }
mov cx,[Start] { MOV CX,[xxxx] }
mov dx,OFFSET Count { MOV DX,xxxx }
end;
Поскольку Start - это непосредственное значение, первая MOV
ассемблируется в инструкцию пересылки непосредственного значения.
Вторая MOV транслируется в инструкцию пересылки памяти, т.к. Count
- это ссылка на память. В третий MOV [] используются для преобразования Start в ссылку на память (в этом случае слово со смещением 10 в сегменте данных) и в четвертой MOV оператор OFFSET
используется для преобразования Count в непосредственное значение
(смещение Count в сегменте данных).
Как Вы видите, [] и OFFSET дополняют друг друга. В терминах результирующего машинного кода следующий оператор asm идентичен двум первым строкам предыдущего оператора asm:
asm
mov ax,OFFSET [Start]
mov bx,[OFFSET Count]
end;
Ссылки на память и непосредственные значения классифицируются как перемещаемые и абсолютные выражения. Перемещаемое выражение означает значение, которое требует перемещения во время редактирования, а абсолютное значение означает значение, которое не требует такого перемещения. Обычно выражения, которые ссылаются на метки, переменные, процедуры или функции, являются переместимыми, а выражения, которые ссылаются только на константы - абсолютные.
Перемещение - это процесс, при котором редактор связей назначает символам абсолютные адреса. Во время компиляции компилятор не знает окончательных адресов меток, переменных, процедур или функций; они неизвестны до времени редактирования, когда редактор назначает абсолютные адреса символам.
Встроенный Ассемблер позволяет Вам выполнить любую операцию над абсолютным значением, но ограничивает операции над перемещаемыми объектами до сложения и вычитания констант.
Типы выражений.
Каждое выражение встроенного ассемблера имеет тип - или более точно размер, поскольку встроенный асссемблер рассматривает тип выражения просто как размер его положения в памяти. Например, тип
(размер) переменной Integer - 2, поскольку она занимает 2 байта.
Встроенный асссемблер выполняет проверку типа, когда это возможно, так в инструкциях
var
QuitFlag: Boolean;
OutBufPtr: Word;
...
asm
mov al,QuitFlag
mov bx,OutBufPtr
end;
встроенный ассемблер проверяет что размер QuitFlag - 1 байт, а размер OutBufPtr - 2 байта. Если тип неправильный, то возникает ошибка; например, неверно:
asm
mov dl,OutBufPtr
end;
поскольку DL - регистр байтового размера, а OutBufPtr - слово.
Тип ссылки на память может быть изменен с помощью приведения типа;
корректный способ написания предыдущей инструкции:
asm
mov dl,BYTE PTR OutBufPtr
mov dl,Byte(OutBufPtr)
mov dl,OutBufPtr.Byte
end;
ссылаются на первый байт (наименее значащий) переменной
OutBufPtr.
В некоторых случаях ссылки на память нетипированные, т.е. не имеют типа. Пример с непосредственным значением, заключенным в []:
asm
mov al,[100H]
mov bx,[100H]
end;
Встроенный асссемблер разрешает обе инструкции, поскольку выражение в [100H] не имеет типа - это означает "содержимое по адресу 100H в сегменте данных", и тип может быть определен из первого операнда (байт для AL, слово для BX). В случае если тип не может быть определен из другого операнда, встроенный Ассемблер требует явного приведения типов:
Уважаемый посетитель!
Чтобы распечатать файл, скачайте его (в формате Word).
Ссылка на скачивание - внизу страницы.