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

7.4. Использование локальных данных

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

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

SUB SP, 6

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

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

Вариант 1

PUSH ВР ; Сохранить значение ВР при вызове

MOV BP, SP ; Установить новое значение ВР

SUB SP, n ; Выделить n байтов

..............

MOV SP, BP ; Освободить память

POP ВР ; Восстановить ВР

RЕТ

Вариант 2

PUSH ВР ; Сохранить значение ВР при вызове

SUB SP, n ; Выделить n байтов

MOV BP, SP ; Установить новое значение ВР

..........

ADD SP, n ; Освободить память

POP ВР ; Восстановить ВР

RET

Обратите внимание на то, что в первом варианте указатель базы устанавлива­ется до выделения в стеке памяти для локальных данных, а во втором — после выделения памяти.

В первом варианте указатель базы продолжает показывать на ту ячейку стека, на которую показывал указатель стека до выделения памяти для локальных данных. Поэтому перед выполнением команды RET стек можно очистить от этих данных путем присвоения указателю стека значения указателя базы.

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

7.5. Использование альтернативных моделей распределения памяти

При использовании больших моделей распределения памяти для адреса требу­ется четыре байта: два для адреса сегмента и два для относительного адреса. В модели распределения памяти с большим сегментом команд для адресов функций потребуется четыре байта. При модели распределения памяти с большим сегментом данных для адресов объектов данных потребуется четыре байта.

Если подпрограммы на языке ассемблера будут кодироваться для использования в большом сегменте команд, то псевдооператор PROC должен иметь вид

NAME PROC FAR.

Если подпрограмма на языке ассемблера использует внешнюю функцию на язы­ке Си, рассчитанную на большой сегмент команд, то имени этой функции также должен быть приписан атрибут FAR:

EXTRN _CFUNC:FAR.

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

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

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

LES ВХ, [ ВР ] + смещение ; "смещение" – положение адреса в стеке

MOV AX, ES : [ BX ] ; поместить значение по заданному адресу

Команда LES языка ассемблера загружает в регистры 4-байтовый указатель. Два старших байта загружаются в заданный регистр (в данном случае – ВХ), а младшее слово (адрес сегмента) за­гружается в регистр дополнительного сегмента ES. Команда имеет формат

LES регистр16, память32,

где регистр16 – любой 16-битовый регистр общего назначения, а память32 – ячейка памяти с атрибутом типа DOUBLEWORD. Операнд память32 может определяться псевдооператором DD.

В результате регистр ES можно использовать в других командах (например, MOV) для извлечения содержимого ячейки большого сегмента данных.

Аналогичная команда LDS (загрузить указатель с использо­ванием регистра DS) считывает из памяти 32-битовое двойное слово и загружает первые 16 битов в заданный регистр, а следующие 16 битов – в регистр сегмента данных DS. Она имеет тот же формат.

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