Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
МЕТОД_МП.DOC
Скачиваний:
2
Добавлен:
01.07.2025
Размер:
2 Мб
Скачать
☆

3.4. Выполнение программы

После ассемблирования и компоновки программы можно ее выполнить. На рис. 3.2 приведена схема команд и шагов для ассемблирования, компоновки и выполнения программы EXASM1. Если ЕХЕ-файл находится на диске C, то выполнить ее можно командой:

C:\EXASM1.EXE или C:\EXASM1

DOS предполагает, что файл имеет тип ЕХЕ (или СОМ), и загружает файл для выполнения. Но так как наша программа не вырабатывает видимых результатов, выполним ее трассировкой под отладчиком DEBUG или TURBO DEBUG.

Рис. 3.2. Схема ассемблирования, компоновки и выполнения программы

3.5. Пример исходной программы

Особенность программы, приведенной на рис. 3.1, состоит в том, что она не содержит определения данных. Обычно все программы имеют определенные константы, рабочие поля для арифметических вычислений и области для операций ввода-вывода.

На рис. 3.3 приводится программа, написанная на языке Ассемблер и для краткости уже ассемблированная. Эта программа знакомит с несколькими новыми особенностями.

1 page 60,132

2 TITLE EXASM2 ( EXE ) Операции пересылки и сложения.

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

4 0000 STACKSG SEGMENT PARA STACK ‘Stack’

5 0000 20 [ DW 32 DUP ( ? )

6 ? ? ? ?

7 ]

8

9 0040 STACKSG ENDS

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

11 0000 DATASG SEGMENT PARA ‘Data’

12 0000 00FA FLDA DW 250

13 0002 007D FLDB DW 215

14 0004 ???? FLDC DW ?

15 0006 DATASG ENDS

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

17 0000 CODESG SEGMENT PARA ‘Code’

18 0000 BEGIN PROC FAR

19 ASSUME CS:CODESG, DS:DATASG, SS:STACKSG, ES:NOTHING

20 0000 1E PUSH DS ; 3аписать DS в стек.

21 0001 2B C0 SUB AX,AX ; 3аписать в стек.

22 0003 50 PUSH AX ; Нулевой адрес.

Рис. 3.3. Листинг ассемблирования программы с сегментом данных

23 0004 B8 ---- R MOV АХ,DATASG ; Поместить адрес.

24 0007 8E D8 MOV DS,AX ; DATASG в регистр DS.

25

26 0009 A1 0000 R MOV AX,FLDA ; Переслать 0250 в AX.

27 000C 03 06 0002 R ADD AX,FLDB ; Прибавить 0125 к AX.

28 0010 A3 0004 R MOV FLDC,AX ; Записать сумму в FLDC.

29 0013 CB RET ; Вернуться в DOS.

30 0014 BEGIN ENDP

31 0014 CODESG ENDS

32 END BEGIN

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

Segments and Groups:

Name Size Align Combine Class

CODESG....................................0014 PARA NONE ‘CODE’

DATASG....................................0006 PARA NONE ‘DATA’

STACKSG..................................0040 PARA STACK ‘STACK’

Symbols:

Name Type Value Attr

BEGIN........................................F PROC 0000 CODESG Length=0014

FLDA..........................................L WORD 0000 DATASG

FLDB..........................................L WORD 0002 DATASG

FLDC..........................................L WORD 0004 DATASG

Рис. 3.3. Окончание

Сегмент стека содержит директиву DW (Define Word), описывающую 32 слова, в которых генерируется неопределенное значение, обозначенное знаком вопроса (?). Определение размера стека в 32 слова является наиболее реальным, так как в больших программах может потребоваться много «прерываний» для ввода-вывода и вызова подпрограмм – все они используют стек. Определение стека дублированием константы ‘STACKSEG’ в примере на рис. 1.2 необходимо лишь для удобства при работе с отладчиком DEBUG.

3амечание. Определяйте размер стека не менее, чем в 32 слова. При малых размерах стека ни ассемблер, ни компоновщик не смогут определить этого, и выполнение программы может разрушиться самым непредсказуемым образом.

На рис. 3.3 определен сегмент данных DATASG, начинающийся по относительному адресу 0000. Этот сегмент содержит три значения в формате DW. Поле FLDA определяет слово (два байта), содержащее десятичное значение 250, которое ассемблер транслирует в шестнадцатеричное 00FA (см. на рис. 3.3 слева).

Поле FLDB определяет слово с десятичным значением 125, которое транслируется в шестнадцатеричное 007D. Действительные значения этих двух констант в памяти FA00 и 7D00 соответственно, что можно проверить с помощью отладчика DEBUG.

Поле FLDC определяет слово с неизвестным значением, обозначенным знаком вопроса (?).

Сегмент кода в данном примере имеет имя CODESG и отличается новыми особенностями, связанными с сегментом данных. Во-первых, директива ASSUME указывает на определение DATASG через регистр DS. Данной программе не требуется регистр ES, но некоторые программисты описывают его для стандартизации. Во-вторых, после команд PUSH, SUB и PUSH, которые инициализируют стек, следуют две команды, обеспечивающие адресацию сегмента данных:

0004 В8 ---- R MOV AX,DATASG

0007 8Е D8 MOV DS,AX

Первая команда MOV загружает сегмент DATASG в регистр AX. На самом деле, поместить в регистр AX весь сегмент 64 Кб нельзя, поэтому команда загружает лишь начальный адрес сегмента DATASG.

Обратите внимание на машинный код слева:

В8 ---- R

Четыре дефиса говорят о том, что ассемблер не может определить адрес DATASG, он определяется лишь тогда, когда объектная программа будет скомпонована и загружена для выполнения. Поскольку загрузчик может расположить программу в любом месте памяти, ассемблер оставляет данный адрес открытым и показывает это символом R. Компоновщик должен будет подставить в это место действительный адрес.

Вторая команда MOV пересылает содержимое регистра АХ в регистр DS. Таким образом, данная программа имеет директиву ASSUME, которая соотносит регистр DS с сегментом данных, и команды, инициализирующие регистр DS относительным адресом DATASG.

Могут возникнуть два вопроса по поводу этой программы. Во-первых, почему не использовать одну команду для инициализации регистра DS, например:

MOV DS,DATASG ?

Дело в том, что не существует команд для непосредственной пересылки данных из памяти в регистр DS. Следовательно, для инициализации DS необходимо кодировать две команды. Во-вторых, почему программа инициализирует регистр DS, а регистры SS и CS нет? Оказывается, регистры SS и CS инициализируются автоматически при загрузке программы для выполнения, а ответственность за инициализацию регистра DS и, если требуется, ES лежит полностью на самой программе.

Пока все эти требования могут показаться весьма туманными, но сейчас не нужно понимать их. Все последующие программы используют аналогичную стандартную инициализацию стека и сегмента данных. Поэтому можно просто копировать данные коды для каждой новой программы. Действительно, вы можете сохранить на диске стандартную часть программы, а для каждой новой программы копировать эту часть с новым именем и, используя редактор, записать дополнительные команды.

В качестве упражнения создайте с помощью вашего редактора программу, приведенную на рис. 3.3, выполните ее ассемблирование и компоновку. Затем с помощью отладчика TURBO DEBUGGER просмотрите сегмент кодов, сегмент данных, регистры и проделайте пошаговое выполнение программы.