Страница 49 из 56
PUBLIC _min
_min PROC near
push bp ; Сохранить bp в стеке
mov bp,sp ; Загрузить sp в bp
mov ax,0 ; Занести в ax 0
mov cx,[bp+4] ; Переместить count в cx
cmp cx,ax ; Cравнить cx c 0
jle exit ; если
-----------------------------------------------------------------
Конечно,можно использовать другой путь: вызвать подпрограммы
Си из модуля, написанного на ассемблере. Но при этом вы должны
сделать Си-функцию видимой из модуля, написанного на ассемблере.
Мы уже вкратце обсудили, как это делается: функция объявляется
как EXTRN, независимо от того, какого она типа - near или far.
Например, вы написали следующую Си-функцию:
long docalc(int *fact1, int fact2, int fact3);
Для простоты предположим, что docalc - это Си-функция (т.е.
противоположна Паскаль-функции). Имея в виду использование кро-
хотной, малой или компактной модели памяти, вы должны Си-функцию
в модуле, написанном на ассемблере, объявить следующим образом:
EXTRN _docalc:near
Подобно этому, если вы использовали среднюю, большую или ог-
ромную модели памяти, то объявите функцию как _docalc:far.
docalc определяется тремя параметрами:
- адресом ячейки памяти - xval;
- значением, хранимым в ячейке - imax;
- константой 421 (десятичной).
Предположим также, что вам нужно сохранить результат в
32-разрядной ячейке памяти, называемой ans. Эквивалентный вызов в
Си будет таким:
ans = docalc (xval, imax, 421);
Вам необходимо занести в стек сначала 421, затем imax, после
этого адрес xval и, наконец, вызвать docalc. При возврате нужно
очистить стек, который увеличился на 6 дополнительных байт, и за-
тем занести ответ в ячейки памяти ans и ans+2.
Программа будет иметь вид:
mov ax,421 ; Занести в стек 421
push ax
push imax ; Занести в стек imax
lea ax,xval ; Занести в стек xval
- 407,408 -
push ax
call _docalc ; Вызов функции docalc
add sp,6 ; Очистка стека
mov ans,ax ; Занести 32-разрядный результат в ans
mov ans+2,dx ; Включая старшее слово
А что если docalc будет использовать Паскаль-соглашение по
передаче параметров? Тогда вам придется изменить порядок парамет-
ров на обратный, и не надо будет беспокоиться о чистке стека при
возврате, т.к. это должна сделать вызываемая подпрограмма. Кроме
того, вы должны соблюдать Паскаль-соглашение при написании docalc
(без символа подчеркивания (_) и в верхнем регистре).
Оператор EXTRN будет таким:
EXTERN DOCALC:near
а программа вызова docalc будет иметь вид:
lea ax,xval ; Занести в стек xval
push ax
push imax ; Занести в стек imax
mov ax,421 ; Занести в стек 421
push ax
call DOCALC ; Вызов функции docalc
mov ans,ax ; Занести 32-разрядный результат в ans
mov ans+2,dx ; Включая старшее слово
Вот и все, что вам необходимо знать, чтобы вы могли устано-
вить связь между языками.
- 409,410 -
ПРОГРАММИРОВАНИЕ НА НИЗКОМ УРОВНЕ:
псевдопеременные, встроенный ассемблер
и функции прерывания
-----------------------------------------------------------------
Предположим, что вы хотите выполнить какие-то действия на
уровне управления машиной, но предпочитаете не испытывать труд-
ностей, связанных с созданием отдельного модуля на языке ассемб-