Goto... Search.. Hext Change.. Follou Previous 3 глава

Goto... Search.. Hext Change.. Follou Previous 3 глава

;Чйсло шагов в цикле

fill:

;Отправим число в массив

;Инкремент числа-заполнителя

; Смещение в массиве к последующему слову

;На метку fill (CX раз)

Увеличение эффективности получается из-за того, что команда за­несения числа в элемент массива оказывается короче (потому что в неё не заходит адресок массива) и производится резвее, потому что этот адресок не нужно Goto... Search.. Hext Change.. Follou Previous 3 глава всякий раз считывать из памяти.

Базово-индексная адресация со смещением. Адресуется память (б либо слово). Относительный адресок операнда определяется как сумма со­держимого 2-ух регистров и смещения.

Это метод адресации является развитием предшествующего. В нем исполь­зуются те же пары регистров, но приобретенный с помощью их результирую­щий адресок Goto... Search.. Hext Change.. Follou Previous 3 глава можно еще сдвинуть на значение обозначенной в команде констан­ты. Как и в случае базово-индексной адресации, константа может пред­ставлять собой индекс (тогда и в одном из регистров должен содержаться базисный адресок памяти), но может быть и базисным адресом. В последнем случае регистры могут употребляться для Goto... Search.. Hext Change.. Follou Previous 3 глава хранения составляющих индекса. Приведем формальный пример рассматриваемого режима адресации.

Пусть в секторе данных определен массив из 24 байтов, в каком записаны коды латинских и российских знаков верхнего ряда клавиатуры:

Sims db "QWERTYUIOPO"

db "ЙЦУКЕНГШЩЗХЪ"

Последовательность команд

;Число байтов в строке

mov BX,12

mov SI,6

mov DL,syms[BX][SI]

загрузит в регистр Goto... Search.. Hext Change.. Follou Previous 3 глава DL элемент с индексом 6 из второго ряда, т.е. код ASCII буковкы Г. Тот же итог можно получить, загрузив в один из регистров не индекс, а адресок массива:

mov BX,offset sym

mov SI, 6

mov DL,12[BX][SI]



Глава 2


Базы программирования





2.6. Переходы

Как ранее говорилось в гл. 1, присущий микропроцессору метод выполне­ния программки Goto... Search.. Hext Change.. Follou Previous 3 глава принуждает его делать команды программки друг за дру­гом, в том порядке, как они были описаны в начальном тексте программки и содержатся в выполнимом модуле. Но нередко программеру требует­ся нарушить этот порядок, заставив микропроцессор обойти некий участок программки, перейти на выполнение другой ветки либо передать управле­ние подпрограмме Goto... Search.. Hext Change.. Follou Previous 3 глава, имея в виду после ее окончания возвратиться на пре­жнее место. Все эти операции осуществляются при помощи команд пере­ходов. Переходы делятся на бесспорные, когда передача управления в другую точку программки осуществляется в бесспорном порядке, неза­висимо ни от каких событий, и условные, осуществляемые либо не осуществляемые зависимо Goto... Search.. Hext Change.. Follou Previous 3 глава от тех либо других критерий: результатов срав­нения, анализа, поиска и т.п. Бесспорные переходы разделяются на фактически переходы (без возврата в точку перехода) и вызовы подпрог­рамм (с возвратом после окончания подпрограммы).

Операции переходов и вызовов подпрограмм, кроме их практичес­кой ценности, представляют значимый методический энтузиазм, потому что Goto... Search.. Hext Change.. Follou Previous 3 глава затрагивают базу архитектуры микропроцессора — сегментную адреса­цию памяти. Бессчетные разновидности команд переходов и вызо­вов должны своим существованием не столько потребностям практичес­кого программирования, сколько принципным строительным осо­бенностям микропроцессора. Ясное осознание этих особенностей и, соответственно, критерий внедрения и способностей рахчичных опера­ций переходов нужно не только лишь при использовании языка Goto... Search.. Hext Change.. Follou Previous 3 глава ассемб­лера, да и при программировании на языках высочайшего уровня, где время от времени употребляется несколько другая терминология, но существо дела остается без конфигурации.

