| |
BIGLIB |
| большущая библиотека (9812 книг), можно не только прочитать но и скачать бесплатно |
|
| |
ФАНТАСТИКА |
| фентези,
фантастика, фантастические повести |
|
| |
ФИЛОСОФИЯ |
книги, которые заставляют
задуматься над окружающим тебя миром.
|
|
| |
МЕДИЦИНА |
медицинские книги,
методички,
народные лечебники |
|
| |
КУЛИНАРИЯ |
рецепты
тортов, консервирование,
все о спиртных
напитках. |
|
| |
СТИХИ |
| стихи популярных
и не очень авторов |
|
| |
ТВОРЧЕСТВО |
| народное творчество,
стихи, песни и т.д. |
|
| |
ЮМОР |
| анекдоты, приколы,
смешные истории |
|
| |
ЭРОТИКА |
| эротические рассказы,
книги о технике секса,
кама-сутра и др. |
|
|
| |
 |
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 ; если <= 0, то конец
mov ax,[bp+4] ; Загрузить первую величину в ax
jmp ltest ; переход на цикл ;проверки
compare: cmp ax,[bp+6] ; Cравнить со след. величиной
jle ltest ; если след. величина меньше
mov ax,[bp+6] ; Загрузить в ах след. величину
ltest: add bp,2 ; Перейти к след. величине
loop compare ; затем в цикле назад
exit: pop bp ; Восстановить bp
ret ; И возврат в Си
_min ENDP
Заметим, что эта версия правильно управляет всеми возможными
значениями count.
- Если count <= 0, min возвращает 0;
- Если count = 1, min возвращает первую величину в списке;
- Если count >= 2, min организует цикл сравнения для поиска
наименьшего значения в списке параметров.
- 403,404 -
Соглашения по регистрам
-----------------------------------------------------------------
В min вы использовали различные регистры (BP, SP, AX,
BX,CX). Возникает вопрос о надежном их использовании. Может ли
программа, написанная на Турбо Си, использовать любые регистры?
Оказывается, вы правильно написали эту функцию. Из всех использо-
ванных регистров предметом ваших забот был лишь регистр BP; вы
сохранили его в стеке при входе и восстановили затем при выходе.
Другие 2 регистра, о которых вы должны побеспокоиться - это
SI и DI: эти регистры Турбо Си использует для регистровых пере-
менных. Если вы используете их только в ассемблерной подпрограм-
ме, то их нужно сохранить (вероятно в стеке) при входе в подпрог-
рамму и восстановить при выходе из нее. Однако, если вы
компилируете Турбо Си-программу с помощью опции -r- (Use register
variables - Off), то не нужно заботиться о сохранении SI и DI.
Замечание: будьте внимательны при использовании опции -r-.
Обратитесь к Приложению С "Справочного руководства по Турбо Си"
для получения более полной информации об опции register
variables.
Регистры CS,DS,SS и ES могут иметь соответствующие значения,
зависящие от используемой модели памяти. Вот эти соотношения:
Крохотная CS=DS=SS; ES=scratch (рабочий)
Малая, Средняя CS!=DS,DS=SS; ES=scratch
Компактная, Большая CS!=DS!=SS;ES=scratch(один CS на модуль)
Огромная CS!=DS!=SS;ES=scratch(по одному CS и DS
на модуль)
- 405,406 -
Вызов Си-функций из .ASM подпрограмм
-----------------------------------------------------------------
Конечно,можно использовать другой путь: вызвать подпрограммы
Си из модуля, написанного на ассемблере. Но при этом вы должны
сделать Си-функцию видимой из модуля, написанного на ассемблере.
Мы уже вкратце обсудили, как это делается: функция объявляется
как 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 -
ПРОГРАММИРОВАНИЕ НА НИЗКОМ УРОВНЕ:
псевдопеременные, встроенный ассемблер
и функции прерывания
-----------------------------------------------------------------
Предположим, что вы хотите выполнить какие-то действия на
уровне управления машиной, но предпочитаете не испытывать труд-
ностей, связанных с созданием отдельного модуля на языке ассемб-
|
adfun.ru
|
|
|
|