X1, y1, x2, y2: integer;
procedure Init(XA, YA, XB, YB: integer);
procedure Union(var R: Rect);
function Contains(X, Y: integer): boolean;
end;
Rect представляет собой прямоугольник, ограниченный четырьмя координатами X1, Y1, X2 и Y2. Левый верхний угол прямоугольника определяется X1 и Y1, а правый нижний - координатами X2 и Y2. Метод Init присваивает значения координатам прямоугольника. Метод Union вычисляет наименьший прямоугольник, который содержит как сам прямоугольник, так и некоторый другой прямоугольник. Contains возвращает True, если данная точка лежит внутри прямоугольника, и False, если вне его. Другие методы, такие как перемещение, изменение размеров, вычисление точек пересечений и проверка на равенство, могут быть легко дописаны, чтобы сделать Rect более полезным объектом.
Реализация методов объекта Rect на Паскале приводит только заголовки методов, за каждым из которых следует зарезервированное слово external.
{$L RECT}
procedure Rect.Init(XA,YA, XB, YB: integer); external;
procedure Rect.Union(var R: Rect); external;
function Rect.Contains(X, Y: integer): boolean; external;
Разумеется, не существует никаких требований, чтобы методы были реализованы как внешние. Каждый отдельный метод может быть реализован как на Паскале, так и на Ассемблере, в зависимости от желания.
Исходный файл на языке Ассемблера RECT.ASM, который реализует три внешних метода, приводится ниже:
TITLE Rect
LOCALS@@
; структура Rect
Rect STRUCT
X1 DW ?
Y1 DW ?
X2 DW ?
Y2 DW ?
Rect ENDS
code SEGMENT BYTE PUBLIC
ASSUME cs:code
; процедура Rect.Init(XA, YA, XB, YB: Integer);
PUBLIC Rect@Init
Rect@Init PROC FAR
@XA EQU (WORD PTR [bp + 16])
@YA EQU (WORD PTR [bp + 14])
@XB EQU (WORD PTR [bp + 12])
@YB EQU (WORD PTR [bp + 10])
@Self EQU (DWORD PTR [bp + 6])
push bp ; сохранить bp
mov bp, sp ; установить границу стека
les di, @Self; загрузить Self d ES:DI
cld ; продвинуться вперед
mov ax, @XA;X1 := XA
stosw
mov ax, @YA;Y1 := YA
stosw
mov ax, @XB;X2 := XB
stosw
mov ax, @YB;Y2 := YB
stosw
pop bp ; восстановить BP
ret12 ; излечь параметры и выполнить возврат
Rect@Init ENDP
; Процедура Rect.Union (var R: Rect)
PUBLIC Rect@Union
Rect@Union PROC FAR
@R EQU (DWORD PTR [bp + 10])
@Self EQU (DWORDPTR [bp + 6])
push bp ; сохранить bp
mov bp, sp ; установить границу стека
push ds ; сохранить ds
lds si, @R ; загрузить R в DS:SI
les di, @Self ; загрузить Self в ES:DI
cld ; продвинуться вперед
lodsw ; если R.X1 >= X1, перейти к @@1
scasw
jge @@1
dec di ; X1 := R.X1
dec di
stosw
@@1: lod sw ; если R.Y1 >= Y1, перейти к @@2
scasw
jge @@2
decdi;Y1 := R.Y1
decdi
stos
@@2: lod sw ; если R.X2 <= X2, перейти к @@3
scasw
jle @@3
decdi ; X2 := R.X2
decdi
stosw
@@3: lodsw ; если R.Y2 <= Y2, перейти к @@4
scasw
jle @@4
decdi ; Y2 := R.Y2
decdi
stosw
@@4: popds ; восстановить ds
pop bp ; восстановить bp
ret8 ; извлечь параметры и выполнить возврат
Rect@Union ENDP
; функция Rect.Contains(X, Y: integer): boolean
PUBLIC Rect@Contains
Rect@Contains PROC FAR
@X EQU (WORD PTR [bp + 12])
@Y EQU (WORD PTR [bp + 10])
@Self EQU (DWORD PTR [bp + 6])
push bp ; сохранить bp
mov bp, sp ; установить границу стека
les di, @Self ; загрузить Self в ES:DI
mov al, 0 ; возвратить false
mov dx, @X ; если (X < X1) or (X > X2) - перейти
; на @@1
cmp dx, es:[di].X1
jl @@1
cmp dx, es:[di].X2
jg @@1
mov dx, @Y ; если (Y < Y1) or (Y > Y2) - на @@1
cmp dx, es:[di].Y1
jl @@1
cmp dx, es:[di].Y2
jg @@1