Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Lekz._4.doc
Скачиваний:
2
Добавлен:
11.08.2019
Размер:
177.66 Кб
Скачать

Використання стандартних директив визначення сегментів

На рис. 4.3 наведено лістинг, створений асемблером під ім'ям A04ASM1.LST. Ширина рядка, зазначена директивою PAGE, дорівнює 132 символам.

На початку лістингу можна бачити, як асемблер відреагував на директиви PAGE та TITLE. Жодна директива, включаючи SEGMENT, PROC, ASSUME або END, не генерує безпосередньо будь-якого машинний коду, оскільки просто містить необхідну асемблеру інформацію. Рядки лістингу містять наступні компоненти:

• на початку рядка ліворуч розташований номер цього рядка в лістингу;

• після номера вказані шістнадцяткові величини зміщень елементів даних та інструкцій;

• після зміщення вказаний згенерований машинний код в шістнадцятковому форматі;

• завершує рядок початковий символьний код.

Сама програма поділена по вертикалі на три сегменти, кожен зі своїми власними величинами зсувів для даних або інструкцій. Кожен сегмент містить директиву SEGMENT, що вказує асемблеру вирівнювати сегмент за адресою, котра без остачі ділиться на 10Н - само по собі речення SEGMENT не генерує машинного коду. Завантажувач програми зберігає вміст кожного сегмента в пам'яті і ініціалізує цими адресами сегментні регістри: STACK в SS, DATASEG в DS і CODESEG в CS. Початок сегмента відповідає нульовому зміщенню від цієї адреси.

Сегмент стеку. Сегмент стеку містить директиву DW, що визначає 32 слова, кожне з яких містить значення 0. Це визначення створює стек з розміром, достатнім для більшості реальних ситуацій. Велика програма може містити виклики багатьох переривань для вводу/виводу і виклики безлічі підпрограм, і всі ці операції вимагають використання стека. Сегмент стеку завершується зміщенням 0040Н, еквівалентним десятковому 64 (32 слова по 2 байти кожне). Асемблер показує згенеровану константу зліва як 0020 [0000], тобто 20Н (32) слова.

Сегмент даних. Сегмент даних програми, DATASEG, містить три певних значення, всі у форматі DW (слово).

1. FLDD визначає слово (два байти) і ініціалізує його десятковим значенням 215, яке асемблер перетворить у 00D7H (показано зліва).

2. FLDE визначає слово, ініціалізоване десятковим значенням 125 і перетворене асемблером в 007DH. Дійсні збережені в пам’яті значення цих двох констант дорівнюють, відповідно, D700 і 7D00, в чому ви можете переконатися, скориставшись DEBUG.

3. FLDF визначається за допомогою DW з операндом ?, тобто не ініціалізованим певним значенням. Лістинг показує його вміст у вигляді 0000.

Адреси зміщень FLDD, FLDE і FLDF - відповідно, 0000, 0002 і 0004, що відповідає їхнім розмірам.

Сегмент коду. Сегмент коду програми, CODESEG, містить виконуваний код програми, весь у одній процедурі (PROC). Три речення дозволяють адресувати сегмент даних:

ASSUME SS:STACK, DS:DATASEG, CS:CODESEG

0000 B8 ---- R MOV AX, DATASEG

0003 8E D8 MOV DS, AX

• Директива ASSUME пов'язує кожен сегмент з відповідним йому сегментним регістром. ASSUME просто надає інформацію асемблеру і не викликає генерування якого-небудь машинного коду.

A04ASM1 (EXE) Переміщення і додавання Page 1-1

1 Page 60, 132

2 TITLE A01ASM1 (EXE) Операції переміщення і додавання

3 ; ----------------------------------------------------------------------------------------------

4 0000 STACK SEGMENT PARA STACK 'Stack'

5 0000 0020 [ DW 32 DUP(0)

6 0000

7 ]

8

9 0040 STACK ENDS

10 ; ----------------------------------------------------------------------------------------------

11 0000 DATASEG SEGMENT PARA ‘Data’ 1

12 0000 00D7 FLDD DW 215 1

13 0002 007D FLDE DW 125 \

14 0004 0000 FLDF DW ?

15 0006 DATASEG ENDS

16 ; ----------------------------------------------------------------------------------------------

17 0000 CODESEG SEGMENT PARA 'Code'

18 0000 MAIN PROC FAR

19 ASSUME SS:STACK, DS:DATASEG, CS:CODESEG

20 0000 B8 ---- R MOV AX, DATASEG ;Помістити адресу

21 0003 8ED6 MOV DS,AX ;сегменту даних в DS

22

