Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Глава14.DOC
Скачиваний:
14
Добавлен:
14.04.2019
Размер:
565.76 Кб
Скачать

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

Операционная система MS DOS предъявляет некоторые обязательные требования к структуре ASM-программы, предназначенной для последующего создания EXE-файла:

  • Программа может использовать 4 сегмента памяти, начальные адреса которых должны быть загружены в регистры микропроцессора CS, SS, DS и ES, а сами сегменты в явном виде определены в программе в виде операторных скобок: имя_сегмента segment ... имя_сегмента ends (версии MS DOS 4.0 и выше допускают более простое указание сегментов в программе: имя_сегмента).

  • В программе должно быть указание, какие сегментные регистры закрепляются за используемыми сегментами памяти; при исполнении программы сегментные регистры CS, SS, ES в соответствии с этими указаниями загружаются автоматически.

  • Сегмент данных DS в EXE-программе не может быть загружен автоматически, поскольку он используется программным загрузчиком для формирования начального адреса служебной области памяти — префикса программного сегмента (PSP), непосредственно предшествующего любой исполняемой программе EXE. Регистр сегмента данных DS должен быть инициирован принудительно — для этого следует в самом начале ASM-программы записать в стек вектор-адрес возврата к служебной области PSP: содержимое регистра DS и нулевое смещение, а затем в регистр DS загрузить адрес сегмента данных. PSP — это группа служебных слов в оперативной памяти, формируемая для каждой загружаемой программы пользователя и занимающая обычно 256 байтов (100h). При запуске программы пользователя в ОЗУ автоматически формируется PSP, и ее начальный адрес помещается в регистр DS.

  • Обеспечение после завершения выполнения программы возврата к префиксу программного сегмента; проще всего это можно сделать, оформив обращение к исполняемой программе в виде обращения к процедуре (главной процедуре, обязательно с атрибутом far) и поместив в конце программы команду возврата ret (выход из программы можно выполнить также, используя прерывание 20H DOS или функцию 4Ch прерывания 21H DOS, но управление при этом передается не в PSP, а непосредственно в резидентную часть программы COMMAND.COM).

Типовая структура ASM-программы включает в себя:

  1. Имя программы.

TITLE prog.ASM

Может присутствовать комментарий назначения программы.

  1. Инициализацию стековой памяти в сегменте стека:

STACKSEG segment stack

DW N dup(?) ; меньше 32 слов в стеке обычно задавать не следует

STACKSEG ends

  1. Инициализацию всех переменных в сегменте данных:

DATASEG segment

; задаются имена всех констант и переменных,

; их начальные значения и резервируется память под них

DATASEG ends

  1. Назначение сегментных регистров в сегменте кодов:

CODESEG segment

Assume CS:codeseg, DS:dataseg, SS:stackseg

  1. Организацию главной программной процедуры far:

MAIN proc far

  1. Запись адреса префикса программного сегмента (PSP) в стек:

push DS

sub AX, AX

push AX

  1. Инициализацию содержимого регистра сегмента данных:

mov AX, dataseg

mov DS, AX

; при указании в команде в качестве операнда символического

; имени сегмента (dataseg) происходит пересылка начального адреса

; этого сегмента — неверно указывать offset dataseg

  1. Текст программы пользователя в сегменте кодов:

основной текст программы

  1. Восстановление адреса PSP в DS:

ret

  1. Тексты процедур; если имеются процедуры near, используемые в данной программе, то записываются тексты этих процедур.

  2. Закрытие главной процедуры main, сегмента кодов и выход из программы:

MAIN endp

CODESEG ends

end MAIN

Итак, обобщенная структура программы:

title prog.asm

stackseg segment

; задание поля памяти для стека

stackseg ends

dataseg segment

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

dataseg ends

codeseg segment

assume CS:codeseg, DS:dataseg, SS:stackseg

main proc far

push DX

sub AX, AX

push AX

mov AX, dataseg

mov DS, AX

; основной текст программы

; ...

ret

; тексты ближних процедур

main endp

codeseg ends

end main

Рассмотрим программу расчета сложных процентов.

Капитал Q вкладывается в некоторое мероприятие, обеспечивающее ежегодный прирост капитала D%. Задача: определить текущую величину капитала в течение первых N лет. Вот соответствующая ASM-программа для создания исполняемого EXE-файла.

TITLE

RASCHET.ASM

; расчет сложных процентов

STACKSG

SEGMENT

STACK 'STACK'

DW

64 DUP(?)

STACKSG

ENDS

