- •1. Внутренние регистры
- •1.1. Регистры данных
- •1.2. Регистры сегментов
- •1.3. Регистры указателей и индексов
- •1.4. Регистр командного указателя
- •1.5. Флаговый регистр
- •2. Структура и процесс разработки программы на языке ассемблера
- •2.1. Команды
- •2.2. Псевдооператоры
- •2.2.1. Псевдооператор segment
- •2.2.2. Псевдооператор proc
- •2.2.3. Псевдооператор assume
- •2.2.4. Псевдооператор end
- •2.2.5. Псевдооператоры определения данных
- •2.3. Инициализация программы
- •3. Команды пересылки данных
- •3.1. Команда mov
- •3.2. Команды push и рор
- •4. Режимы адресации
- •4.1. Регистровая и непосредственная адресация
- •4.2. Исполнительный адрес
- •4.3. Прямая адресация
- •4.4. Косвенная регистровая адресация
- •4.5. Адресация по базе
- •4.6. Прямая адресация с индексированием
- •4.7. Адресация по базе с индексированием
- •5. Команды передачи управления
- •5.1. Команды call и ret
- •5.2. Команда безусловного перехода jmp
- •5.3. Команды условной передачи управления
- •5.4. Команды управления циклами
- •6. Команды обработки строк
- •6.1. Команды пересылки строк movs, movsb, movsw
- •6.2. Префиксы повторения
- •6.3. Команды сравнения строк. Команда cmps.
- •6.4. Команды сканирования строк
- •6.5. Команды загрузки и сохранения строки
- •7. Взаимодействие языков Си и Ассемблера
- •7.1. Внутренняя структура программы на языке Си для ibm pc
- •7.2. Использование функций на языке Ассемблера
- •7.2.1. Основы взаимодействия языков Си и Ассемблера
- •7.2.2. Передача управления в подпрограмму и обратно
- •7.2.3. Использование глобальных данных
- •7.2.4. Использование аргументов функции
- •7.2.5. Возвращение значения через имя подпрограммы
- •7.2.6. Использование аргументов
- •7.3. Вызов функций на языке Си из программ на языке Ассемблера
- •7.4. Использование локальных данных
- •8. Арифметические команды
- •8.1. Форматы хранения десятичных чисел
- •8.2. Команды сложения
- •8.3. Коррекция результата сложения для bcd-форматов
- •8.4. Команда приращения значения приемника на единицу
- •8.5. Команды вычитания
- •8.6. Коррекция результата вычитания для bcd-форматов
- •8.7. Команда уменьшения содержимого приемника на единицу
- •8.8. Команда обращения знака
- •8.9. Команды умножения
- •8.10. Коррекция результатов умножения
- •8.11. Команды деления
- •8.12. Коррекция результатов деления
- •8.13. Команды расширения знака
- •9. Команды манипулирования битами
- •9.1. Логические команды and, or и xor
- •9.2. Команда логического отрицания nот
- •9.3. Команда проверки test
- •9.4. Команды сдвига и циклического сдвига
- •9.4.1. Команды сдвига
- •9.4.2. Команды циклического сдвига
- •10. Команды работы с флагами
- •10.1. Команды управления флагами
- •10.2. Команды пересылки флагов
- •11. Псевдооператоры определения идентификаторов и операции
- •11.1. Псевдооператоры определения идентификаторов
- •11.2. Операции
- •11.2.1. Арифметические операции
- •11.2.2. Логические операции
- •11.2.3. Операции отношения
- •11.2.4. Операции, возвращающие значения
- •11.2.5. Операции присваивания атрибутов
- •12. Условные псевдооператоры
- •13. Макроопределения
- •13.1. Сравнение макроопределений и процедур
- •13.2. Состав макроопределений
- •13.3. Псевдооператоры макроассемблера
- •13.3.1. Псевдооператор local
- •13.3.2. Псевдооператоры повторения
- •13.3.3. Условные псевдооператоры
- •13.3.4. Псевдооператор eхiтм
- •13.4. Операции в макроопределениях
- •13.5. Задание макроопределений в исходных программах
- •13.5.1. Использование библиотеки макроопределений
- •13.5.2. Указания для задания макроопределений
- •13.5.3. Считывание библиотеки макроопределений в программу
- •13.5.4. Удаление макроопределений
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. Она имеет тот же формат.