Бесспорные переходы осуществляются при помощи команды jmp, которая может употребляться в 5 разновидностях. Переход может быть:

прямым маленьким (в границах -128...+127 байтов);

прямым ближним Goto... Search.. Hext Change.. Follou Previous 3 глава (в границах текущего сектора команд);

прямым далеким (в другой сектор команд);

косвенным ближним (в границах текущего сектора команд через ячейку

с адресом перехода);

косвенным далеким (в другой сектор команд через ячейку с адресом

перехода).

Разглядим поочередно структуру программ с переходами раз­ного вида.

Прямой маленький (short) переход. Прямым именуется переход, в Goto... Search.. Hext Change.. Follou Previous 3 глава ко­манде которого в очевидной форме указывается метка, на которую необходимо пе­рейти. Очевидно, эта метка должна находиться в том же программ­ном секторе, при всем этом помеченная ею команда может находиться как до, так и после команды jmp. Достоинство команды недлинного перехода состоит в том, что она занимает только 2 б памяти Goto... Search.. Hext Change.. Follou Previous 3 глава: в первом б записывается код операции (EBh), во 2-м — смещение к точке пере­хода. Расстояние до точки перехода отсчитывается от очередной команды,


т.е. команды, последующей за командой jmp. Так как требуется обеспе­чить переход как вперед, так и вспять, смещение рассматривается, как число со знаком Goto... Search.. Hext Change.. Follou Previous 3 глава и, как следует, переход может быть осуществлен мак­симум на 127 б вперед либо 128 б вспять. Прямой маленький переход оформляется последующим образом:

code segment

jmp short go ;Код ЕВ dd
go:

code ends

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

tasm /m2 p Goto... Search.. Hext Change.. Follou Previous 3 глава,p,p

то описатель short можно опустить, потому что ассемблер сам обусловит, что расстояние до точки перехода укладывается в маленький переход, даже если метка go размещена после строчки с командой jmp. При использо­вании транслятора MASM указание описателя short непременно (если метка go размещена после команды jmp). Тут появляются малозначительные Goto... Search.. Hext Change.. Follou Previous 3 глава различия ассемблеров различных разработчиков.

В комменты указан код команды; dd (от displacement, смещение) обозначает б со смещением к точке перехода от команды, последующей за командой jmp.

При выполнении команды прямого недлинного перехода микропроцессор при­бавляет значение б dd к младшему б текущего значения указателя команд IP (который, как уже говорилось, всегда показывает Goto... Search.. Hext Change.. Follou Previous 3 глава на команду, последующую за выполняемой). В итоге в IP оказывается адресок точки перехода, а предложения, находящиеся меж командой jmp и точкой перехода, не производятся. Меж иным, конструкция с прямым перехо­дом вперед нередко употребляется для того, чтоб обойти данные, которые по каким-то причинам лучше расположить Goto... Search.. Hext Change.. Follou Previous 3 глава в секторе команд.

Прямой ближний (near), либо внутрисегментный переход. Этот переход отличается от предшествующего только тем, что под смещение к точке пере­хода отводится целое слово. Это дает возможность выполнить переход в всякую точку 64-кбайтного сектора.

code segment

jmp go ;Код Е9 dddd
go:

code ends



Глава 2


Базы программирования




Метка go может находиться в Goto... Search.. Hext Change.. Follou Previous 3 глава любом месте сектора команд, как до, так и после команды jmp. В коде команды dddd обозначает слово с величи­ной относительного смещения к точке перехода от команды, последующей за командой jmp.