23 0005 A1 0000 R MOV AX,FLDD ;Помістити 0215 в АХ

24 0008 03 06 0002 R ADD AX,FLDE ;Додати 0125 в АХ

25 000C A3 0004 R MOV FLDF,AX ;Зберегти суму в FLDF

26 000F B8 4C00 MOV AX,4C00H ;Завершити роботу 1

27 0012 CD 21 INT 21H

28 0014 MAIN ENDP ;Кінець процедури ;Конец процедуры

29 0014 CODESEG ENDS ;Кінець сегменту ;Конец сегмента

30 END MAIN ;Кінець програми

---------------------------------------------------------------------------------------------------------------------------------------

Segments and Groups:

Name Length Align Combine Class

CODESEG …………………………… 0014 PARA NONE 'CODE'

DATASEG …………………………… 0006 PARA NONE 'DATA'

STACK …………………………… 0040 PARA STACK 'STACK'

Symbols:

Name Type Value Attr

MAIN …………………………….. F PROC 0000 CODESEG Length = 0014

FLDD …………………………….. L WORD 0000 DATASEG

FLDE …………………………….. L WORD 0002 DATASEG

FLDF …………………………….. L WORD 0004 DATASEG

0 Warning Errors

0 Severe Errors

Рис. 4.3 – Відтрансльована програма зі звичайною структурою сегментів

• Перша інструкція MOV "зберігає" DATASEG в регістрі АХ. Зауважимо, що інструкція не може дійсно зберегти сегмент у регістрі - асемблер розуміє, що це посилання на сегмент і тільки при виконанні запише в регістр його адресу. Подивіться на машинний код ліворуч: В8 ---- R.Чотири дефіса означають, що на даному етапі асемблер не може визначити адресу DATASEG; система визначає цю адресу тільки тоді, коли програма вже скомпонована і завантажена для виконання. Оскільки завантажувач може помістити програму де завгодно в пам'яті, асемблер залишає адресу відкритою і вказує на це символом R - relocatable, тобто переміщуваний. Завантажувач повинен замінити незакінчену адресу дійсною.

• Друга інструкція MOV заносить вміст регістра АХ в DS. Оскільки немає інструкції, що коректно переміщує дані безпосередньо з пам'яті в регістр DS, для його ініціалізації потрібні дві інструкції.

Зауважте, що програма не використовує регістр ES, хоча багато програмістів ініціалізують його у звичайному порядку. Хоча завантажувач автоматично ініціалізує регістри SS і CS, коли завантажує програму на виконання, ви повинні проініціалізувати регістр DS, і, якщо необхідно, ES.

Перша інструкція після ініціалізації регістра DS - MOV AX, FLDD, що починається з клітинки зі зміщенням 0005 і генерує машинний код А1 0000. Проміжок в лістингу між А1 (операцією) та 0000 (операндом) призначений тільки для зручності сприйняття. Наступна інструкція, ADD AX,FLDE, починається зі зміщення 0008 і генерує чотири байти машинного коду. Інструкція MOV FLDF,AX копіює суму з регістра АХ в змінну FLDF із зміщенням 0004 в сегменті даних. У цьому прикладі машинні інструкціі мають довжину два, три або чотири байти.

Останнє речення в програмі, END, містить операнд MAIN, зв’язаний з ім'ям PROC зі зміщенням 0000. Це - комірка в сегменті коду, на яку передає управління завантажувач програми для початку її виконання.

За лістингом програми слідують таблиця сегментів і груп, а також таблиця символів.

Таблиця сегментів і груп

Ця таблиця показує будь-які певні сегменти та групи. Зауважимо, що сегменти показані не в тій послідовності, в якій вони зазначені в програмі; асемблер, використаний в цьому прикладі, перераховує їх поіменно в алфавітному порядку. (Ця програма не містить груп, які розглядаються далі.) У таблиці наводяться довжина одного сегмента в байтах, вирівнювання (усі - по межах параграфів), тип поєднання і клас.

Таблиця символів

Ця таблиця містить імена полів даних у сегменті даних (FLDD, FLDE і FLDF) і мітки, які відносяться до інструкцій в сегменті коду. Для MAIN (єдиного запису в сегменті) величина F PROC у стовпці Туре означає процедуру типу Far (far - віддалений - у свою чергу, означає, що MAIN, як початкова точка для виконання, має бути відома за межами програми). Стовпець Value вказує зміщення від початку сегменту для імен, міток і процедур. Стовпець, що має назву "Attr" (attribute - атрибут), вказує сегмент, у якому визначено кожен елемент.

MASM 6.хх також приводить списки процедур, параметрів і таблицю груп.

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]