 |
lea bx,DestString ; самый левый параметр
lea ax,SourceString ; самый правый параметр
call strcpy pascal,bx,ax
Турбо Ассемблер 3.0/tasm/#2-2 = 114 =
Турбо Ассемблер автоматически вставит команды помещения ар-
гументов в стек в последовательности, принятой в Паскале (сначала
BX, затем AX), и выполнит вызов STRCPY (преобразуя имя к верхнему
регистру, как принято в соглашениях Паскаля).
В последнем случае конечно подразумевается, что вы переком-
пилировали функцию strcpy с параметром -p, так как в стандартной
библиотечной версии данной функции используются соглашения по вы-
зову, принятые в С++, а не в Паскале.
Функции С++ сохраняют следующие регистры (и только их): SI,
DI, BP, DS, SS, SP и CS. Регистры AX, BX, CX, DX, ES и флаги мо-
гут произвольно изменяться.
Вызов из Турбо Ассемблера функции Borland C++
ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД
Одним из случаев, когда вам может потребоваться вызвать из
Турбо Ассемблера функцию Borland C++, является необходимость вы-
полнения сложных вычислений, поскольку вычисления гораздо проще
выполнять на С++, чем на Ассемблера. Особенно это относится к
случаю смешанных вычислений, где используются и значения с плава-
ющей точкой и целые числа. Лучше возложить функции по выполнению
преобразования типов и реализации арифметики с плавающей точкой
на С++.
Давайте рассмотрим пример программы на Ассемблере, которая
вызывает функцию Borland C++, чтобы выполнить вычисления с плава-
ющей точкой. Фактически в данном примере функция Borland C++ пе-
редает последовательность целых чисел другой функции Турбо Ас-
семблера, которая суммирует числа и в свою очередь вызывает
другую функцию Borland C++ для выполнения вычислений с плавающей
точкой (вычисление среднего значения).
Часть программы CALCAVG.CPP, реализованная на С++
(CALCAVG.CPP), выглядит следующим образом:
#include
extern float Average(int far * ValuePtr, int
NumberOfValues);
#define NUMBER_OF_TEST_VALUES 10
int TestValues(NUMBER_OF_TEST_VALUES) = {
1, 2, 3, 4, 5, 6, 7, 8, 9, 10
};
main()
{
printf("Среднее арифметическое равно: %f\n",
Average(TestValues, NUMBER_OF_TEST_VALUES));
}
float IntDivide(int Divedent, int Divisor)
}
return( (float) Divident / (float) Divisor );
Турбо Ассемблер 3.0/tasm/#2-2 = 115 =
}
а часть программы на Ассемблере (AVERAGE.ASM) имеет вид:
;
; Вызываемая из С++ функция с малой моделью памяти,
; которая возвращает среднее арифметическое последова-
; тельности целых чисел. Для выполнения завершающего
; деления вызывает функцию С++ IntDivide().
;
; Прототип функции:
; extern float Average(int far * ValuePtr,
; int NumberOfValues);
;
; Ввод:
; int far * ValuePtr: ; массив значений для
; ; вычисления среднего
; int NumberOfValues: ; число значений для
; ; вычисления среднего
.MODEL SMALL
EXTRN _IntDivide:PROC
.CODE
PUBLIC _Average
_Average PROC
push bp
mov bp,sp
les bx,[bp+4] ; ES:BX указывает на
; массив значений
mov cx,[bp+8] ; число значений, для
; которых нужно
; вычислить среднее
mov ax,0
AverageLoop:
add ax,es:[bx] ; прибавить текущее
; значение
add ax,2 ; ссылка на следующее
; значение
loop AverageLoop
push WORD PTR [bp+8] ; получить снова число
; значений, переданных
; в функцию IntDivide
; в правом параметре
push ax ; передать сумму в
; левом параметре
call _IntDivide ; вычислить среднее
; значение с плавающей
; точкой
add sp,4 ; отбросить параметры
pop bp
ret ; среднее значение в
; регистре вершины
; стека сопроцессора
; 8087
Турбо Ассемблер 3.0/tasm/#2-2 = 116 =
_Average ENDP
END
Основная функция (main) на языке С++ передает указатель на
массив целых чисел TestValues и длину массива в функцию на Ас-
семблере Average. Эта функция вычисляет сумму целых чисел, а за-
тем передает эту сумму и число значений в функцию С++ IntDivide.
Функция IntDivide приводит сумму и число значений к типу с плава-
ющей точкой и вычисляет среднее значение (делая это с помощью од-
ной строки на С++, в то время как на Ассемблере для этого потре-
бовалось бы несколько строк). Функция IntDivide возвращает сред-
нее значение (Average) в регистре вершины стека сопроцессора 8087
и передает управление обратно основной функции.
Программы CALCAVG.CPP и AVERAGE.ASM можно скомпилировать и
скомпоновать в выполняемую программу CALCAVG.EXE с помощью коман-
ды:
bcc calcavg.cpp average.asm
Отметим, что функция Average будет работать как с малой, так
и с большой моделью данных без необходимости изменения ее исход-
ного кода, так как во всех моделях передается указатель дальнего
типа. Для поддержки больших моделей кода (сверхбольшой, большой и
средней) пришлось бы только изменить соответствующую директиву
.MODEL.
Пользуясь преимуществами расширений, обеспечивающих незави-
симость Турбо Ассемблера от языка, ассемблерный код из предыдуще-
го примера можно записать более сжато (CONSISE.ASM):
.MODEL small,C
EXTRN C IntDivide:PROC
.CODE
PUBLIC C Average
Average PROC C ValuePtr:DWORD, NumberOfValues:WORD
les bx,ValuePtr
mov cx,NumberOfValues
mov ax,0
AverageLoop:
add ax,es:[bx]
add bx,2 ;установить указатель
;на следующее значение
loop AverageLoop
call _IntDivide C,ax,NumberOfValues
ret
Average ENDP
END
Турбо Ассемблер 3.0/tasm/#2-2 = 117 =
Глава 19. Интерфейс Турбо Ассемблера с Турбо Паскалем
ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД
В Турбо Ассемблере предусмотрены расширенные и мощные
средства, позволяющие вам добавлять код Ассемблера к программам
Турбо Паскаля. В данной главе мы подробно расскажем вам о том,
что нужно знать, чтобы полностью использовать данные средства,
приведем множество примеров и дадим некоторую более глубокую ин-
формацию.
Большинство программ, которые вы захотите написать, можно
реализовать целиком на Турбо Паскале. В отличие от большинства
других компиляторов Паскаля, Турбо Паскаль позволяет вам с по-
мощью массивов Port[], Mem[], MemW[] и MemL[] непосредственно об-
ращаться ко всем ресурсам компьютера, а с помощью процедур
Intr() и MsDos() вы можете обращаться к базовой системе ввода-вы-
вода (BIOS) и операционной системе.
Для чего же тогда может потребоваться использовать совместно
с Турбо Паскалем Ассемблер? Для этого существуют две вероятные
причины: выполнение некоторого небольшого числа операций, которые
непосредственно в Турбо Паскале недоступны, и использование преи-
муществ высокой скорости работы, которые дает Ассемблер. (Сам
Турбо Паскаль работает достаточно быстро, потому что он написан
на языке Ассемблера.) В данной главе мы покажем вам, как можно
использовать в Турбо Паскале преимущества Ассемблера.
 |
|