При выполнении команды прямого близкого перехода микропроцессор должен прибавить значение слова dddd к текущему значению указателя команд Goto... Search.. Hext Change.. Follou Previous 3 глава IP и сформировать тем адресок точки перехода. Что пред­ставляет собой смещение dddd? Какая это величина, со знаком либо без знака' Если рассматривать смещение как величину без знака, то переход будет вероятен только вперед, что, естественно, ошибочно. Если же смещение является величиной со знаком, то переход вероятен менее, чем на Goto... Search.. Hext Change.. Follou Previous 3 глава полсегмента вперед либо на полсегмента вспять, что тоже ошибочно. В дей­ствительности, рассматривая вычисление адреса точки перехода, следует подразумевать явление оборачивания, сущность которого можно коротко выра­зить такими соотношениями:

FFFFh+0001h=OOOOh

OOOOh-0001h=FFFFh j

i

Если поочередно наращивать содержимое какого-нибудь регистра либо ячейки памяти, то, достигнув верхнего вероятного предела FFFFh, число Goto... Search.. Hext Change.. Follou Previous 3 глава «перевалит» через эту границу, станет равным нулю и продолжит нарастать в области малых положительных чисел (1, 2, 3, и т.д.). Точно так же, если поочередно уменьшать некое положительное чис­ло, то оно, достигнув нуля, перейдет в область отрицательных (либо, что то же самое, огромных беззнаковых) чисел, проходя значения 2, 1, О, FFFFh, FFFEh Goto... Search.. Hext Change.. Follou Previous 3 глава и т.д.

Таким макаром, при вычислении адреса точки перехода смещение следует считать числом без знака, но при всем этом учесть явление обора­чивания. Если команда jmp находится кое-где сначала сектора команд, а смещение имеет величину порядка 64 К, то переход произойдет вперед, к концу сектора. Если же команда Goto... Search.. Hext Change.. Follou Previous 3 глава находится в конце сектора команд, а смещение имеет ту же величину порядка 64 К, то для определения точки перехода нужно двигаться по сектору вперед, дойти до его конца и про­должать передвигаться от начала сектора как и раньше вперед, пока не будет пройдено данное в смещении число Goto... Search.. Hext Change.. Follou Previous 3 глава байтов. Для обозначенных усло­вий мы попадем в точку, находящуюся неподалеку от команды jmp со сто­роны наименьших адресов.

Итак, при помощи команды близкого перехода (команда jmp без ка­ких-либо спецификаторов) можно перейти в всякую точку в границах дан­ного сектора команд. Для того, чтоб перейти в другой сектор команд, следует Goto... Search.. Hext Change.. Follou Previous 3 глава пользоваться командой далекого перехода.

Прямой далекий (far), либо межсегментный переход. Этот переход позво­ляет передать управление в всякую точку хоть какого сектора. При всем этом, оче­видно, подразумевается, что программный комплекс включает несколько частей команд. Команда далекого перехода имеет длину 5 б и вклю­чает, не считая кода операции Goto... Search.. Hext Change.. Follou Previous 3 глава EAli, к тому же полный адресок точки перехода, т.е.


сегментный адресок и смещение. Транслятору нужно сказать, что этот пе­реход — далекий (по дефлоту команда jmp транслируется, как коман­да близкого перехода). Это делается при помощи описателя far ptr, указы­ваемого перед именованием точки перехода.

codel segment

assume Goto... Search.. Hext Change.. Follou Previous 3 глава CS:codel ;Сообщим транслятору, что это сектор команд

jmp far ptr go ;Код EA dddd ssss

codel ends

code 2 segment

assume CS:code2 ;Сообщим транслятору, что это сектор команд

go:

code2 ends

Метка go находится в другом секторе команд этой двухсегментной программки. В коде команды ssss — сегментный адресок сектора code2, a dddd — смещение точки перехода go в секторе Goto... Search.. Hext Change.. Follou Previous 3 глава команд code2.

Заметим, что при наличии в программке нескольких частей команд, любой из их нужно предварять директивой ассемблера assume СВ:1шя_сегмента, которая докладывает транслятору о том, что начался оче­редной сектор команд. Это поможет транслятору верно обрабаты­вать адреса меток, встречающихся в этом секторе.

