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

0000 Codesg segment para public 'code'

0000 SUBMUL PROC FAR

ASSUME CS:CODESG

PUBLIC SUBMUL

0000 F7 E3 MUL BX ;AX-стоимость, BX-количество

0002 CB RET ;Произведение в DX:AX

0003 SUBMUL ENDP

0003 CODESG ENDS

END SUBMUL

Segments and Groups:

N a m e Size Align Combine Class

CODESG. . . . . . . . . . . . . 0003 PARA PUBLIC 'CODE'

Symbols:

N a m e Type Value Attr

SUBMUL. . . . . . . . . . . . .F PROC 0000 CODESG Global Length=0003

LINK

IBM Personal Computer Linker

Version 2.30 (C) Copyright IBM Corp 1981, 1985

Object Modules: B:CALLMUL2+B:SUBMUL2

Run File: [B:CALLMUL2.EXE]:

List File: [NUL.MAP]: CON

Libraries [.LIB]:

Start Stop Length Name Class

00000H 00022H 0023H CODESG CODE <-- Примечание: 1 сегмент кода

00030H 00033H 0004H DATASG DATA

00040H 000BFH 0080H STACKSG STACK

Program entry point at 0000:0000

__________________________________________________________________________

Рис.21.4. Кодовый сегмент, определенный как PUBLIC.

Следующий пример на рис.21.4 представляет собой вариант программы на

рис.21.3. Имеется одно изменение в основной программе и одно - в

подпрограмме. В обоих случаях в директиве SEGMENT используется атрибут

PUBLIC:

CODESG SEGMENT PARA PUBLIC 'CODE'

Рассмотрим результирующую карту компоновки и объектный код команды

CALL.

Из таблицы идентификаторов (в конце каждого листинга ассемблирования)

следует: обобщенный тип кодового сегмента CODESG - PUBLIC (на рис.21.3

было NONE). Но более интересным является то, что карта компановки в конце

листинга показывает теперь только один кодовый сегмент! Тот факт, что оба

сегмента имеют одни и те же имя (CODESG), класс ('CODE') и атрибут PUBLIC,

заставил компоновщика объединить два логических кодовых сегмента в один

физический кодовый сегмент. Кроме того, при трассировке выполнения

программы можно обнаружить, что теперь команда вызова подпрограммы имеет

следующий объектный код:

9A 2000 D213

Эта команда заносит шест.2000 в регистр IP и шест.D213 в регистр CS. Так

как подпрограмма находится в общем с основной программой кодовом сегменте,

то в регистре CS устанавливается тот же стартовый адрес - шест.D213. Но

теперь смещение равно шест.0020:

Адрес в CS: 13D20

Смещение в IP: 0020

Действительный адрес: 13D40

Таким образом, кодовый сегмент подпрограммы начинается, очевидно, по

адресу шест.13D40. Правильно ли это? Карта компановки не дает ответа на

этот вопрос, но можно определить адрес по листингу основной программы,

которая заканчивается на смещении шест.0016. Так как кодовый сегмент для

подпрограммы определен как SEGMENT, то он должен начинаться на границе

параграфа, т.е. его адрес должен нацело делиться на шест.10 или правая

цифра адреса должна быть равна 0. Компоновщик размещает подпрограмму на

ближайшей границе параграфа непосредственно после основной программы -

этот относительный адрес равен шест.00020. Поэтому кодовый сегмент

подпрограммы начинается по адресу 13D20 плюс 0020 или 13D40.

__________________________________________

| Основная программа... | Подпрограмма |

| (не используемый участок) | |

|___________________________|______________|

| | |

13D20 13D30 13D40

Рассмотрим, каким образом компоновщик согласует данные, определенные в

основной программе и имеющие ссылки из подпрограммы.

ПРОГРАММА: ОБЩИЕ ДАННЫЕ В ПОДПРОГРАММЕ

________________________________________________________________

__________________________________________________________________________

page 60,132

TITLE CALLMUL3 (EXE) Вызов подпрограммы

; для умножения

EXTRN SUBMUL:FAR

PUBLIC QTY,PRICE

;-------------------------------------------------