Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Скачиваний:
86
Добавлен:
11.02.2014
Размер:
102.4 Кб
Скачать

Работа команд ret и retf

Алгоритм работы: Работа команд зависит от типа процедуры:

  • для процедур ближнего типа — восстановить из стека содержимое ip;

  • для процедур дальнего типа — последовательно восстановить из стека содержимое ip и сегментного регистра cs.

  • если команда ret имеет операнд, то увеличить содержимое sp на величину операнда число;

Состояние флагов после выполнения команды не меняется. Error: Reference source not found

Применение:Команду ret необходимо применять для возврата управления вызывающей программе из процедуры, управление которой было передано по команде call. На самом деле микропроцессор имеет три варианта команды возврата ret - это ret, ее синоним retn, а также команда retf. Они отличаются типами процедур, в которых используются. Команды ret и retn служат для возврата из процедур ближнего типа. Команда retf — команда возврата для процедур дальнего типа. Какая конкретно команда будет использоваться, определяется компилятором; программисту лучше использовать команду ret, и доверить транслятору самому сгенерировать ее ближний или дальний вариант. Количество команд ret в процедуре должно соответствовать количеству точек выхода из нее. Некоторые языки высокого уровня, к примеру Pascal, требуют, чтобы вызываемая процедура очищала стек от переданных ей параметров. Для этого команда ret содержит необязательный параметр число, который, в зависимости от установленного атрибута размера адреса, означает количество байт или слов, удаляемых из стека по окончании работы процедуры

Синтаксис директив ARG и LOCAL

Приведем синтаксис определения передаваемых процедуре аргументов:

ARG аргумент [,аргумент]... [=идентификатор]

[RETURNS аргумент] [,аргумент]]

При определении локальных переменных процедуры используется следующий синтаксис:

LOCAL аргумент [,аргумент]... [=идентификатор]

Отдельные аргументы имеют следующий синтаксис:

имя_аргумента [[выражение_счетчик_1]]

[: сложный_тип [:выражение_счетчик_2]]

где "сложный_тип" - это тип данных аргумента. Он может быть либо простым типом, либо сложным выражением-указателем.

"Выражение_счетчик_2" задает, сколько элементов данного типа определяет аргумент. Например, в определении аргумента:

ARG tmp:DWORD:4

определяется аргумент с именем "tmp", состоящий из 4 двойных слов.

По умолчанию "выражение_счетчик_2" имеет значение 1 (кроме аргументов типа BYTE). Так как вы не можете занести в стек байтовое значение, для аргументов типа BYTE значение счетчика по умолчанию равно 2, что обеспечивает для них в стеке размер в слово.

Это согласуется с языками высокого уровня, которые интерпретируют передаваемые в качестве параметров символьные переменные. Если вы действительно хотите задать аргумент, как один байт в стеке, нужно явным образом определить значение поля "выражение_счетчик_2", равное 1. Например:

ARG realbyte:BYTE:1

"Выражение_счетчик_1" представляет собой число элементов массива. Общее пространство, резервируемое для аргумента в стеке, равно произведению "выражения_счетчик_2" на длину, заданную полем "тип_аргумента" и на "выражение_счетчик_1". Если поле "выражение_счетчик_1" не задано, то по умолчанию оно равно 1. Общее число аргументов задает произведение "выражения"_счетчик_1" на "выражение_счетчик_2".

Если вы завершаете список аргументов символом равенства (=) и идентификатором, тоАссемблер будет приравнивать этот идентификатор к общему размеру блока аргументов (в байтах). Если вы не используете автоматическое использование соглашений языков высокого уровня вАссемблере, то можете использовать данное значение в конце процедуры в качестве аргумента инструкции RET. Заметим, что это вызывает очистку стека от всех занесенных туда перед возвратом аргументов (это соглашения по вызову, принятые в Паскале).

Аргументы и переменные определяются в процедуре как операнды в памяти относительно BP. Передаваемые аргументы, определенные с помощью директивы ARG, имеют положительное смещение относительно BP. Локальные переменные, определенные с помощью директивы LOCAL, имеют отрицательное смещение от BP. Приведем пример:

.

func1 PROC NEAR

ARG a:WORD,b:WORD:4,c:BYTE=d

LOCAL x:DWORD,y=WORD:2=z

.

Здесь a определяется, как [bp+4], b определяется, как [bp+6], c определяется, как [bp+14], а d - как 20. x - это [bp-2], y - [bp-6], а z - 8.

Область действия аргументов и имен локальных переменных

