
- •Глава 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 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
;-------------------------------------------------