КАТЕГОРИИ: Архитектура-(3434)Астрономия-(809)Биология-(7483)Биотехнологии-(1457)Военное дело-(14632)Высокие технологии-(1363)География-(913)Геология-(1438)Государство-(451)Демография-(1065)Дом-(47672)Журналистика и СМИ-(912)Изобретательство-(14524)Иностранные языки-(4268)Информатика-(17799)Искусство-(1338)История-(13644)Компьютеры-(11121)Косметика-(55)Кулинария-(373)Культура-(8427)Лингвистика-(374)Литература-(1642)Маркетинг-(23702)Математика-(16968)Машиностроение-(1700)Медицина-(12668)Менеджмент-(24684)Механика-(15423)Науковедение-(506)Образование-(11852)Охрана труда-(3308)Педагогика-(5571)Полиграфия-(1312)Политика-(7869)Право-(5454)Приборостроение-(1369)Программирование-(2801)Производство-(97182)Промышленность-(8706)Психология-(18388)Религия-(3217)Связь-(10668)Сельское хозяйство-(299)Социология-(6455)Спорт-(42831)Строительство-(4793)Торговля-(5050)Транспорт-(2929)Туризм-(1568)Физика-(3942)Философия-(17015)Финансы-(26596)Химия-(22929)Экология-(12095)Экономика-(9961)Электроника-(8441)Электротехника-(4623)Энергетика-(12629)Юриспруденция-(1492)Ядерная техника-(1748) |
Процедуры в языке ассемблера
В ассемблере есть еще две команды перехода - CALL (переход с возвратом) и RET (возврат из подпрограммы) Переход с возвратом: CALL <операнд1> Эта команда записывает адрес следующей за ней команды в стек и затем делает переход по адресу, определяемому операндом <операнд1>. Она используется для переходов на подпрограммы с запоминанием в стеке адреса возврата. Имеются следующие разновидности этой команды (они аналогичны вариантам команды безусловного перехода JMP): - внутрисегментный относительный длинный переход (<операнд1> - непосредственный операнд размером в слово, а в ассемблере - это метка из текущего сегмента команд или имя близкой процедуры, в этом случае в стек заносится только текущее значение счетчика команд IP, т.е. смещение следующей команды; - внутрисегментный абсолютный косвенный переход (<операнд1> - адрес слова памяти, в которой находится адрес (смещение) той команды, на которую и будет сделан переход); и здесь в стек записывается только смещение адреса возврата; - межсегментный абсолютный прямой переход (<операнд1> - непосредственный операнд вида seg:ofs, а в ассемблере - это FAR PTR <метка> или имя дальней процедуры, здесь в стек заносятся текущие значения регистров CS и IP (первым в стек записывается содержимое CS), т.е. абсолютный адрес возврата, после чего меняются регистры CS и IP; - межсегментный абсолютный косвенный переход (<операнд1> - адрес двойного слова, в котором находится пара seg:ofs, задающая абсолютный адрес перехода); и здесь в стеке спасается содержимое регистров CS и IP. Переход (возврат) по адресу из стека: RET <операнд1> Из стека считывается адрес и по нему производится переход. Если указан операнд (а это должно быть неотрицательное число), то после чтения адреса стек еще очищается на это число байтов (к SP добавляется это число). Команда используется для возврата из подпрограммы по адресу, записанному в стек по команде CALL при вызове подпрограммы, и одновременной очистки стека от параметров, которые основная программа занесла в стек перед обращением к подпрограмме. В ПК стек в основном используется для организации подпрограмм и прерываний. Однако, даже если программе не нужен стек, она все равно должна отвести под него место. Дело в том, что стеком будет неявно пользоваться операционная система при обработке прерываний, которые возникают (например, при нажатии клавиш на клавиатуре) в то время, когда выполняется программа. Для нужд ОС рекомендуется выделять в стеке 64 байта. В конкретных случаях можно использовать более простые схемы. Например, параметры можно передавать не через стек, а через регистры, место под локальные величины можно отводить не в стеке, а в сегменте данных и т.п. При составлении и вызове подпрограмм необходимо следить за тем, чтобы команды CALL и RET действовали согласовано - были одновременно близкими или дальними. В ассемблере эта проблема снимается, если подпрограмму описать как процедуру. Процедуры имеют следующий вид: имя_процедуры PROC [NEAR или FAR] ... имя_процедуры ENDP Хотя в директиве PROC после имени процедуры не ставится двоеточие, это имя относится к меткам и его можно указывать в командах перехода, в частности в команде CALL, когда надо вызвать процедуру. Это же имя должно быть повторено в директиве ENDP, заканчивающей описание процедуры. Предложения между этими двумя директивами образуют тело процедуры (подпрограмму). Имя процедуры является фактически меткой первой из команд тела, поэтому данную команду не надо специально метить. Если в директиве PROC указан параметр NEAR или он вообще не указан, то такая процедура считается "близкой" и обращаться к ней можно только из того сегмента команд, где она описана. Дело в том, что ассемблер будет заменять все команды CALL, где указано имя данной процедуры, на машинные команды близкого перехода с возвратом, а все команды RET внутри процедуры - на близкие возвраты. Если же в директиве PROC указан параметр FAR, то это "дальняя" процедура: все обращения к ней и все команды RET внутри нее рассматриваются ассемблером как дальние переходы. Обращаться к этой процедуре можно из любых сегментов команд. Таким образом, достаточно лишь указать тип процедуры (близкая она или дальняя), всю же остальную работу возьмет на себя ассемблер: переходы на нее и возвраты из нее будут автоматически согласованы с этим типом. В этом главное (и единственное) достоинство описания подпрограмм в виде процедур. Например, вычисление AX:=SIGN(AX) можно описать в виде процедуры следующим образом: SIGN PROC FAR; дальняя процедура CMP AX,0 JE sgn1; AX =0 - перейти к sgn1 MOV AX,1; AX:=1 (флаги не изменились!) JG sgn1; AX >0 - перейти к sgn1
MOV AX,-1; AX:=-1 sgn1: RET; дальний возврат SIGN ENDP ... Возможный пример обращения к этой процедуре: ; CX:= SIGN (VAR) MOV AX, VAR CALL SIGN; дальний вызов MOV CX, AX
Дата добавления: 2014-11-09; Просмотров: 1520; Нарушение авторских прав?; Мы поможем в написании вашей работы! Нам важно ваше мнение! Был ли полезен опубликованный материал? Да | Нет |