Использование turbo pascal с языком ассемблера. Встроенный ассемблер, страница 12

function StringOf; external;

end.

Программа на  Ассемблере,  реализующая  функции  UpperCase   и

StringOf,  показана  ниже.  Она  должна  быть ассемблирована в файл

Strs.OBJ до  компиляции  модуля  Strings.  Заметим,  что  программы используют   дальнюю   модель  вызова,  так  как  они  объявлены  в интерфейсной части модуля.

CODE    SEGMENT BYTE PUBLIC

ASSUME  CS:CODE

PUBLIC UpperCase, StringOf   ; объявление функций

; function UpperCase(S: String): String;

UpperRes  EQU     DWORD PTR [BP+10]

UpperStr  EQU     DWORD PTR [BP+6]

UpperCase PROC FAR

push   bp             ; сохранить bp

mov    bp,sp          ; установить стек

push   ds             ; сохранить ds

lds    si,UpperStr    ; загрузить адрес строки

les    di,UpperRes    ; загрузить адрес результата

cld

lodsb                 ; загрузить длину строки

stosb                 ; копировать в результат

mov    cl,al          ; длину строки в CX

xor    ch,ch

jcxz   U3             ; пропустить, если строка пустая

U1: lodsb                 ; загрузить символ

cmp  al,'a'           ; пропустить если не 'a'..'z'

jb   U2

cmp  al,'z'

ja   U2

sub  al,'a'-'a'       ; преобразовать в заглавные

U2: stosb                 ; запомнить в результат

loop U1               ; цикл для всех символов

U3: pop  ds               ; востановить ds

pop  bp               ; востановить bp

ret  4                ; удалить параметр и возврат

UpperCase  ENDP

; procedure StringOf(var S :string; Ch : char; Count: byte)

StrOfs     EQU   DWORD PTR [BP + 10]

StrOfChar  EQU   BYTE PTR [BP + 8]

StrOfCount EQU   BYTE PTR [BP + 6]

StringOf   Proc FAR

push  bp              ; сохранить bp

mov   bp,sp           ; установить стек

les   di,StrOfRes     ; загрузить адрес результата

mov   al,StrOfCount   ; загрузить счетчик

cld

stosb                 ; сохранить длину

mov   cl,al           ; счетчик в CX

xor   ch,ch

mov   al, StrOfChar   ; загрузить символ

rep   STOSB           ; сохранить строку символов

pop   bp              ; восстановить bp

ret   8               ; удалить параметр и возврат

StringOf  ENDP

CODE      ENDS

END

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

TASM STRS

TPC strings

Следующий пример показывает, как программа на Ассемблере может обращаться  к  программам  и переменным Паскаля.  Программа Numbers

читает  до  100  целых  значений  и  затем  вызывает  процедуру  на

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

program Numbers;

{$L CHECK}

var

Buffer: array[1..100] of Integer;

Count: Integer;

procedure RangeError(N: Integer);

begin

WriteLn('Range error: ', N);

end;

procedure CheckRange(Min, Max: Integer); external;

begin

Count := 0;

while not EOF and (Count < 100) do

begin

Count := Count + 1;

ReadLn(Buffer[Count]);

{закончится, когда пользователь введет CTRL-Z или после 100 итераций}

end;

CheckRange(-10,10);

end.

Программа на  Ассемблере,  реализующая  процедуру  CheckRange, приведена ниже.

Она должна быть ассемблирована в файл Check.OBJ  до компиляции программы Numbers. Заметим, что процедура использует ближнюю модель вызова, так как объявлена в программе.

DATA SEGMENT WORD PUBLIC

EXTRN   Buffer: WORD, Count: WORD;   ;Переменные Паскаля

DATA ENDS

CODE SEGMENT BYTE PUBLIC

ASSUME CS: CODE, DS: Buffer

EXTRN  RangeError: NEAR        ;реализован в Паскале

PUBLIC CheckRange              ;реализован здесь

CheckRange PROC NEAR

mov   bx,sp           ;получить указатель параметров

mov   ax,ss:[bx+4]    ;загрузить Min

mov   dx,ss:[bx+2]    ;загрузить Max

xor   bx,bx           ;очистить индекс данных

mov   cx,Count        ;загрузить Count

jcxz  SD4             ;пропустить если 0

SD1: cmp   Buffer[BX],AX   ;слишком мал?