Опубликован: 15.11.2010 | Доступ: свободный | Студентов: 643 / 18 | Оценка: 4.00 / 5.00 | Длительность: 17:30:00
Специальности: Программист
Лекция 1:

Классификация ввода-вывода

Лекция 1: 12345678 || Лекция 2 >

1.9. Приложение V. Описание шаблонов для программирования на языке Ассемблера в MS-DOS.

Человеку, занимающимся программированием на языке Ассемблера в операционной системе MS-DOS часто приходится использовать одни и те же конструкции для инициализации программы, использовать однотипные операции и функции. При этом код повторяется "один в один", и при его наборе можно сделать досадную ошибку. Чтобы это не делать, автор разработал несколько простых шаблонов для осуществления часто встречающихся однотипных операций, и предлагает к его использованию согласно лицензии GPL. Ниже приводится описание этих шаблонов.

1.9.1. Введение

Данные шаблоны предназначены для создания исходного кода на языке Ассемблер для операционной системе MS-DOS и совместимых с нею операционных системах, в том числе и для Microsoft Windows 95-7. В этих шаблонах есть повторяющиеся элементы, смысл которых будет объяснён ниже.

  1. Директива: page - указывает, сколько строк и позиций будет содержать листинг программы, генерируемый транслятором Ассемблера. Лучше оставить его значение, указанное в шаблоне: 60 строк и 132 позиции в строке, page 60,132;
  2. Директива: TITLE - указывает, как будет озаглавлен листинг программы, и какие колонтитулы будут печататься при выводе листинга. После этой директивы может идти любой текст, общий длиной до 60 символов. Автор рекомендует в качестве текста использовать имя и назначение программы;
  3. Директива: ASSUME - указывает, какой сегмент поставлен в соответствие определённому сегментному регистру. По-умолчанию сегменту кода соответствует регистр CS, сегментам данных - DS и ES, сегменту стека - SS. Эти сегменты должны быть определены оператором: SEGMENT перед вызовом этой директивы. Сам вызов этой директивы осуществляется в сегменте кода, обязательно перед вызовом других операторов программы. Если по каким-то причинам часть сегментных регистров не используется, вместо указания имени регистра используется слово: "NOTHING", например: ES:NOTHING ;
  4. Оператор: SEGMENT - определяет имя и параметры сегмента, используемого в программе на языке Ассемблер. В качестве параметров используются:
    • Имя сегмента - располагается перед именем оператора. Оно обозначает метку, под которой данный сегмент идентифицируется в программе на языке Ассемблер. Это имя фигурирует при объявлении сегмента директивой: ASSUME. Это имя используется также в операторах загрузки адреса сегмента;
    • Параметр выравнивания сегмента по границе сегмента PARA. Автор рекомендует этот параметр к обязательному использованию;
    • Параметр: STACK - используется только для сегментов стека. Указывает, что данный сегмент является сегментом стека;
    • Параметр, заключённый в апострофы - указывает компилятору, как будут компоноваться сегменты и их содержимое при выводе листинга ассемблерного файла. Иными словами, он определяет необязательный "класс сегмента". Рекомендуется для сегментов с кодом указывать класс: 'Code', для сегментов с данными - класс 'Data', для сегментов стека - класс 'Stack' ;

      Примечание. Несколько сегментов можно указывать только для программ с форматом файла: "EXE". Для файлов в формате "COM" возможен только один сегмент, и этот сегмент - кодовый.

  5. Оператор: PROC - используется для указания начала любой процедуры на языке Ассемблера. Перед названием этой процедуры стоит её метка, определяющая имя процедуры в программе. Физический конец процедуры указан при помощи оператора: "метка" ENDP, где "метка" имеет то же имя, что и у оператора: PROC. Перед оператором конца процедуры должен находиться оператор выхода из процедуры: RET.

    Примечание: После оператора PROC следуют два параметра, определяющие, как будет производиться адресация памяти внутри процедуры. Параметр "FAR" указывает, что будут использоваться только "длинные указатели" - пара адресов: "Сегмент:Смещение". Параметр "NEAR" указывает, что будут при адресации использоваться только "короткие указатели" - "Смещение" адреса внутри текущего сегмента. В программе формата: "COM" допускаются только "короткие" указатели адресов.

Во избежание путаницы не желательно переопределять имена сегментов и процедур, приведённые в шаблонах.

Более подробное описание этих директив и операторов языка ассемблер смотри в книге Питера Абеля.

