| |
BIGLIB |
| большущая библиотека (9812 книг), можно не только прочитать но и скачать бесплатно |
|
| |
ФАНТАСТИКА |
| фентези,
фантастика, фантастические повести |
|
| |
ФИЛОСОФИЯ |
книги, которые заставляют
задуматься над окружающим тебя миром.
|
|
| |
МЕДИЦИНА |
медицинские книги,
методички,
народные лечебники |
|
| |
КУЛИНАРИЯ |
рецепты
тортов, консервирование,
все о спиртных
напитках. |
|
| |
СТИХИ |
| стихи популярных
и не очень авторов |
|
| |
ТВОРЧЕСТВО |
| народное творчество,
стихи, песни и т.д. |
|
| |
ЮМОР |
| анекдоты, приколы,
смешные истории |
|
| |
ЭРОТИКА |
| эротические рассказы,
книги о технике секса,
кама-сутра и др. |
|
|
| |
 |
PUBLIC _min
_min PROC near
.
.
.
- 393,394 -
_min ENDP
Это верно в предположении, конечно, что функция min будет
near-функцией. Если это far-функция, то вы должны заменить far на
near. Заметим, что min снабжено знаком подчеркивания для того,
чтобы компоновщик Турбо Си мог корректно установить связи.
Передача параметров
-----------------------------------------------------------------
Ваша первая задача - выбрать используемое в подпрограмме
соглашение по передаче параметров; учитывая приведенные ранее со-
ображения о трудностях использования Паскаль-соглашения, будем
избегать его и использовать Си-метод. Это означает, что когда
вызвана функция min, стек выглядит следующим образом:
SP + 04: v2
SP + 02: v1
SP: адрес возврата
Если вы хотите получить параметры, не изменяя содержания
стека, то для зтого необходимо сохранить базовый указатель (BP),
затем занести стековый указатель (SP) в базовый и использовать
его в качестве указателя на стек для извлечения из него необходи-
мых вам величин. Заметим, что после занесения BP в стек относи-
тельные смещения параметров возрастут на 2, т.к. в стек будут до-
бавлены 2 байта.
- 395,396 -
Управление возвращаемыми величинами
----------------------------------------------------------------
Ваша функция возвращает целую величину; куда вы ее помести-
те? Для 16-битных (2-байтных) величин (char, shot, int, enum,
near-указатели) вы используете регистр AX; для 32-битных (4-байт-
ных), включающих far- и huge-указатели - регистр DX для старшего
слова (или для адреса сегмента у указателей) и регистр AX для
младшего слова.
Величины float, double и long double возвращаются в регистре
top-of-stack (TOS) процессора 8087/80287, ST(0); если использует-
ся эмулятор 8087/80287, то величина возвращается в TOS регистр
эмулятора.
Величины структур возвращаются путем занесения их в стати-
ческую ячейку памяти и передачей указателя на эту ячейку (в АХ
для моделей с малыми данными, в DX:АХ для моделей с большими дан-
ными).
Вызывающая функция должна затем скопировать эту величину в
любом месте, где она необходима. Структуры длиной в 1 и 2 байта
возвращаются в АХ (подобно любой обычной целой), а 4-байтные
структуры в АХ и DX.
В примере с min вы имеете дело с 16-битной величиной, поэто-
му можете поместить ответ в АХ.
Ваша программа выглядит теперь так:
PUBLIC _min
_min PROC near
push bp ; Сохранить bp в стеке
mov bp,sp ; Загрузить sp в bp
mov ax,[bp+4] ; Переместить v1 в ax
cmp ax,[bp+6] ; Cравнить v1 и v2
jle exit ; если v1 > v2
mov ax,[bp+6] ; Загрузить в ax v2
exit: pop bp ; Восстановить bp
ret ; И возврат в Си
_min ENDP
А что изменится, если вы объявите min как far-функциюЯ? Ос-
- 397,398 -
новное отличие в том, что стек при входе будет выглядеть так:
SP + 06: v2
SP + 04: v1
SP + 02: сегмента возврата
SP: смещение возврата
Это означает, что смещение в стеке увеличилось на 2, т.к. в
стек внесены 2 дополнительных байта (сегмент возврата). Far-вер-
сия вашей программы будет выглядеть так:
PUBLIC _min
_min PROC far
push bp ; Сохранить bp в стеке
mov bp,sp ; Загрузить sp в bp
mov ax,[bp+6] ; Переместить v1 в ax
cmp ax,[bp+8] ; Cравнить v1 и v2
jle exit ; если v1 > v2
mov ax,[bp+6] ; Загрузить в ax v2
exit: pop bp ; Восстановить bp
ret ; И возврат в Си
_min ENDP
Заметим, что все смещения для v1 и v2 увеличились на 2, что
отражает добавление байтов в стеке.
А что если из каких-либо соображений вы объявите min как
Паскаль-функцию? Это равносильно вашему решению использовать Пас-
каль-соглашение по передаче параметров.
Ваш стек при входе будет выглядеть следующим образом (при
условии, что min является near-функцией):
SP + 04: v1
SP + 02: v2
SP: смещение возврата
Дополнительно вы должны соблюдать Паскаль-соглашения для
идентификатора min: писать его заглавными буквами и без подчерки-
вания.
Кроме изменения порядка занесения параметров v1 и v2 это
соглашение требует от min очистки стека при ее завершении. Это
делается указанием в команде RET количества байтов, пропускаемых
- 399,400 -
в стеке. В нашем случае вы должны пропустить в стеке 4 дополни-
тельных байта, используемых для v1 и v2 (адрес возврата извлечет-
ся с помощью RET автоматически).
Теперь модифицированная подпрограмма будет выглядеть так:
РUBLIC MIN
MIN PROC near ; Паскаль-версия
push bp ; Сохранить bp в стеке
mov bp,sp ; Загрузить sp в bp
mov ax,[bp+6] ; Переместить v1 в ax
cmp ax,[bp+4] ; Cравнить v1 и v2
jle exit ; если v1 > v2
mov ax,[bp+4] ; Загрузить в ax v2
exit: pop bp ; Восстановить bp
ret 4 ; Очистка стека и возврат
MIN ENDP
И последний пример, демонстрирующий, почему вам может потре-
боваться использовать Си-соглашение по передаче параметров. Пред-
положим, вы переопределили min следующим образом:
int extern min (int count, int v1, int v2, ...);
Теперь min может получать любое количество целых чисел и бу-
дет возвращать минимальное из них. Однако, т.к. min не имеет воз-
можности автоматически узнавать, сколько значений ей передано, то
первым ее параметром будет величина count, указывающая, сколько
величин следуют за ней.
Например, вы можете записать это так:
i = min (5, j, limit, indx, lcount, 0);
предполагая, что i, j, limit, indx и lcount - целые (или совмес-
тимого с int типа). Стек при входе будет выглядеть так:
SP + 08: (и т.д.)
SP + 06: v2
SP + 04: v1
SP + 02: count (счетчик)
SP: адрес возврата (смещение)
Теперь модифицированная версия min имеет вид:
- 401,402 -
|
adfun.ru
|
|
|
|