- •Глава 1 Введение в семейство персональных компьютеров ibm pc
- •Глава 2 Выполнение программ
- •Глава 3 Требования языка ассемблер
- •Глава 4 Ассемблирование и выполнение программ
- •Глава 5 Определение данных
- •Глава 8 Экранные операции I: Основные свойства
- •Глава 9 Экранные операции II: Расширенные возможности
- •Глава 10 Экранные операции III: Цвет и графика
- •Глава 11 Команды обработки строк
- •Глава 12 Арифметические операции I: Обработка двоичных данных
- •Глава 13 Арифметические операции II:
- •Глава 14 Обработка таблиц
- •Глава 15 Дисковая память I: Организация
- •Глава 16 Дисковая память II: Функции базовой версии dos
- •Глава 17 Дисковая память III: Расширенные функции dos
- •Глава 18 Дисковая память IV: Функции bios
- •Глава 19 Печать
- •Глава 20 Макросредства
- •0000 Csig segment para 'Code'
- •0100 Eb 00 begin: jmp short main
- •0102 Main proc near
- •0109 Main endp
- •0109 Cseg ends
- •20.1. Напишите необходимые директивы: а) для подавления всех команд,
- •04Af в регистр cs. Комбинация этих адресов указывает на первую выполняемую
- •0000 Stacksg segment para stack 'Stack'
- •0000 Codesg segment para 'Code'
- •13D40 плюс 0000. Обратите внимание, что основная программа начинается по
- •0000 Stacksg segment para stack 'Stack'
- •0000 Codesg segment para public 'code'
- •0000 Stacksg segment para stack 'Stack'
- •0000 Codesg segment para public 'code'
- •Ibm Personal Computer Linker
- •0000 Stacksg segment para stack 'Stack'
- •0000 Codesg segment para public 'Code'
- •1. Инициализирующая команда push ds заносит адрес сегмента в стек. Этот
- •010 Clear ,32768!
- •1. Наберите ассемблерную подпрограмму, сохраните ее под именем
- •Ibm Personal Computer Linker
- •Version 2.30 (c) Copyright ibm Corp. 1981, 1985
- •00000H 00011h 00012h codesg code
- •Ibm Personal Computer Basic
- •00 Указатель блока вызывающей программы
0000 Csig segment para 'Code'
ASSUME CS:CSEG,DS:CSEG
ASSUME SS:CSEG,ES:CSEG
0100 ORG 100H
0100 Eb 00 begin: jmp short main
; ...
0102 Main proc near
.LALL
MOVIF B
+ IFIDN ,
0102 F3/A4 + REP MOVSB
+ EXITM
MOVIF W
+ ENDIF
+ IFIDN ,
0104 F3/A5 + REP MOVSW
+ ENDIF
MOVIF
+ ENDIF
+ ELSE
+ ;Не указан парам. B или W, по умолч.принято B
+ ;--------------------------------------------
0106 F3/A4 + REP MOVSB
+ ENDIF
0108 C3 RET
0109 Main endp
0109 Cseg ends
END BEGIN
__________________________________________________________________________
Рис.20.7. Использование директивы IFIDN
ОСНОВНЫЕ ПОЛОЖЕНИЯ НА ПАМЯТЬ
________________________________________________________________
- Макросредства возможны только для полной версии ассемблера (MASM).
- Использование макрокоманд в программах на ассемблере дает в
результате более удобочитаемые программы и более производительный код.
- Макроопределение состоит из директивы MACRO, блока из одного или
нескольких операторов, которые генерируются при макрорасширениях и
директивы ENDM для завершения определения.
- Код, который генерируется в программе по макрокоманде, представляет
собой макрорасширение.
- Директивы .SALL, .LALL и .XALL позволяют управлять распечаткой
комментариев и генерируемого объектного кода в макрорасширении.
- Директива LOCAL позволяет использовать имена внутри
макроопределений. Директива LOCAL кодируется непосредственно после
директивы MACRO.
- Использование формальных параметров в макроопределении позволяет
кодировать параметры, обеспечивающие большую гибкость макросредств.
- Библиотека макроопределений дает возможность использовать
макрокоманды для различных ассемблерных программ.
- Условные директивы позволяют контролировать параметры макрокоманд.
ВОПРОСЫ ДЛЯ САМОПРОВЕРКИ
________________________________________________________________
20.1. Напишите необходимые директивы: а) для подавления всех команд,
которые генерирует макрокоманда и б) для распечатки только команд,
генерирующих объектный код.
20.2. Закодируйте два макроопределения для умножения: а) MULTBY
должна генерировать код для умножения байта на байт; б) MULTWD должна
генерировать код для умножения слова на слово. Для множителя и множимого
используйте в макроопределении формальные параметры. Проверьте выполнение
макрокоманд на небольшой программе, в которой также определены необходимые
области данных.
20.3. Запишите макроопределения из вопроса 20.2 в "макробиблиотеку".
Исправьте программу для включения элементов библиотеки по директиве
INCLUDE в первом проходе ассемблирования.
20.4. Напишите макроопределение BIPRINT, использующей BIOS INT 17H
для печати. Макроопределение должно включать проверку состояния принтера и
обеспечивать печать любых строк любой длины.
20.5. Измените макроопределение на рис.20.6 для проверки делителя на
ноль (для обхода деления).
ГЛАВА 21 Компоновка программ
__________________________________________________________________________
Ц е л ь: Раскрыть технологию программирования, включающую компоновку
и выполнение ассемблерных программ.
ВВЕДЕНИЕ
________________________________________________________________
Примеры программ в предыдущих главах состояли из одного шага
ассемблирования. Возможно, однако, выполнение программного модуля,
состоящего из нескольких ассемблированных программ. В этом случае
программу можно рассматривать, как состоящую из основной программы и одной
или более подпрограмм. Причины такой организации программ состоят в
следующем:
- бывает необходимо скомпоновать программы, написанные на разных
языках, например, для объединения мощности языка высокого уровня и
эффективности ассемблера;
- программа, написанная в виде одного модуля, может оказаться
слишком большой для ассемблирования;
- отдельные части программы могут быть написаны разными группами
программистов, ассемблирующих свои модули раздельно;
- ввиду возможно большого размера выполняемого модуля, может
появиться необходимость перекрытия частей программы в процессе
выполнения.
Каждая программа ассемблируется отдельно и генерирует собственный
уникальный объектный (OBJ) модуль. Программа компоновщик (LINK) затем
компонует объектные модули в один объединенный выполняемый (EXE) модуль.
Обычно выполнение начинается с основной программы, которая вызывает одну
или более подпрограмм. Подпрограммы, в свою очередь, могут вызывать другие
подпрограммы.
На рис.21.1 показаны два примера иерархической структуры основной
подпрограммы и трех подпрограмм. На рис.21.1.(а) основная программы
вызывает подпрограммы 1, 2 и 3. На рис.21.1.(б) основная программа
вызывает подпрограммы 1 и 2, а подпрограмма 1 вызывает подпрограмму 3.
Существует много разновидностей организации подпрограмм, но любая
организация должна быть "понятна" и ассемблеру, и компоновщику, и этапу
выполнения. Следует быть внимательным к ситуациям, когда, например, под
программа 1 вызывает подпрограмму 2, которая вызывает подпрограмму 3 и,
которая в свою очередь вызывает подпрограмму 1. Такой процесс, известный
как рекурсия, может использоваться на практике, но при неаккуратном
обращении может вызвать любопытные ошибки при выполнении.
__________________________________________________________________________
a) ЪДДДДДДДДДДД¬ б) ЪДДДДДДДДДДД¬
¦ Основная ¦ ¦ Основная ¦
¦ программа ¦ ¦ программа ¦
АДДДДДВДДДДДЩ АДДДДДВДДДДДЩ
ЪДДДДДДДДД†ДДДДДДДДД¬ ЪДДДДБДДДД¬
ЪДДДДДД¬ ЪДДДДДД¬ ЪДДДДДД¬ ЪДДДДДД¬ ЪДДДДДД¬
¦ П/П 1 ¦ ¦ П/П 2 ¦ ¦ П/П 3 ¦ ¦ П/П 1 ¦ ¦ П/П 2 ¦
АДДДДДДДЩ АДДДДДДДЩ АДДДДДДДЩ АДДДВДДДЩ АДДДДДДДЩ
ЪДДДДДД¬
¦ П/П 3 ¦
АДДДДДДДЩ
__________________________________________________________________________
Рис.21.1. Иерархия программ.
МЕЖСЕГМЕНТНЫЕ ВЫЗОВЫ
________________________________________________________________
Команды CALL в предыдущих главах использовались для внутрисегментных
вызовов, т.е. для вызовов внутри одного сегмента. Внутрисегментный CALL
может быть короткий (в пределах от +127 до -128 байт) или длинный (
превышающий указанные границы). В результате такой операции "старое"
значение в регистре IP запоминается в стеке, а "новый" адрес перехода
загружается в этот регистр.
Например, внутрисегментный CALL может иметь следующий объектный код:
E82000. Шест.E8 представляет собой код операции, которая заносит 2000 в
виде относительного адреса 0020 в регистр IP. Затем процессор объединяет
текущий адрес в регистре CS и относительный адрес в регистре IP для
получения адреса следующей выполняемой команды. При возврате из процедуры
команда RET восстанавливает из стека старое значение в регистре IP и
передает управление таким образом на следующую после CALL команду.
Вызов в другой кодовый сегмент представляет собой межсегментный
(длинный) вызов. Данная операция сначала записывает в стек содержимое
регистра CS и заносит в этот регистр адрес другого сегмента, затем
записывает в стек значение регистра IP и заносит новый относительный адрес
в этот регистр.
Таким образом в стеке запоминаются и адрес кодового сегмента и
смещение для последующего возврата из подпрограммы.
Например, межсегментный CALL может состоять из следующего объектного
кода:
9A 0002 AF04
Шест.9A представляет собой код команды межсегментного вызова которая
записывает значение 0002 в виде 0200 в регистр IP, а значение AF04 в виде