1.9.2. Формат "EXE". Шаблон для создания файла в формате "EXE" Simple001

Исполняемый MS-DOS файл формата EXE обязательно должен содержать в себе следующие сегменты:

  • Сегмент кода (с кодом программы). Таких сегментов может быть несколько, если выполняемая программа содержит множество процедур;
  • Сегмент стека. Этот сегмент нужен как для инициализации программы, так и для работы операторов PUSH и POP. В программе на языке Ассемблер указывается максимальный размер стека (это значение Вы должны поставить при объявлении этого сегмента).
  • Сегменты данных. В-принципе, это не обязательный сегмент, тем не менее, часто используемый. В этом сегменте объявляются пользовательские переменные и константы языка Ассемблер, которые нужны для вычислений. Если в описании конструкций языка Ассемблер используется комментарий "в сегменте данных", то эти константы и переменные должны быть записаны в одном из сегментов данных.

При инициализации программы на языке Ассемблер для исполняемых файлов в формате "EXE" должны присутствовать следующие операторы:

  • PUSH DS - сохранение в стеке содержимого регистра DS. Первоначально в этом регистре находился адрес загрузчика программ в командной оболочке MS-DOS;
  • Далее в стек необходимо записать значение "0". Это значение используется для инициализации загрузчика MS-DOS после выполнения программы;
  • Затем в регистр DS заносится адрес сегмента с данными выполняемой программы;
  • Только после этого пишется код программы на языке Ассемблер.
  • Основная процедура программы (как и любая процедура на языке Ассемблер) заканчивается оператором "RET". Этот оператор приводит сегментные регистры в первоначальное состояние и возвращает управление вызывающей программе или загрузчику командной оболочки.

Таким образом, зарезервированными словами шаблона программы на языке Ассемблер являются следующие слова:

  • ASSUME
  • AX
  • BEGIN
  • 'Code'
  • CODESG
  • CS
  • 'Data'
  • DATASG
  • DS
  • END
  • ENDP
  • ENDS
  • ES
  • FAR
  • MOV
  • page
  • PARA
  • PROC
  • PUSH
  • RET
  • SEGMENT
  • SS
  • STACK
  • 'Stack'
  • STACKSG
  • SUB
  • TITLE

Пример шаблона смотри ниже

page  60,132
TITTLE  SIMPLE001 (EXE) Пример шаблона на языке Ассемблер
; ---------------------------------------------------------
STACKSG  SEGMENT  PARA STACK 'Stack'
; --- <ОБЪЯВЛЕНИЕ РАЗМЕРА СТЕКА>
STACKSG  ENDS
; ---------------------------------------------------------
DATASG  SEGMENT  PARA 'Data'
; --- <ОБЪЯВЛЕНИЕ ПЕРЕМЕННЫХ В СЕГМЕНТЕ ДАННЫХ>
DATASG  ENDS
; --------------------------------------------------------
CODESG  SEGMENT PARA 'Code'
BEGIN  PROC  FAR
  ASSUME  CS:CODESG, DS:DATASG, SS:STACKSG, ES:DATASG
; --- ИНИЦИАЛИЗАЦИЯ exe ФАЙЛА ---
  PUSH  DS    ; Записать DS в стек
  SUB  AX, AX    ; Установить ноль в AX
  PUSH  AX    ; Записать ноль в стек
  MOV  AX, DATASG  ; Занести адрес
  MOV  DS, AX    ;   DATASG в DS

; --- <КОД ПРОГРАММЫ>

  RET      ; Возврат в DOS
BEGIN  ENDP
CODESG  ENDS
  END  BEGIN
; --- Конец программы

1.9.3. Формат "COM". Шаблон для создания файла в формате "COM" Simple002

Исполняемый файл в формате "COM", написанный на языке Ассемблер, содержит только один сегмент - сегмент кода. Поэтому в директиве ASSUME все регистры инициализируются только одним значением: CODESG.

Для инициализации "COM" файла необходимо вначале вызвать оператор "ORG", с помощью которого производится пропуск части кода системного загрузчика программы. Затем идёт определение переменных и констант, используемых в программе. Поскольку в файлах формата "COM" нет сегмента данных, то объявление переменных происходит в начале программы, сразу за адресом загрузчика оболочки. Поскольку, по логике MS-DOS, в первом адресе исполняемой программы в сегменте кода должен быть исполняемый оператор, а не директива определения констант, то первым оператором "COM" программы будет оператор безусловного перехода на метку JMP. В качестве метки выступает имя основной процедуры исполняемого файла "MAIN". Между этими операторами будут располагаться описание констант и переменных программы, которое в файлах формата "EXE" располагались в сегменте данных.

