Читайте также:
|
|
; Секция констант
integer_1 EQU [ВР+6]; задает адрес первого аргумента
integer_2 EQU [BP+8]; задает адрес второго аргумента
.MODEL medium; указываем компилятору, что он должен
; использовать модель памяти MEDIUM
.CODE; начало кодового сегмента
PUBLIC _Add_Int; эта функция - общедоступна
_Add_Int PROC FAR; имя функции и ее тип (дальняя)
push BP; эти две инструкции инициализируют
; фрейм стека
mov ВР, SP
mov AX,integer_1; помещаем первое слагаемое
; в аккумулятор (регистр АХ)
add AX,integer_2; добавляем второе, слагаемое
; к содержимому АХ
pop ВР; ликвидируем фрейм стека
_Add_Int ENDP; конец процедуры
END; конец кодового сегмента
Единственное, что мы изменили по сравнению с Листингом 2.1, это добавили несколько строк кода и ввели определения для адресов параметров. Теперь давайте проанализируем то, что у нас получилось.
§ Как и в предыдущем листинге, здесь были использованы директивы ассемблера для указания модели памяти, способа вызова, начала и конца функции;
§ EQU — это простая директива, заменяющая одну строку на другую. Я прибег к ней потому, что мне не хотелось в тексте самой функций использовать синтаксические конструкции [ВР+6] и [BP+8]. Строки, задающие выражения, которые будут подставлены при компиляции, это:
integer_l EQU [ВР+6]
integer_2 EQU [BP+8]
В общем, использование таких подстановок позволяет сделать ассемблерную программу более читабельной. Единственной альтернативой такому подходу является написание команды индексирования относительно содержимого одного из регистров (типа [ВР+6]).
Директива USES
Надо сказать, что ассемблер MASM, начиная с версии 5.1, имеет некоторые новые директивы, упрощающие порядок передачи параметров и создания фрейма стека. Для этого вы можете использовать директиву USES вместе с директивой PROC. Они сообщат ассемблеру, какие именно регистры будут использоваться в функции. Директива USES оберегает вас от всей рутины, связанной с определением стекового фрейма и подстановками переменных. Более того, она генерирует код пролога и эпилога для сохранения регистров, которые вы указали для использования в функциях. Таким образом, содержимое этих регистров не будет изменено, когда процедура вернет управление вызвавшей ее Си-функции.
Внимание!
Помните, что Си и ассемблер используют одни и те же регистры процессора. Если вы пользуетесь регистром в ассемблерной программе, то должны его сохранить в стеке и восстановить перед завершением функции. Иначе, ваша Си-программа может просто "сломаться" в момент выхода из вызова ассемблерной вставки.
Директива PROC и относящийся к ней уточнитель USES имеет следующий синтаксис.
label PROC [[attributes]] [[USES register_list]] [[,]]
[[parameter list][:type]]...]]
§ Поле label — это имя процедуры;
§ Поле attributes сообщает ассемблеру свойства вашей процедуры. Она может содержать множество параметров, таких как тип процедуры (NEAR или FAR), «видимость» процедуры (PUBLIC или PRIVATE) и, наконец, тип языка (С, PASCAL и т. д.). Эта возможность делает наши программы на ассемблере более читаемыми. Правда, это связывает руки, но зато программы обретают определенную элегантность;
§ Поле register_list показывает, какие регистры будет использовать функция. При этом ассемблер генерирует код, который может сохранить их на время работы процедуры и восстановить при выходе;
§ Поле parameter_list очень похоже на список параметров в Си;
Для каждой передаваемой процедуре переменной должен быть указан тип, определяющий их размер (например, BYTE или WORD). Тип задается в поле type.
Если вы пишите процедуру, в которую передаете три целых величины, и будете использовать регистры SI, DI и СХ, то должны включить следующий оператор:
far proc USES SI DI СХ, integer_1:WORD, integer_2:WORD,
integer_3:WORD
Используя директивы PROC и USES, давайте перепишем процедуру из Листинга 2.2.
Дата добавления: 2015-07-12; просмотров: 85 | Нарушение авторских прав
<== предыдущая страница | | | следующая страница ==> |
Листинг 2.1. Прототип процедуры для MASM 5.0 и более старших версий. | | | Листинг 2.3. Модифицированная версия Add_Int. |