Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
АССЕМБЛЕР И ПРОГРАММИРОВАНИЕ ДЛЯ IBM PC.doc
Скачиваний:
48
Добавлен:
25.05.2014
Размер:
3.21 Mб
Скачать

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 в виде