Имена процедур в файле формата "COM" должны обязательно иметь параметр "NEAR", поскольку в файлах этого формата допустимы лишь "короткие" адреса памяти (то есть только смещение относительно сегмента кода текущей программы). Заканчиваться процедура должна оператором: "RET" (последний выполняемый оператор) и, затем, оператором: "метка программы" ENDP". Собственно же программа должна заканчиваться директивой: "END "метка оператора JMP".

Таким образом, зарезервированными словами шаблона программы на языке Ассемблер являются следующие слова:

  • ASSUME
  • BEGIN
  • 'Code'
  • CODESG
  • CS
  • DS
  • END
  • ENDP
  • ENDS
  • ES
  • JMP
  • MAIN
  • NEAR
  • ORG
  • page
  • PARA
  • PROC
  • RET
  • SEGMENT
  • SS
  • TITLE

Примечание. Рекомендуется писать небольшие программы для операционной системы MS-DOS именно в "COM" формате, где это возможно, поскольку двоичный код в формате "COM" в 3 - 10 раз более компактный, чем в формате "EXE". Соответственно выше и скорость загрузки, меньше время выполнения программы. Однако на размер программ в этом формате накладывается ограничение - не более 64 Кбайт.

Пример шаблона смотри ниже.

page  60,132
TITLE  SIMPLE002 (COM) Пример шаблона на языке Ассемблер
; ---------------------------------------------------------
CODESG  SEGMENT PARA 'Code'
  ASSUME  CS:CODESG, DS:CODESG, SS:CODESG, ES:CODESG
; --- ИНИЦИАЛИЗАЦИЯ COM ФАЙЛА ---
  ORG  100H
BEGIN:  JMP  MAIN
; ---------------------------------------------------------
; --- <ОБЪЯВЛЕНИЕ ПЕРЕМЕННЫХ В ОБЛАСТИ ДАННЫХ>
; --------------------------------------------------------
MAIN  PROC  NEAR

; --- <КОД ПРОГРАММЫ>

; --- Возврат в DOS и завершение программы

  RET      ; Возврат в DOS
MAIN  ENDP
CODESG  ENDS
  END  BEGIN
; --- Конец программы

1.9.4. "Учебный" шаблон файла на языке "Ассемблер"

page  60,132
TITLE  PRENT (COM) Пример шаблона на языке Ассемблер
; ---------------------------------------------------------
CODESG  SEGMENT PARA 'Code'
  ASSUME  CS:CODESG, DS:CODESG, SS:CODESG, ES:CODESG
; --- ИНИЦИАЛИЗАЦИЯ COM ФАЙЛА ---
  ORG  100H
BEGIN:  JMP  MAIN
; ---------------------------------------------------------
; --- В сегменте данных ---
PRESS_MSG  DB  0DH, 0AH, 'Press key Enter to Exit...', 0DH, 0Ah,'$' ; --- Приглашение
PRESS_ENTER  LABEL  BYTE  ; Ссылка на набор полей
MAX_ENTER_LEN  DB  02H  ; Максимальная длина поля -- 2 байта
CUR_ENTER_LEN  DB  ?
PRESS_BUFFER  DB  2 DUP (0)   ; Буфер для ввода данных
; --------------------------------------------------------
MAIN  PROC  NEAR

; --- <КОД ПРОГРАММЫ>
  CALL  PRENTER

; --- Возврат в DOS и завершение программы

  RET      ; Возврат в DOS
MAIN  ENDP

; --- ОБЪЯВЛЕНИЕ ПРОЦЕДУРЫ
PRENTER  PROC  NEAR

; --- Вывод сообщения
  MOV  AH, 09H
  LEA  DX, PRESS_MSG
  INT  21H

; --- Ввод клавиши 'Enter'
  MOV  AH, 0AH
  LEA  DX, PRESS_ENTER
  INT  21H

; --- ВЕРНУТЬСЯ В ВЫЗЫВАЮЩУЮ ПРОГРАММУ
  RET
PRENTER  ENDP

; --- КОНЕЦ ПРОЦЕДУРЫ

CODESG  ENDS
  END  BEGIN
; --- Конец программы
Листинг .
Лекция 1: 12345678 || Лекция 2 >
Дмитрий Карпов
Дмитрий Карпов
Россия, Нижний Новгород
Олег Корсак
Олег Корсак
Латвия, Рига