Освоив применение команд Goto... Search.. Hext Change.. Follou Previous 3 глава далеких переходов, мы получили возмож­ность создавать программки хоть какой длины. Вправду, предусмотрев в конце каждого программного сектора команду далекого перехода на на­чало последующего, мы можем включить в программный комплекс хоть какое число частей по 64 Кбайт. Единственное ограничение — чтоб все они поместились в памяти. В реальности так, естественно Goto... Search.. Hext Change.. Follou Previous 3 глава, не делают. Разум­нее дополнительные сегменты команд заполнить подпрограммами и вы­зывать их из основного сектора (либо друг из друга) по мере необходимо­сти. Но и в данном случае команды вызовов подпрограмм должны быть далекими. Разновидности подпрограмм и команд их вызова будут рассмот­рены ниже.

Все виды прямых переходов требуют Goto... Search.. Hext Change.. Follou Previous 3 глава указания в качестве точки пере­хода программной метки. С одной стороны, это очень наглядно; просмат­ривая текст программки, можно сходу найти, куда осуществляется переход. С другой стороны, таковой переход носит статический нрав — его нельзя настраивать по ходу программки. Еще больше суровый недоста­ток прямых переходов состоит Goto... Search.. Hext Change.. Follou Previous 3 глава в том, что они не дают возможность Перейти по известному абсолютному адресу, т.е. не позволяют обратиться ни к системным средствам, ни вообщем к другим загруженным в память Программкам (к примеру, резидентным). Вправду, программки опе­рационной системы не имеют никаких меток, потому что метка — это атри-



Глава 2


Основы^рограттрования




бут Goto... Search.. Hext Change.. Follou Previous 3 глава начального текста программки, а программки операционной системы транслировались не нами и находятся в компьютере исключительно в виде вы­полнимых модулей. А вот адреса каких-либо соответствующих точек системных программ найти можно, хотя бы из векторов прерываний. Для обра­щения по абсолютным адресам нужно пользоваться командами косвен­ных переходов, которые Goto... Search.. Hext Change.. Follou Previous 3 глава, как и прямые, могут быть ближними и далекими. Косвенный ближний (внутрисегментный) переход. Б отличие от команд прямых переходов, команды косвенных переходов могут использовать разные методы адресации и, соответственно, иметь много различных вариантов. Общим для их будет то, что адресок перехода не указывается очевидным образом в виде метки, а содержится или в Goto... Search.. Hext Change.. Follou Previous 3 глава ячейке памяти, или в одном из регистров, Это позволяет по мере надобности видоизменять адресок перехода, также производить переход по известному абсолютно­му адресу. Разглядим случай, когда адресок перехода хранится в ячейке сектора данных. Если переход ближний, то ячейка с адресом состоит из 1-го слова и содержит только смещение к точке Goto... Search.. Hext Change.. Follou Previous 3 глава перехода.

code segment

jmp DS:go_addr ;Код FF 26 dddd
go: ;Точка перехода

code ends data segment

go_addr dw go ;Адресок перехода (слово) data ends

Точка перехода go может находиться в любом месте сектора команд. В коде команды dddd обозначает относительный адресок слова go_addr в секторе данных, содержащем эту ячейку Goto... Search.. Hext Change.. Follou Previous 3 глава.

В приведенном куске адресок точки перехода в слове go_addr задан совершенно точно указанием имени метки go. Таковой вариант косвенного пере­хода делает практически те же функции, что и прямой (переход по единственному данному заблаговременно адресу), только несколько более запу­танным образом. Плюсы косвенного перехода будут более наглядны, если представить Goto... Search.. Hext Change.. Follou Previous 3 глава, что ячейка go_addr сначала пуста, а по ходу выполне­ния программки в нее, зависимо от каких-то критерий, помещается адресок той либо другой точки перехода:

mov mov mov

go_addr,gol go_addr,go2 go_addr,go3