Если вы не задаете для них имена с предшествующий префиксом локального идентификатора, все аргументы, заданные в заголовке процедуры, определены ли они с помощью директивы ARG (передаваемые аргументы), RETURN (возвращаемые аргументы) или LOCAL (локальные переменные) имеют глобальную область действия.

Идентификаторы с локальной областью действия разрешает директива LOCALS. Например:

..

LOCALS

test1 PROC PASCAL FAR

ARG @a:WORD,@d:WORD,@c:BYTE

LOCAL @x:WORD,@y:DWORD

MOV ax,@a

MOV @x,ax

LES di,@b

MOV WORD ptr @y,di

MOV WORD ptr @y+2,es

MOV @c,'a'

RET

ENDP

test2 PROC PASCAL FAR

ARG @a:DWORD,@b:BYTE

LOCAL @x:WORD

LES di,@a

MOV ax,es:[di]

MOV @x,ax

CMP a1,@b

jz @dn

MVO @x,0

@dn: MOV ax,@x

RET

ENDP

..

Поскольку в данном примере используются переменные локальной области действия, их имена существуют только в теле процедуры. Таким образёом, в test2 можно снова использовать имена @a, @b и @x.

Сохранение регистров

Большинство языков высокого уровня требуют, чтобы вызываемые процедуры сохраняли определенные регистры. Это можно сделать, занося их в стек в начале процедуры и извлекая из стека в конце процедуры.

Ассемблер может автоматически генерировать код для сохранения и восстановления этих регистров, который включается в код начала и завершения. Эти регистры можно указать в операторе USES, который имеет следующий синтаксис:

USES элемент [,элемент]...

где "элемент" может быть регистром или состоящим из одной лексемы элементом данных, который можно заносить и извлекать из стека. В одной процедуре допускается использовать не более 8 элементов.

Например:

.

myproc PROC PASCAL NEAR

ARG @source:DWORD,@dest:DWORD,@count:WORD

USES cx,si,di,foo

MOV cx,@count

MOV foo,@count

LES di,@dest

LDS si,@source

REP MOVSB

ENDP

..

Вложенные процедуры и правила области действия

Хотя вы можете вкладывать одну процедуру в другую, все процедуры имеют глобальную область действия. Например:

.

test1 PROC FAR

; код процедуры

CALL test2

; код процедуры

RET

test2 PROC NEAR

; код процедуры

RET ; ближний возврат

test2 ENDP

test1 ENDP

.

В данном примере вне охватывающей процедуры можно вызывать test1 и test2.

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

.

LOCALS

test1 PROC FAR ; код процедуры

RET

@test2 PROC NEAR ; код процедуры

RET

@test2 ENDP

test1 ENDP

.

.

Примечание: Директива LOCALS разрешает идентификаторы с локальной областью действия.

В данном коде в процедуре test1 вы можете обратиться только к процедуре @test2. Фактически, если они не находятся в одной и той же процедуре может существовать несколько процедур с именем @test2. Например, допустимо следующее:

.

.

LOCALS

test1 PROC FAR

MOV si, OFFSET Buffer

CALL @test2

RET

@test2 PROC NEAR ; некоторый код

RET

@test2 ENDP

test2 PROC FAR

MOV si,OFFSET Buffer2

CALL @test2

RET

@test2 PROC NEAR ; некоторый код

RET

@test2 ENDP

test2 ENDP

.

Следующий код недопустим:

..

LOCALS

test1 PROC FAR

MOV si,OFFSET Buffer

CALL @test2

RET

test1 ENDP

@test2 PROC NEAR

; код процедуры

RET

@test2 ENDP

..

так как вызов @test2 задает локальный идентификатор для процедуры test1, а таких идентификаторов не существует.

Ниже приведены форматы соответствующих машинных команд. Прямой вызов NEAR-процедуры (для получения адреса перехода disp добавляется к IP):

Е8

disp_l

disp_h

Прямой вызов FAR-процедуры (offset и seg замещают IP и CS):

Е8

offset_l

offset_h

seg_l

seg_h

Задание 1 (2 часа)

  1. Повторить теоретический материал о процедурах по конспекту лекций и литературе.

  2. Прочитайте задание, которое выполняет нижеприведеннаяпрограмма, напишите эту программу с именем Lab7-1.asm.

  3. Сделайте исполняемый файл, и проследить за работой в Турбоотладчике с различными данными.

Задание 2 (2 часа)

  1. Напишите комментарий к каждой строке программы №7.1 с содержанием регистров.

  2. На основе проделанной работы сделать отчет, внести в него краткие выводы.

Следующая программа переводит содержимое регистра AX в шестнадцатеричное представление и записывает результат в строку смещение которой хранится в регистре BX

Соседние файлы в папке лабораторные работы по ASSAMBLER