Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Абель.docx
Скачиваний:
13
Добавлен:
26.11.2018
Размер:
569.84 Кб
Скачать

1. Assume - это ассемблерная директива, которая устанавливает

для ассемблера соответствие между конкретными сегментами и

сегментными регистрами; в данном случае, CODESG - CS, DATASG - DS и

STACKSG - SS. DATASG и STACKSG не определены в этом примере, но они

будут представлены следующим образом:

STACKSG SEGMENT PARA STACK Stack 'Stack'

DATASG SEGMENT PARA 'Data'

Ассоциируя сегменты с сегментными регистрами, ассемблер сможет

определить смещения к отдельным областям в каждом сегменте. Например,

каждая команда в сегменте кодов имеет определенную длину: первая

команда имеет смещение 0, и если это двухбайтовая команда, то вторая

команда будет иметь смещение 2 и т.д.

2. Загрузочному модулю в памяти непосредственно предшествует

256-байтовая (шест.100) область, называемая префиксом программного

сегмента PSP. Программа загрузчика использует регистр DS для

установки адреса начальной точки PSP. Пользовательская программа

должна сохранить этот адрес, поместив его в стек. Позже, команда RET

использует этот адрес для возврата в DOS.

3. В системе требуется, чтобы следующее значение в стеке

являлось нулевым адресом (точнее, смещением). Для этого команда SUB

очищает регистр AX, вычитая его из этого же регистра AX, а команда

PUSH заносит это значение в стек.

4. Загрузчик DOS устанавливает правильные адреса стека в

регистре SS и сегмента кодов в регистре CS. Поскольку программа

загрузчика использует регистр DS для других целей, необходимо

инициализировать регистр DS двумя командами MOV, как показано на

рис.3.1. В следующем разделе этой главы "Исходная программа. Пример

II" детально поясняется инициализация регистра DS.

5. Команда RET обеспечивает выход из пользовательской программы

и возврат в DOS, используя для этого адрес, записанный в стек в

начале программы командой PUSH DS. Другим обычно используемым выходом

является команда INT 20H.

__________________________________________________________________________

CODESG SEGMENT PARA 'CODE'

BEGIN PROC FAR

1. ASSUME CS:CODESG,DS:DATASG,SS:STACKG

2. PUSH DS ;Записать DS в стек

3. SUB AX,AX ;Установить ноль в AX

PUSH AX ;Записать ноль в стек

4. MOV AX,DATASG ;Занести адрес

MOV DS,AX ; DATASG в DS

.

.

.

5. RET ;Возврат в DOS

BEGIN ENDP

CODESG ENDS

END BEGIN

__________________________________________________________________________

Рис.3.1. Инициализация EXE-программы.

Теперь, даже если приведенная инициализация программы до конца не

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

шаги инициализации, так что их можно дублировать всякий раз при

кодировании программ.

ПРИМЕР ИСХОДНОЙ ПРОГРАММЫ

________________________________________________________________

Рис.3.2 обобщает предыдущие сведения в простой исходной программе на

ассемблере. Программа содержит сегмент стека - STACKSG и сегмент кода -

CODESG.

__________________________________________________________________________

page 60,132

TITLE EXASM1 (EXE) Пример регистровых операций

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

STACKSG SEGMENT PARA SACK 'Stack'

DB 12 DUP('STACKSEG')

STACKSG ENDS

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

CODESG SEGMENT PARA 'Code'

BEGIN PROC FAR

ASSUME SS:STACKSG,CS:CODESG,DS:NOTHING

PUSH DS ;Записать DS в стек

SUB AX,AX ;Записать ноль

PUSH AX ; в стек

MOV AX,0123H ;Записать шест.0123 в AX

ADD AX,0025H ;Прибавить шест.25 к AX

MOV BX,AX ;Переслать AX в BX

ADD BX,AX ;Прибавить BX к AX

MOV CX,BX ;Переслать BX в CX

SUB CX,AX ;Вычесть AX из CX

SUB AX,AX ;Очистить AX

NOP

RET ;Возврат в DOS

BEGIN ENDP ;Конец процедуры

CODESG ENDS ;Конец сегмента

END BEGIN ;Конец программы

__________________________________________________________________________

Рис.3.2. Пример исходной программы на ассемблере.

STACKSG содержит один элемент DB (определить байт), который

определяет 12 копий слова 'STACKSEG'. В последующих программах стек не

опpеделяется таким способом, но при использовании отладчика для просмотра

ассемблированной программы на экране, данное определение помогает

локализовать стек.

CODESG содержит выполняемые команды программы, хотя первая директива

ASSUME не генерирует кода. Директива ASSUME назначает регистр SS для

STACKSG и регистр CS для CODESG. В действительности, эта директива

сообщает ассемблеру, что для адресации в STACKSG необходимо использовать

адрес в регистре SS и для адресации в CODESG - адрес в регистре CS.

Системный загрузчик при загрузке программы с диска в память для выполнения

устанавливает действительные адреса в регистрах SS и CS. Программа не

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

соответственно, в ASSUME нет необходимости ассигновать pегистр DS.

Команды, следующие за ASSUME - PUSH, SUB и PUSH выполняют стандартные

действия для инициализации стека текущим адресом в регистре DS и нулевым

адресом. Поскольку, обычно, программа выполняется из DOS, то эти команды

обеспечивают возврат в DOS после завершения программы. (Можно также

выполнить программу из отладчика, хотя это особый случай).

Последующие команды выполняют те же действия, что показаны на pис.2.1

в предыдущей главе, когда рассматривался отладчик.

ОСНОВНЫЕ ПОЛОЖЕНИЯ НА ПАМЯТЬ

________________________________________________________________

- Не забывайте ставить символ "точка с запятой" перед комментариями.

- Завершайте каждый сегмент директивой ENDS, каждую процедуру -

директивой ENDP, а программу - директивой END.

- В директиве ASSUME устанавливайте соответствия между сегментными

регистрами и именами сегментов.

- Для EXE-программ (но не для COM-программ, см. гл.6) обеспечивайте

не менее 32 слов для стека, соблюдайте соглашения по инициализации стека

командами PUSH, SUB и PUSH и заносите в регистр DS адрес сегмента данных.

ВОПРОСЫ ДЛЯ САМОПРОВЕРКИ

________________________________________________________________

3.1. Какие команды заставляют ассемблер печатать заголовок в начале

каждой страницы листинга и делать прогон листа?

3.2. Какие из следующих имен неправильны: а) PC_AT, б) $50, в) @$_Z,

г) 34B7, д) AX?

3.3. Какое назначение каждого из трех сегментов, описанных в этой

главе?

3.4. Что конкретно подразумевает директива END, если она завершает а)

программу, б) процедуру, в) сегмент?

3.5. Укажите различия между директивой и командой.

3.6. Укажите различия в назначении RET и END.

3.7. Для сегментов кода, данных и стека даны имена CDSEG, DATSEG и

STKSEG соответственно. Сформируйте директиву ASSUME.

3.8. Напишите три команды для инициализации стека адресом в DS и

нулевым адресом.