DATASG

SEGMENT

'DATA' ; задание переменных

VVQ

DB

' Введите величину начального капитала (до 64 000)'

DB

10,13,'$'

DB

10,13,'Введите процент годового прироста'

DB

10,13,'$'

VVN

DB

10,13,'Введите количество расчетных лет'

DB

10,13,'$'

Q0

DW

?

D

DW

?

D1

DW

?

N

DW

?

I

DW

1

Q

DW

?

BUF

DB

5, 0, 0, 0, 0, 0, 0, 0

VIV1

DB

' год капитал'

DB

10,13,'$'

SRB

DB

14 DUP(0), '$'

SR

DB

6 DUP(0), '$'

SRK

DB

10, 13, '$'

FT10

DW

1

TEN

DW

10

STO

DW

100

DATASG

ENDS

CODESG

SEGMENT

'CODE'

MAIN

PROC

FAR

ASSUME

CS:CODESG, DS:DATASG, SS:STACKSG

PUSH

DS

SUB

AX, AX

PUSH

AX

MOV

AX, DATASG

MOV

DS, AX

MOV

AH, 9 ; запрос на ввод Q

MOV

DX, offset VVQ

INT

21H

MOV

AH, 0Ah ; ввод Q

MOV

DX, offset BUF

INT

21H

CALL

STR2BIN

MOV

Q0, DI

MOV

AH, 9 ; запрос на ввод D

MOV

DX, offset VVD

INT

21H

MOV

AH, 0AH ; ввод D

MOV

DX, offset BUF

INT

21H

CALL

STR2BIN

MOV

D, DI

MOV

AH, 9 ; запрос на ввод N

MOV

DX, offset VVN

INT

21H

MOV

AH, 0AH ; ввод N

MOV

DX, offset BUF

INT

21H

CALL

STR2BIN

MOV

N, DI

MOV

AX, D

MOV

D1, AX

ADD

D1, 100 ; расчет D1 = (1 + D/100) * 100

MOV

AX, Q0 ; присвоение Q = Q0

MOV

Q, AX

MOV

AH, 9

MOV

DX, offset VIV1

INT

21H

RST:

MOV

AX, Q ; расчет Q = Q * D1

MUL

D1

DIV

STO

MOV

Q, AX

MOV

AX, I

CALL

BIN2STR

MOV

AH, 9 ; вывод года

MOV

DX, offset SR

INT

21H

MOV

AH, 9 ; вывод пробела

MOV

DX, offset SRB

INT

21H

MOV

AX, Q ; вывод прибыли

CALL

BIN2STR

MOV

AH, 9

MOV

DX, offset SR

INT

21H

MOV

AH, 9 ; перевод строки

MOV

DX, offset SRK

INT

21H

INC

I ; I = I + 1

MOV

AX, I ; сравнение I с N

CMP

AX, N

JLE

RST ; условный переход по I <= N

RET

BIN2STR

PROC

NEAR

MOV

SI, offset SR+5 ; процедура перевода двоичного

PR2:

SUB

DX, DX ; кода в код ASCII с предварительным

MOV

[SI], DL ; обнулением поля SR

DEC

SI

CMP

SI, offset SR

JA

PR2

MOV

CX, 10

MOV

SI, offset SR+5

PR1:

XOR

DX, DX

DIV

CX

OR

DL, 30H

MOV

[SI], DL

DEC

SI

CMP

AX,0

JNE

PR1

RET

BIN2STR

ENDP

STR2BIN

PROC

NEAR ; процедура перевода ASCII-кодов

MOV

FT10, 1 ; в двоичный код

XOR

DI, DI

MOV

CX, 10

LEA

SI, BUF + 1

XOR

BH, BH

MOV

BL, [BUF + 1]

PR3:

MOV

AL, [SI+BX]

AND

AX, 0FH

MUL

FT10

ADD

DI, AX

MOV

AX, FT10

MUL

TEN

MOV

FT10, AX

DEC

BX

JNZ

PR3

RET

STR2BIN

ENDP

MAIN

ENDP

CODESG

ENDS

END

MAIN

В качестве иллюстративного примера для сравнения сложности программ на языке ассемблера с программами на языке высокого уровня, ниже приводится без пояснений программа решения этой задачи на языке Basic:

10 print “Расчет сложных процентов“

20 input “Введите Q, D, N“, Q, D, N

30 D1 = 1 + D/100

40 I = 1

50 Q = Q * D1

60 print I, Q

70 I = I + 1

80 if I <= N then goto 50

90 end

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