Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
lec_asm_06_3495.doc
Скачиваний:
2
Добавлен:
01.04.2025
Размер:
178.18 Кб
Скачать

7.2.5. Возвращение значения через имя подпрограммы

Если подпрограмма возвращает только одно значение, то проще всего трактовать его как значение имени подпрограммы. Чтобы вызывающая программа могла воспринять возвращаемую сумму как значение имени подпрограммы, нужно следу­ющим образом модифицировать наш пример

extern “C” void sum();

main ()

{

int val;

int x = 10;

val = sum(x, 20, 20+5);

printf( "val = %d\n", val );

}

Вызывающая функция и подпрограмма должны придерживаться определенных соглашений относительно возвращения значения через имя подпрограммы. Многие компиляторы языка Си рассчитаны на то, что это значение хранится в одном или нескольких регистрах.

Рассмотрим общепринятые соглашения по использованию этих ресурсов на IBM PC .

Тип возвращаемого значения

Используемые регистры

Целый (16 битов)

АХ

Длинный целый (32 бита)

АХ, ВХ или DX, AX

Вещественный с двойной точностью (64 бита)

АХ, ВХ, СХ, DX

Чтобы в соответствии с этими соглашениями модифицировать подпрограмму SUM, надо просто удалить ссылки на внешний объект VAL и оставить вычисленный ею результат в регистре АХ. Т.е. удалить строку

MOV VAL, AX ; Поместить результат в VAL

Программа на языке Си извлечет результат из регистра АХ, когда ей будет возвращено уп­равление.

7.2.6. Использование аргументов

Если подпрограмма должна возвращать несколько значений, то она может использовать для этой цели свои аргументы. На языке Си это производится путем передачи аргументов по адресу. Доступ к аргументам, передаваемым по адресу, можно получить и в подпрограммах на языке ассемблера.

Еще раз модифицируем подпрограмму SUM: теперь у нее будет четыре аргумента и результат будет возвращаться через последний из них. Ее вызов будет иметь следующий вид:

sum(x, 20, 20+5, & val);

После загрузки адреса val в регистр ВХ мы сможем поместить по этому адресу значение, используя косвенную регистровую адресацию.

MOV ВХ, [ ВР ] +10 ; Загрузить адрес, по которому должен быть

; помещен результат

MOV [ ВХ ], АХ ; Поместить значение суммы по этому адресу

7.3. Вызов функций на языке Си из программ на языке Ассемблера

Чаще всего приходится вызывать подпрограммы на языке ассемблера из функций на языке Си. Однако можно вызывать функции на языке Си из программ на языке ассемблера.

Для этого надо объявить имя функции на языке Си в прог­рамме на языке ассемблера путем использования псевдооператора EXTRN, который должен следовать за псевдооператором SEGMENT.

Если имя функции на языке Си myfunc, то для моделей распределения памяти с малыми кодами ее объявление будет иметь вид

EXTRN _MYFUNC : NEAR

Чтобы вызвать функцию на языке Си, ее каждый аргумент нужно поместить в стек, начиная с последнего аргумента, а затем вызвать функцию с помощью команды CALL.

После возвращения из функции на языке Си программа на языке ассемблера должна очистить стек, удалив из него все ранее помещенные аргументы. Для этого можно с помощью команды POP извлечь их один за другим. Но легче всего просто увеличить содержимое указателя стека на целое значение, которое равно числу байтов, ранее помещенных в стек (напомним, что команда PUSH уменьшает содержимое указателя стека).

Приведем пример вызова из программы на языке Ассемблера функции на языке Си, которой требуются три целых аргумента.

PGROUP GROUP PROG

PROG SEGMENT BYTE PUBLIC 'PROG'

EXTRN _MYFUNC: NEAR ; имя Си-функции

ASSUME CS: PGROUP

PUBLIC ASMFUNC

ASMFUNC PROC NEAR

PUSH AX ; значения аргументов

PUSH ВХ ; находятся в регистрах

PUSH СХ ; АХ, ВХ и СХ

CALL MYFUNCT ; вызвать Си-функцию

ADD SP, 6 ; очистить стек от

................... ; значений аргументов

В этом примере перед исполнением команды CALL исполняются три команды PUSH, в результате чего содержимое указателя стека уменьшается на шесть бай­тов. Увеличение указатель стека SP на шесть после исполнения команды CALL позволяет восстановить его исходное содержимое.

Если данные определены внутри программы на языке ассемблера, то их можно сделать доступными функциям на языке Си, объявив их

– общедоступными с помощью псевдооператора PUBLIC в сегменте данных программы на языке ассем­блера,

– внешними с помощью служебного слова extern в функции на языке Си.

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]