Страница 51 из 60
Создание внешней программы на ассемблере
Теперь, когда рассмотрены соглашения о связях, приведем код действительной программы на ассемблере. Предположим, что требует- ся составить программу на ассемблере для следующей функции: function Xmul(a, b: integer): integer; begin a: = a*b; Xnul: = a; end; Поскольку эта функция будет вызываться из программы на TURBO -Паскале, то два аргумента целого типа будет помещаться в стек, занимая два слова. Поэтому при следующем вызове функции xmu(10,20); первым будет помещаться в стек значение 20 и затем значение 10. Следует помнить, что для скалярных переменных значения по ме- щаются в стек. Для массива и записи в стек помещается адрес. Результат этой функции будет помещен в регистр АХ. Ниже при- водится код этой функции на ассемблере: code segment 'code' assume cs:code public xmul xmul proc near
;сохранить указатель стека push bp mov bp,sp
;получить первый параметр mov ax,[bp]+4 ;умножить на второй параметр mul word ptr [bp]+6 ;восстановить "вр" и очистить стек ;результат уже находится в регистре АХ pop bp ret 4 xmul endp code ends end
Следует отметить, что все регистры сохраняются при помощи инструкций "push" и "рор" и доступ к аргументам осуществляется через стек. Кроме того, функция "xmul" объявлена как "public". Это необходимо для обеспечения Турбо Паскалем ее правильной связи с остальной программой. Если вы незнакомы с ассемблером процессо- ров 8086 и 8088, то вам могут помочь следующие пояснения. Расс- мотрим следующий код: mov bp,sp mov ax,[bp]+4. Эти инструкции помещают адрес вершины стека в регистр ВР и затем сдвигают четвертый байт дальше в стек /т.е. параметр "а" помещается в регистр АХ/. Параметры занимают четвертый и шестой байты, поскольку адрес возврата и инструкция "push bp" занимают четыре байта. Следовательно, параметры начинаются на четыре байта ниже вершины стека. Внешняя функция "xmul" является "близкой" процедурой. Если процедура объявляется в программе или в разделе реализации блока, она должна объявляться с параметром "near". Если внешняя функция объявляется в секции интерфейса блока, то она должна будет объяв- ляться с параметром "far". Перед использованием этой внешней функции она должна быть ассемблирована с применением макроассемблера фирмы "Майкроусофт". Следует помнить, что все процедуры, функции и переменные, к кото- рым необходимо обеспечить доступ в вашей программе, должны объяв- ляться с параметром "public". В вашей программе на Турбо Паскале можно использовать ука- занную внешнюю функцию следующим образом: {программа, которая обеспечивает связь с внешней подпрог- раммой, написанной на ассемблере } program asmtest;
{SL XMUL}
var a, b, c: integer;
function xmul(x, y: integer): integer; external;
begin a: = 40; b: = 20; c: = xmul(a,b); {умножение "а" на "в" и получение результата} WriteLn(c); end.
Директива компилятора $L используется для указания на необ- ходимость подсоединения к программе объектного кода модуля "xmul". Следует помнить, что все примеры даются для ассемблера про- цессоров 8086 и 8088. Если используется Турбо Паскаль версии СР/М, то примеры должны быть изменены в соответствии с руководс- твом пользователя по Турбо Паскалю. Кроме того, связь с подпрог- раммами на языке ассемблера будет отличаться для TURBOПаскаля версий более ранних, чем версия 4.0.
|