logo
TurboProlog / Документация / TOM_2

Вызов программ на языке ассемблера из Турбо Пролога.

Предположим, что вы хотите написать процедуру double на языке ассем-

блера. Программа Турбо Пролога, содержащая вызов double, должна содержать

в global predicates объявление:

global predicates

double(integer, integer) - (i, o) language asm

Использование language asm инструктирует Турбо Пролог о том, что па-

раметры нужно выбирать слева направо, и сообщает, что вызванная программа

будет выбирать параметры из стека.

Запись активизации, расположенная в вершине стека, при активизации

double принимает форму, показанную на рис.3.1.

-----------------------------------------------------------------

[ВР] + 10 Значение, с которым связывается ВхЦелое

= 2 байта

-----------------------------------------------

[ВР] + 6 Адрес, где должна храниться ВыхПеременная

= 4 байта

-----------------------------------------------

[ВР] + 2 Адрес, с которого продолжается выполнение

после выполнения double = 4 байта

-----------------------------------------------

[ВР] + 0 Предыдущая установка ВР (перед тем, как

началось выполнение double) = 2 байта

-----------------------------------------------------------------

Рис.3.1. Запись активизации.

Основной текст double на языке ассемблера выглядит следующим обра-

зом:

MOV AX, [ВР] + 10; получает значение, с которым связывается

ВхЦелое

ADD AX, AX; удваивает это значение

LDS SI, DWORD PTR [ВР] + 6; заносит значение ВыхПеременная в

допустимый адрес

MOV [SI], AX

После добавления утверждений, необходимых для сохранения SP и ВР-ре-

гистров Турбо Пролога и связи ассемблерного фрагмента с модулем .OBJ Тур-

бо Пролога, вы получаете следующий код:

name double

DOUBLE_TEXT segment byte public 'CODE'

DGROUP GROUP _DATA,_BSS

assume cs:DOUBLE_TEXT,ds:DGROUP

DOUBLE_TEXT ends

_DATA segment word public 'DATA'

d@ label byte

_DATA ends

_BSS segment word public 'BSS'

b@ label byte

_BSS ends

DOUBLE_TEXT segment byte public 'CODE'

; Line 3

DOUBLE_0 prog far

push bp

mov bp,sp

mov ax,word ptr [bp+10]

add ax,ax

les bx,dword ptr [bp+6]

mov word ptr es:[bx],ax

pop bp

ret 6

DOUBLE_0 endp

DOUBLE_TEXT ends

_DATA segment word public 'DATA'

s@ label byte

_DATA ends

DOUBLE_TEXT segment byte public 'CODE'

public DOUBLE_0

DOUBLE_TEXT ends

end

Если вы ассемблируете эту программу в файл MYASM.OBJ, а вызывающий

объектный модуль Турбо Пролога есть MYPROLOG.OBJ, то вы их можете связать

при помощи командной строки:

tlink init + myprolog + myasm + myprolog.sym, mixprog, ,

prolog

На выходе получится выполняемый программный файл MIXPROG.EXE (ис-

пользующий библиотеку PROLOG.LIB). Файл MYPROLOG.SYM должен быть послед-

ним перед запятой.

Вообще говоря, формат записи активизации зависит от числа аргументов

в вызывающем предикате Турбо Пролога и типов доменов, соответствующих

этим аргументам. Например, если вы хотите определить

add(Val1, Val2, Sum)

где Val1, Val2 и Sum принадлежат доменам типа integer, запись активизации

примет форму, показанную на рис.3.2.

-------------- -----------------------------------------------

[ВР] + 10 Адрес, где должна располагаться величина SUM.

4 байта

-----------------------------------------------

[ВР] + 8 Величина, с которой связывается Val2

2 байта

-----------------------------------------------

[ВР] + 6 Величина, с которой связывается Val1

2 байта

-----------------------------------------------

[ВР] + 2 Адрес, с которого продолжается выполнение

после того, как выполнена add. 4 байта

-----------------------------------------------

[ВР] + 0 Предыдущая установка ВР (перед тем, как

началось выполнение add). 2 байта

-------------- -----------------------------------------------

Рис.3.2. Запись активизации.

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

Для выходных аргументов размер всегда 4 байта (используемый для адреса

сегмента и смещения); для входных аргументов размер определяется значени-

ем, записанным в стек, поэтому он зависит от соответствующего типа доме-

на.

В этом примере Val1 и Val2 (принадлежащие домену типа integer и ис-

пользуемые в шаблоне как (i), т.е. входные) оба занимают по 2 байта, а

Sun (используемая в шаблоне (o)) занимает 4 байта.

Отметим также, что внутри компилятора Турбо Пролога вызов внешнего

предиката имеет вид

/*Занесение параметров*/

MOV AX, SEGMENT DATA

MOV DS, AX

CALL FAR PTR EXTERNEL_PREDICATE_IMPLEMENTATION

поэтому регистр DS установлен на указание сегмента DATA перед тем, как

система вызывает процедуру для внешнего предиката.