
- •140010, Г. Люберцы, Московской обл., Октябрьский пр-т, 403.
- •Глава 1. Архитектура реального режима
- •1.1. Память и процессор
- •Глава 1
- •Глава 1
- •1.2. Распределение адресного пространства
- •Глава 1
- •1.3. Регистры процессора
- •Глава 1
- •Глава 1
- •9 7H Шестнадцатернчное обозначение числа
- •Глава 1
- •1.4. Сегментная структура программ
- •Глава 1
- •Глава 1
- •Глава 1
- •1.5. Стек
- •Глава 1
- •1.6. Система прерываний
- •Глава 1
- •Глава I
- •1.7. Система ввода-вывода
- •Глава I
- •Глава 1
- •Глава 2. Основы программирования
- •2.1. Подготовка и отладка программы
- •Глава 2
- •Глава 2
- •Глава 2
- •Глава 2
- •Глава 2
- •2.2. Представление данных
- •Глава 2
- •Глава 2
- •2.3. Описание данных
- •Глава 2
- •Глава 2
- •2.4. Структуры и записи
- •Глава 2
- •Глава 2
- •2.5. Способы адресации
- •Глава 2
- •Глава 2
- •Глава 2
- •Глава 2
- •Глава 2
- •Глава 2
- •Глава 2
- •Глава 2
- •Глава 2
- •Глава 2
- •2.7. Вызовы подпрограмм
- •Глава 2
- •2.8. Макросредства ассемблера
- •Глава 2
- •Глава 2
- •Глава 2
- •Глава 3. Команды и алгоритмы
- •Глава 3
- •Глава 3
- •Глава 3
- •Глава 3
- •Глава 3
- •Глава 3
- •Глава 3
- •Глава 3
- •3.2. Циклы и условные переходы
- •Глава 3
- •Глава 3
- •3.3. Обработка строк
- •Глава 3
- •3.4. Использование подпрограмм
- •Глава 3
- •Глава 3
- •3.5. Двоично-десятичные числа
- •Глава 3
- •Глава 3
- •3.6. Программирование аппаратных средств
- •Глава 3
- •37Ah Порт управлсш!я
- •Глава 3
- •Глава 3
- •Глава 4. Расширенные возможности
- •4.1. Архитектурные особенности
- •Глава 4
- •4.2. Дополнительные режимы адресации
- •Глава 4
- •4.3. Использование средств 32-разрядных процессоров в программировании
- •Глава 4
- •Глава 4
- •Глава 4
- •4.4. Основы защищенного режима
- •Глава 4
- •Глава 4
- •Глава 4
- •Глава 4
- •Idiv Деление целых чисел со знаком
- •Imul Умножение целых чисел со знаком
- •In Ввод из порта
- •Inc Инкремент (увеличение на 1)
- •Int Программное прерывание
- •Into Прерывание по переполнению
- •Iret Возврат из прерывания
- •1 Lods Загрузка операнда из строки : lodsb Загрузка байта из строки lodsw Загрузка слова из строки
- •Операнд
- •Xadd память, регистр
- •Xchg Обмен данными между операндами
- •Xlat Табличная трансляция
- •Xor Логическое исключающее или
- •Содержание
Глава 3
пользуем старшую часть произведения и фактически ее может и не быть, сохранение и последующее восстановление регистра DX является обязательным.
Передача параметров в подпрограмму через регистры общего назначения или даже через сегментные регистры вполне возможна, однако на практике для передачи параметров чаще всего используют стек, хотя бы потому, что регистров немного, а в стек можно поместить любое число параметров. При этом применяется своеобразная методика работы со стеком не с помощью команд push и pop, а с помощью команд mov с косвенной адресацией через регистр ВР, который архитектурно предназначен именно для адресации к стеку. Преобразуем пример 3-86 так, чтобы единственный в этом примере параметр (условная величина задержки) передавался в подпрограмму не через регистр SI, а через стек. Вызов подпрограммы delay в этом случае должен выполняться следующим образом:
push 2000 ;Проталкиваем в стек значение параметра
call delay ;Вызываем подпрограмму delay
Текст подпрограммы подвергнется значительным изменениям: ;Пример 3-8в. Передача параметра через стек
delay |
ргос |
|
|
push |
CX |
|
push |
BP |
|
mov |
BP,SP |
|
mov |
CX,[BP+6] |
dell: |
push |
CX |
|
mov |
cx,o |
de!2: |
loop |
de!2 |
|
pop |
CX |
|
loop |
dell |
|
pop |
BP |
|
pop |
CX |
|
ret |
2 |
;Процедура-подпрограмма
;Сохраним СХ основной программы
;Сохраним ВР
;Настроим ВР на текущую вершину стека
;Скопируем из стека параметр
;Сохраним его ;,*•
;Счетчик внутреннего цикла }':';-
;Внутренний цикл (64К шагов) ;#
;Восстановим внешний счетчик i\-:
; Внешний цикл
восстановим ВР
;и СХ программы ||,_
;Возврат и снятие со стека \
;ненужного уже параметра gj>;
Команда call, передавая управление подпрограмме, сохраняет в стеке адрес возврата в основную программу. Подпрограмма сохраняет в стеке еще два 16-разрядных регистра. В результате стек оказывается в состоянии, изображенном на рис. 3.9.
После сохранения в стеке исходного содержимого регистра ВР (в основной программе нашего примера этот регистр не используется, однако в общем случае это может быть и не так), в регистр ВР копируется содержимое указателя стека, после чего в ВР оказывается смещение вершины стека. Далее командой mov в регистр СХ заносится содержимое ячейки стека, на 6 байтов ниже текущей вершины. В этом месте стека как раз находится передаваемый в подпрограмму параметр, как это показано в левом столбце рис. 3.9. Конкретную величину смещения относительно вершины стека надо для каждой подпрограммы определять индивидуально,
Команды и алгоритмы
139
ВР + 4
ВР + 6
Рис. 3.9. Состояние стека в подпрограмме после сохранения регистров.
исходя из того, сколько слов сохранено ею в стеке к этому моменту. Напомним, что при использовании косвенной адресации с регистром ВР в качестве базового, по умолчанию адресуется стек, что в данном случае и требуется.
Параметр, полученный таким образом, используется далее в подпрограмме точно так же, как и в примере 3-8а.
Выполнив возложенную на нее задачу, подпрограмма восстанавливает сохраненные ранее регистры и осуществляет возврат в основную программу с помощью команды ret, в качестве аргумента которой указывается число байтов, занимаемых в стеке отправленными туда перед вызовом подпрограммы параметрами. В нашем случае единственный параметр занимает 2 байт. Если здесь использовать обычную команду ret без аргумента, то после возврата в основную программу' параметр останется в стеке, и его надо будет оттуда извлекать (между прочим, не очень понятно, куда именно, ведь все регистры у нас могут быть заняты). Команда же с аргументом, осуществив возврат в вызывающую программу, увеличивает содержимое указателя стека на значение ее аргумента, тем самым осуществляя логическое снятие параметра. Физически этот параметр, как, впрочем, и все остальные данные, помещенные в стек, остается в стеке и будет затерт при дачьнейших обращениях к стеку.
Разумеется, в стек можно было поместить не один, а сколько угодно параметров. Тогда для их чтения надо было использовать несколько команд mov со значениями смещения ВР+6, ВР+8, BP+OAh и т.д.
Рассмотренная методика может быть использована и при дальних вызовах подпрограмм, но в этом случае необходимо учитывать, что дальняя команда call сохраняет в стеке не одно, а два слова, что повлияет на ^величину рассчитываемого смещения относительно вершины стека.