Очевидно, приведенные выше команды должны производиться не вереницей, а альтернативно Goto... Search.. Hext Change.. Follou Previous 3 глава. В данном случае создается возможность перед выполнением перехода найти либо даже вычислить адресок перехода, требуемый в данных критериях.

Ассемблер допускает разные формы описания косвенного перехо­да через ячейку сектора данных:

jmp DS:go_addr jmp word ptr go_addr jmp go_addr

В первом варианте, использованном в приведенном выше куске Goto... Search.. Hext Change.. Follou Previous 3 глава, обозначено, через какой сегментный регистр надлежит обращаться к ячейке go_addr, содержащей адресок перехода. Тут допустима подмена сегме'нта, если сектор с ячейкой go_addr адресуется через другой сегментный ре­гистр, к примеру, ES либо CS.

Во 2-м варианте подчеркивается, что переход осуществляется через ячейку размером в одно слово и, как Goto... Search.. Hext Change.. Follou Previous 3 глава следует, является ближним. Ячейка go_addr могла быть объявлена при помощи директивы dd и содержать пол­ный двухсловный адресок перехода, требуемый для реализации далекого пе­рехода. Но сю можно пользоваться и для близкого перехода. Описа­тель word ptr перед именованием ячейки с адресом перехода принуждает трансля­тор считать Goto... Search.. Hext Change.. Follou Previous 3 глава, что она имеет размер 1 слово (независимо от того, как она была объявлена), и что переход, как следует, является ближним.

В конце концов, вероятен и самый обычный, 3-ий вариант, который со­впадает по форме с прямым переходом, но, все же, является кос­венным, потому что символическое обозначение go Goto... Search.. Hext Change.. Follou Previous 3 глава_addr является именованием поля данных, а не программной меткой. В этом варианте подразумевается, что сектор, в каком находится ячейка go_addr, адресуется по умолча­нию через регистр DS, хотя, как и во всех таких случаях, допустима заме­на сектора. Тип перехода (ближний либо далекий) определяется, исходя из размера ячейки go Goto... Search.. Hext Change.. Follou Previous 3 глава_addr. Но этот вариант не всегда вероятен. Для его правильной трансляции нужно, чтоб транслятору к моменту обработки предложения

jmp go_addr

было уже понятно, что собой представляет имя go_addr. Этого можно достигнуть 2-мя методами. 1-ый — расположить сектор данных до сег­мента команд, а не после, как в приведенном выше примере. 2-ой — вынудить Goto... Search.. Hext Change.. Follou Previous 3 глава транслятор обрабатывать начальный текст программки не один раз, как он это делает по дефлоту, а несколько. Число проходов для трансля­тора TASM можно задать при его вызове при помощи ключа /т#, где # — требуемое число проходов. В нашем случае довольно 2-ух проходов.

В приведенных примерах адресок поля памяти с Goto... Search.. Hext Change.. Follou Previous 3 глава адресом точки перехода задавался конкретно в коде команды косвенного перехода. Но этот адресок можно задать и в одном из регистров общего предназначения (ВХ, SI либо DI). Для приведенного выше примера косвенного перехода в точку


so


Глава 2


Базы программирования




go, адресок которой находится в ячейке go_addr в секторе данных, пере­ход с Goto... Search.. Hext Change.. Follou Previous 3 глава внедрением косвенной регистровой адресации может смотреться последующим образом:

mov BX,offset go_addr jmp [BX]

;B ВХ смещение поля с адресом перехода ;Переход в точку go

В особенности огромные способности предоставляет методика косвенного перехода с внедрением базово-индексной адресации через пары ре­гистров, к примеру, [BX][SI] либо Goto... Search.. Hext Change.. Follou Previous 3 глава [BX][DI]. Этот метод комфортен в тех случа­ях, когда имеется ряд других точек перехода, выбор которых за­висит от неких критерий. В данном случае в секторе данных создается не одно поле с адресом, а таблица адресов переходов. В базисный регистр ВХ загружается адресок этой таблицы, а в один из индексных Goto... Search.. Hext Change.. Follou Previous 3 глава регистров — оп­ределенный тем либо другим методом индекс в этой таблице. Переход осу­ществляется в точку, подобающую данному индексу. Структура про­граммы, использующий такую методику, смотрится последующим образом:

code segment mov BX,offset go_tbl mov SI,4 jmp [BX][SIj gol: go2: go3: code ends data segment go_tbl Goto... Search.. Hext Change.. Follou Previous 3 глава label word gol_addrdw gol go2_addrdw go2 go3_addrdw go3 data ends

;3агружаем в ВХ базисный адресок таблицы

вычисленное каким-то

;образом смещение в таблице

;Если индекс =4, переход в точку go3

;1-я точка перехода ;2-я точка перехода ;3-я точка перехода

;Таблица адресов переходов

;Адресок первой другой

;точки перехода

;Адресок 2-ой другой

;точки перехода

;Адрсс третьей другой

;точки Goto... Search.. Hext Change.. Follou Previous 3 глава перехода

Приведенный пример носит условный нрав; в реальной програм­ме индекс, помещаемый в регистр SI, должен рассчитываться по результа­там анализа неких критерий.

В конце концов, существует еще одна разновидность косвенного перехода, в каком не употребляется сектор данных, а адресок перехода помещается конкретно в один из регистров общего предназначения. Нередко Goto... Search.. Hext Change.. Follou Previous 3 глава таковой


переход относят к категории прямых, а не косвенных, но это вопрос не столько принципа, сколько терминологии.

Применительно к обозначениям последнего примера таковой переход будет смотреться, к примеру, последующим образом:

mov BX,oflset gol jmp BX

Тут, как и в прошлых вариантах, имеется возможность вычисле­ния адреса перехода, но нельзя этот адресок Goto... Search.. Hext Change.. Follou Previous 3 глава регистрировать.

Косвенный далекий (межсегментный) переход. Как и в случае ближ­него перехода, переход осуществляется по адресу, который содержится в ячейке памяти, но эта ячейка имеет размер 2 слова, и в ней содер­жится полный (сектор плюс смещение) адресок точки перехода. Програм­ма в данном случае должна включать само мало два сектора Goto... Search.. Hext Change.. Follou Previous 3 глава команд. Структура программки с внедрением косвенного далекого перехода может смотреться последующим образом:

codel segment

assume CS:code 1 ,DS:data

jmp DS:go_addr ; Код FF 2E dddd

codel ends code2 segment assume CS:code2

go: code 2 data

;Точка перехода в другом секторе команд

ends segment

go_addr dd go Двухсловный адресок Goto... Search.. Hext Change.. Follou Previous 3 глава точки перехода

data

ends

Точка перехода go находится в другом секторе команд этой двухсег-ментной программки. В коде команды dddd обозначает относительный ад­рес слова go_addr в секторе данных. Ячейка go_addr объявляется дирек­тивой dd (define double, найти двойное слово) и содержит двухслов­ный адресок точки перехода; в первом Goto... Search.. Hext Change.. Follou Previous 3 глава слове содержится смещение go в секторе команд codel, во 2-м слове сегментный адресок code2. Оба ком­понента адреса перехода могут быть вычислены и помещены в ячейку go_addr по ходу выполнения программки.

Как и в случае близкого косвенного перехода, ассемблер допускает разные формы описания далекого косвенного перехода через ячейку сектора Goto... Search.. Hext Change.. Follou Previous 3 глава данных:



Глава 2


Базы программирования


S3



jmp DS:go_addr ;Вероятна имена сектора

jmp dword ptr go_addr ;Если поле go_addr объявлено

;операторами dw
jmp go_addi Свойства ячейки должны

;быть известны

Для далекого косвенного перехода, как и для близкого, допустима адресация через регистр общего предназначения, если в него поместить адресок поля с адресом перехода:

mov BX Goto... Search.. Hext Change.. Follou Previous 3 глава,offset go_addr jmp [BX]

Может быть также внедрение базово-индексной адресации, если в сег­менте данных имеется таблица с двухсловными адресами точек переходов.

2.7. Вызовы подпрограмм

Фактически в хоть какой программке, независимо от се содержания, встре­чаются участки, которые требуется делать (может быть, с маленькими переменами) пару раз Goto... Search.. Hext Change.. Follou Previous 3 глава по ходу программки. Такие повторяющиеся участки целенаправлено выделить из общей программки, оформить в виде подпрограмм и обращаться к ним всякий раз, когда в основной програм­ме появляется необходимость их выполнения.

Подпрограмма, зависимо от выполняемых ею функций, может добиваться передачи из вызывающей программки определенных данных (на­зываемых аргументами, либо параметрами), возвращать в Goto... Search.. Hext Change.. Follou Previous 3 глава вызывающую про­грамму результаты вычислений либо обходиться и без того, и без другого.

Подпрограмма может быть оформлена в виде процедуры, тогда и имя этой процедуры будет служить точкой входа в подпрограмму:

drawline proc

; Подпрограмма -про цедура

ret endp

;Тело подпрограммы

;Команда возврата в вызывающую программку

drawlme

С таким же фуррором возможно Goto... Search.. Hext Change.. Follou Previous 3 глава обойтись без процедуры, просто пометив первую строчку программки некой меткой:

drawline: ; Под программка, начинающаяся с метки

;Тело подпрограммы

ret ;Команда возврата в вызывающую программку Продолжение основной программки либо ;другие подпрограммы

В любом случае вызов подпрограммы осущестшшется командой call. Подпрограмма должна завершаться командой ret, служащей для возврата управления в ту точку, откуда подпрограмма Goto... Search.. Hext Change.. Follou Previous 3 глава была вызвана.

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


как механизм выполнения и способности команд call и ret. При всем этом нужно подразумевать, что синтаксические особенности и закономерности исполь­зования команд Goto... Search.. Hext Change.. Follou Previous 3 глава call и jmp почти во всем совпадают, и значимая часть пояснений к командам перехода справедлива и для команд вызова.

Команда вызова подпрограммы call может употребляться в 4 разно­видностях. Вызов может быть:

прямым ближним (в границах текущего сектора команд);

прямым далеким (в другой сектор команд);

косвенным ближним (в границах текущего Goto... Search.. Hext Change.. Follou Previous 3 глава сектора команд через ячей­ку с адресом перехода);

косвенным далеким (в другой сектор команд через ячейку с адресом

перехода).

Разглядим поочередно перечисленные варианты.

code segment main proc call

Прямой ближний вызов. Как и в случае прямого близкого перехода, в команде прямого вызова в очевидной форме указывается адресок (смещение) точки входа Goto... Search.. Hext Change.. Follou Previous 3 глава в подпрограмму; в качестве этого адреса можно использовать как имя процедуры, так и имя метки, характеризующей точку входа в подпрограмму. В код команды, не считая кода операции E8h, заходит смеше­ние к вызываемой подпрограмме. В приведенном ниже примере подпрог­рамма оформлена в виде процедуры.

;Основная программка ;Код Е8 dddd

sub

Подпрограмма Goto... Search.. Hext Change.. Follou Previous 3 глава ;Код СЗ

main endp .

sub proc near

ret

sub endp code ends

Про цедура-программа находится в том же секторе команд, что и вызывающая программка. В коде команды dddd обозначает смещение в сег­менте команд к точке входа в подпрограмму. При выполнении команды call микропроцессор помещает адресок возврата (содержимое регистра IP) в стек выполняемой Goto... Search.. Hext Change.. Follou Previous 3 глава программки (рис. 2.16), после этого к текущему содержимому IP добавляет dddd. В итоге в IP оказывается адресок подпрограммы. Команда ret, которой завершается подпрограмма, делает оборотную функцию — извлекает из стека адресок возврата и вносит его в IP.

•\ Состояние стека после входа в подпрограмму

4— Начальное состояние SP

Рис. 2.16.Роль стека в механизме вызова ближней Goto... Search.. Hext Change.. Follou Previous 3 глава подпрограммы.



Глава'2


Базы программирования





Роль стека в механизме вызова подпрограммы и возврата из нее является решающим. Так как в стеке хранится адресок возврата, под­программа, сама используя стек, к примеру, для хранения промежуточ­ных результатов, должна к моменту выполнения команды ret возвратить стек в начальное состояние. Команда ret, естественно, никак Goto... Search.. Hext Change.. Follou Previous 3 глава не анализирует состояние либо содержимое стека. Она просто снимает со стека верхнее слово, считая его адресом возврата, и загружает это слово в указатель команд IP. Если к моменту выполнения команды ret указатель стека ока­жется смещенным в ту либо иную сторону, команда ret как и раньше Goto... Search.. Hext Change.. Follou Previous 3 глава будет рассматривать верхнее слово стека, как адресок возврата, и передаст по нему управление, что неизбежно приведет к краху системы.

; Основная программка far ptr subr ;Код 9А dddd ssss
;Объявляем подпрограмму. ;далекой ;Код СВ — далекий возврат

Прямой далекий вызов. Этот вызов позволяет обратиться к подпрог­рамме из другого сектора. В код команды, не Goto... Search.. Hext Change.. Follou Previous 3 глава считая кода операции 9Ah, заходит полный адресок (сектор плюс смещение) вызываемой подпрог­раммы. Обычно в начальном тексте программки при помощи описателя far ptr указывается, что вызов является далеким, хотя, если транслятор на­строен на трансляцию в два прохода, этот описатель не обязателен. Струк­тура программного комплекса Goto... Search.. Hext Change.. Follou Previous 3 глава, содержащая далекий вызов подпрограм­мы, может смотреться последующим образом:

codel assume segment CS:codel
main proc call far
main codel endp ends
code 2 assume segment CS:code2
subr proc far
ret
subr code 2 cndp ends

Процедура-подпрограмма находится в другом секторе команд той же программки. В коде команды dddd обозначает относительный адресок Goto... Search.. Hext Change.. Follou Previous 3 глава точки входа в подпрограмму в ее секторе команд, a ssss — ее сегментный адресок. При выполнении команды call микропроцессор помещает в стек сначшга сегмен­тный адресок вызывающей программки, а потом относительный адресок возвра­та (рис. 2.17). Дальше в сегментный регистр CS заносится ssss (у нас это значе­ние Goto... Search.. Hext Change.. Follou Previous 3 глава code2), а в IP — dddd (у нас это значение subr). Так как процедура-подпрограмма атрибутом far объявлена датьней, команда ret имеет код, хороший от кода аналогичной команды ближней процедуры и выполняет­ся по-другому: из стека извлекаются два верхних слова и переносятся в IP и CS, чем и осуществляется возврат в вызывающую Goto... Search.. Hext Change.. Follou Previous 3 глава программку, находящу­юся в другом секторе команд. В языке ассемблера существует и очевидное мне­моническое обозначение команды далекого возврата — retf.


^— Состояние стека после входа в подпрограмму

^— Начальное состояние SP Рис. 2.17. Роль стека в механизме вызова далекой подпрограммы.

Косвенный ближний вызов. Адресок подпрограммы содержится или в ячейке памяти, или Goto... Search.. Hext Change.. Follou Previous 3 глава в регистре. Это позволяет, как и в случае косвенного близкого перехода, видоизменять адресок вызова, также производить вызов не при помощи метки, а по известному абсолютному адресу. Струк­тура программки с косвенным вызовом подпрограммы может смотреться последующим образом:

code main
segment proc

;Основная программка


gotovaya-produkciya-eyo-uchet-i-realizaciya.html
gotovi-k-oborone-informacionnoe-agentstvo-uralbizneskonsalting-22082012-rossijskie-smi-o-mchs-monitoring-za-20-aprel-2013-g.html
gotovi-predostavit-otveti-na-vse-interesuyushie-vas-voprosi.html