На главную
Подписка
Новости










Главная / MS-DOS / MS-DOS. РУКОВОДСТВО РАЗРАБОТЧИКА / Глава 12 / Использование шаблонов для создания .COM- и .EXE - программ Сделать домашней страницей Добавить в избранное Написать писмо

НАЗАД СОДЕРЖАНИЕ ВПЕРЁД

Использование шаблонов для создания .COM- и .EXE - программ

Листинги A-5, A-6 и A-7 могут оказаться полезными в начальной стадии разработки Вами программ.


Листинг A-5 показывает формат для .EXE-программ с промежутками для записи Вашего текста программы.


Листинг A-6 показывает формат для .COM- файлов.


Листинг A-7 содержит некоторые макрокоманды, которые могут оказаться полезными при написании или .EXE-, или .COM - программ. Некоторые макрокоманды могут быть или встроены в исходный файл Вашей программы, или могут постоянно размещаться в отдельном файле, который "включается" в Ваш исходный файл в процессе трансляции с языка ассемблера (путем встраивания управляющей команды INCLUDE макроассемблера MASM в исходный файл).


      Листинг A-5. Шаблон .EXE-программы
----------------------------------------------------------------
   PAGE    60,132    ; широкая печать
 ;- - - - - - - - - - - - - - - - - - - - - - - - - - - -
   FALSE   EQU     0 ; сравнить с логическим значением
   ; FALSE ("ложь")
   TRUE    EQU     0FFFFH     ; сравнить и проверить по маске
   ; логическоe значениe TRUE
   ; ("истина")
   ;
   ;    <Установление равенств и макрокоманд>
   ;
   ;- - - - Инициализация - - - - - - - - - - - -
   _TEXT   SEGMENT WORD PUBLIC 'CODE' ;сегмент текста программы
   _TEXT   ENDS
   _DATA   SEGMENT WORD PUBLIC 'DATA' ; сегмент данных
   _DATA   ENDS
   _STACK  SEGMENT PARA STACK 'STACK'  ; сегмент стека
   _STACK  ENDS
   ;
   DGROUP  GROUP   _DATA, STACK
   ;
  ASSUME cs:_TEXT,ds:DGROUP,ss:DGROUP,es:DGROUP
   ;
   _TEXT   SEGMENT     ; начало сегмента текста программы
   ; Локальная память данных (хранит  эти  описания  в
   ; сегменте текста программы)
   DSdsave   dw   seg DGROUP  ; память для DS-регистра
   ;
   _TEXT   ENDS
   _DATA   SEGMENT
   PSPseg  dw   ?     ; сегмент PSP
   _DATA   ENDS

_TEXT   SEGMENT
;
main    PROC     NEAR ; начинайте процесс "main"
        mov      ds,DSsave  ; инициализируйте память данных DS
        mov      ax,es      ; получите адрес сегмента
        mov      word ptr PSPseg,ax  ; PSP и сохраните его
;
;
;       < Основная стандартная программа >
;
;
        mov      ax,4C00h  ; завершите  программу
        int      21h
;
main    ENDP
;
;- - - - - - - - - - - - - - - - - - - - - - - - - - -
;
;   <Оставшаяся часть ваших стандартных программ>
;
;- - - - - - - - - - - - - - - - - - - - - - - - - - - -
_TEXT   ENDS
_DATA   SEGMENT
;
;       < Bставьте данные >
;
_DATA   ENDS
_TEXT   SEGMENT
;------------------------------------------------------
_TEXT   ENDS
        END      main
----------------------------------------------------------------

      Листинг A-6. Шаблон .COM-программы
----------------------------------------------------------------
PAGE    60,132    ; широкая  печать
;- - - - - - - - - - - - - - - - - - - - - - - - - - - -
FALSE   EQU     0 ; сравнить с логическим значением
; FALSE ("ложь")
TRUE    EQU     0FFFFH     ; сравнить и проверить по маске
; логическоe значениe TRUE
; ("истина")
;
;    <Установление равенств и макрокоманд>
;
;- - - - Инициализация - - - - - - - - - - - -
code   SEGMENT
ASSUME  cs:code, ds:code, ss:code, es:code
;
main   PROC  NEAR
;
entry: ORG   0100h
;
       mov   sp,offset top_of_stack   ; установите новый стек
;
;
;       < Основная стандартная программа >
;
       mov      ax,4C00h      ; завершите программу
       int      21h
;
main   ENDP
;
;- - - - - - - - - - - - - - - - - - - - - - - - - - -
;
;   <Оставшаяся часть ваших стандартных программ>
;
;- - - - - - - - - - - - - - - - - - - - - - - - - - -
;- - - - - - - - - - - - - - - - - - - - - - - - - - -
;
;       < Bставьте данные >
;
;- - - - - - - - - - - - - - - - - - - - - - - - - - -
;Дополнительный  стек  -  BHИМAHИЕ - вы ДОЛЖНЫ(!)
;использовать функцию 4Сh для завершения данной
;программы, если вы используете локальный стек !
;
       db       32 DUP ('stack   ')     ; 256-байтный стек
top_of_stack    EQU    $
;
;- - - - - - - - - - - - - - - - - - - - - -  - - - - -
code   ENDS      ; конец сегмента текста программы
       END      entry
----------------------------------------------------------------

        Листинг A-7. Полезные  макрокоманды (STDMAC.INC):
----------------------------------------------------------------
; - - - - - - - - - - - - - - - - - - - - - - - - - - - -
;  Файл включения макроопределений
;- -  - - - - - - - - - - - - - - - - - - - - - - - - - - -
; Стандартные равенства:
;
TRUE   EQU      0FFFFh  ;  "истина"

   FALSE   EQU     0    ;  "ложь"
   ;
   ; Cтандартные непечатаемые символы
   NUL     EQU    00000000b ; нуль
   BEL     EQU    00000111b ; "звонок"
   BS      EQU    00001000b ; возврат на символ с его стиранием
   HT      EQU    00001001b ; горизонтальная табуляция
   LF      EQU    00001010b ; перевод строки
   FF      EQU    00001100b ; перевод страницы
   CR      EQU    00001101b ; возврат каретки
   SUBST   EQU    00011010b ; подстановка
   ESCAPE  EQU    00011011b ; переход
   SPACE   EQU    00100000b ; пробел
   COLON   EQU    00111010b ; двоеточие
   SCOLON  EQU    00111011b ; точка с запятой
   ;
   ; Pасширенные символы (фирмы "ИБМ"):
   SLINE   EQU    11000100b  ; горизонтальная строка
   ;
   ;- - - - - - - - - - - - - - - - - - - - - - -
   ..XLIST   ; запретить распечатку макроопределений
   ;;.LALL ї_ї.  ; распечатка всего
   ;;
   ;;
   ;;** @MODEL ********* Макроопределения общего назначения **
   ;; Установка сегментов согласно модели памяти.
   ;; Это  макроопределение эмулирует управляющую команду
   ;; 5.Х.МОDEL макроассемблера MASM для использования с
   ;; более ранними версиями MASM.

   IF1    ;; Ассемблирование только в процессе прохода 1
   @Model MACRO memory_model,code_name,stack_size
  ;; ПРИМЕЧAHИЕ: "имя-программы" используется только
  ;; со средними, большими, а также с очень большими
  ;; моделями памяти
  IFNB   ;; модель памяти была указана?
  ;;
     IF memory_model  EQ 0
     @TinyModel stack_size
 ELSE
     IF memory_model EQ 1
     @SmallModel stack_size
  ELSE
       IF memory_model EQ 2
       @MediumModel code_name,stack_size
     ELSE
       IF memory_model EQ 3
       @CompactModel stack_size
     ELSE
       IF memory-model EQ 4
       @ LargeModel code_name,stack_size
     ELSE
       IF memory_model EQ 5
       @Large_Model code_name,stack_size
     ELSE
       .ERR
       %0UT @Model macro: неизвестная модель памяти
     ENDIF;; конец проверки очень большой модели
   ENDIF;; конец проверки большой модели
 ENDIF;; конец проверки компактной модели
        ENDIF;; конец проверки средней модели
      ENDIF;; конец проверки малой модели
    ENDIF;; конец проверки  очень малой модели
   ;;
   ELSE   ;; модель памяти не была указана
      .ERR       ;; завершить сообщением об ошибке
      %0UT @MODEL macro error: модель памяти не указана
   ENDIF  ;; конец проверки параметров модели - памяти
   ;;
   ENDM   ;; конец макроопределения
   ;;
   ENDIF  ;; конец обработки  прохода
   ;;
   ;;** @Tiny ************ Макрокоманды общего назначения **
   ;; (Эта управляющая макрокоманда вызывается через @Model 0.
   ;; Эта управляющая макрокоманда также может  вызываться
   ;; непосредственно).
   ;; Отметим, что эта макрокоманда, в отличие от других мак-
   ;; рокоманд  памяти-модели,  не  использует   макрокоманду
   ;; @Stack, поскольку другие стеки в .COM - программах дол-
   ;; жны  быть описаны в конце данной программы. Для опреде-
   ;; ления других стеков в .COM-программах выполните  макро-
   ;; команду @Stack в соответствующем месте исходного текста
   ;; программы.
   IF1   ;; Ассемблировать только в процессе прохода 1
   @TinyModel MACRO
       MEMODEL = 0
      _TEXT SEGMENT BYTE PUBLIC  'CODE' ; сегмент программы
      _TEXT ENDS
      ;; Назначить  физические  сегменты
      ASSUME cs:_TEXT,ds:_TEXT,ss:_TEXT, es:_TEXT
      ;;- - - - - - - - - - - - - - - - - - - - - - -
      ;; Вставьте вручную следующий текст программы после
      ;; @Model 0:
      ;;
      ;; _TEXT SEGMENT
      ;; main PROС near ;;  entry:  ORG 0100h ;;  jmp Start ;;  ;
      вставьте данные  здесь,  если  требуется  ;;  start:  ;;  ;
      вставьте текст программы здесь ;;  main ENDP ;;  ; вставьте
      стандартные программы здесь ;;  ;  вставьте  дополнительный
      стек здесь ;; ; вставьте данные в конце, если требуется
      ;; _TEXT ENDS ;;
      ;;- - - - - - - - - - - - - - - - - - - - - - - - - - -
      ENDM ;; конец макроопределения
ENDIF    ;; конец обработки прохода
;;** @Small ************ Mакрокоманды общего назначения **
;; Управляющая  макрокоманда  для установки Малой (SMALL)
;; модели памяти.
;; (Эта макрокоманда вызывается  через "@Model Small".
;; Эта  макрокоманда может быть вызвана также
;; непосредственно.)
IF1   ;; Ассемблирование только в процессе прохода 1
@SmallModel MACRO stack_size
      MEMODEL = 1
      _TEXT SEGMENT BYTE PUBLICK 'CODE'  ; сегмент программы
      _TEXT ENDS
      _DATA SEGMENT WORD PUBLIC 'DATA'   ; сегмент данных
     ; (DGROUP)
      _DATA ENDS
      CONST SEGMENT WORD PUBLIC 'CONST'  ; сегмент констант
      CONST ENDS       ; (DGROUP)
      _BSS SEGMENT WORD PUBLIC 'BSS'     ; сегмент непроинициа-
      _BSS ENDS        ; лизированных данных
     ; (DGROUP)
      STACK SEGMENT PARA STACK 'STACK'   ; сегмент стека
     ; (DGROUP)
      STACK ENDS
      ;;
      IFNB 
     @Stack stack_size
      ;;
     ENDIF  ;; конец обработки прохода
      ;;
      DGROUP GROUP _DATA,CONST,_BSS,STACK ; группирование
      ; сегментов данных
      ;;
      ;; Назначить физические сегменты:
      ASSUME   cs:_TEXT, ds:DGROUP, ss:DGROUP, es:DGROUP
      ;;
      ENDM  ;;  конец макроопределения
ENDIF   ;; конец обработки прохода
;;
;;** @Medium ******** Макрокоманды общего назначения **
;; Управляющая макрокоманда для установки средней модели
;; памяти. (Эта макрокоманда  вызывается  через  "@Model
;; medium".  Эта  макрокоманда  может быть вызвана также
;; непосредственно.)
IF1  ;; Ассемблировать только в процессе прохода 1
@MediumModel MACRO code_name,stack_size
       MEMODEL = 2
       code_name_TEXT SEGMENT BYTE PUBLIC 'CODE' ;поименованный
        ; сегмент программы
       code_name_TEXT ENDS     ;
       _DATA SEGMENT WORD PUBLIC 'DATA'     ; сегмент данных
       _DATA ENDS; (DGROUP)
       CONST SEGMENT WORD PUBLIC 'CONST'    ; сегмент констант
       CONST ENDS; (DGROUP)
       _BSS SEGMENT WORD PUBLIC 'BSS'       ; сегмент непроинициа-
       _BSS ENDS ; лизированных данных
        ; (DGROUP)
       STACK SEGMENT PARA STACK 'STACK'     ; сегмент стека
       STACK ENDS; (DGROUP)
       ;;
       IFNB 
      @Stack stack_size
       ENDIF
       ;;
       DGROUP GROUP _DATA,CONST,_BSS,STACK  ; группирование
        ; сегмента данных
       ;;
       ;; Hазначить физические сегменты
       ASSUME  cs:_TEXT, ds:DGROUP, ss:DGROUP, es:DGROUP
       ;;
       ENDM   ;; конец макроопределения
     ENDIF  ;; конец обработки прохода
       ;;
       ;;** @COMPACT ****** Mакрокоманды общего назначения **
       ;; Управляющая макрокоманда для установки компактной
       ;; (COMPACT) модели памяти. (Эта макрокоманда вызывается
       ;; через "@Model compact". Эта макрокоманда может быть
       ;; вызвана также непосредственно.)
       IF1   ;; Ассемблировать только в процессе прохода 1
       @CompactModel MACRO stack_size
       MEMODEL = 3
     _TEXT SEGMENT BYTE PUBLIC 'CODE' ;сегмент текста программы
     _TEXT ENDS
     FAR_DATA SEGMENT PARA 'FAR_DATA' ; личный далекий сегмент
     FAR_DATA ENDS  ; данных (DGROUP)
     FAR_BSS SEGMENT PARA 'FAR_BSS'   ; личный далекий непро-
     FAR_BSS ENDS   ; инициализированный сег-
  ; мент данных (DGROUP)
    _DATA SEGMENT WORD PUBLICK 'DATA'  ; сегмент данных
    _DATA ENDS       ; (DGROUP)
    CONST SEGMENT WORD PUBLIBC 'CONST' ; сегмент констант
    CONST ENDS       ; (DGROUP)
   _BSS SEGMENT WORD PUBLIC 'BSS'      ; сегмент непроинициа-
   _BSS ENDS; лизированных данных
   ; (DGROUP)
     STACK SEGMENT PARA STACK 'STACK'     ; сегмент стека
     STACK ENDS; (DGROUP)
     ;;
     IFNB 
    @Stack stack_size
     ENDIF
     ;;
     DGROUP GROUP _DATA,CONST,_BSS,STACK  ; группирование
      ; сегментов данных
     ;;
     ;; Назначить физические сегменты:
     ASSUME cs:_TEXT,ds:DGROUP, ss:DGROUP,es:DGROUP
     ;;
     ENDM  ;; конец макроопределения
ENDIF  ;;  конец обработки прохода
;;
;;** @Large ***************** Mакрокоманды общего назначения **
;; Управляющая макрокоманда для установки большой (LARGE)
;; модели памяти. (Эта макрокоманда вызывается
;; через "@Model Large". Эта макрокоманда может быть
;; вызвана также непосредственно.)
IF1  ;; Ассемблировать только в процессе прохода 1
@LargeModel MACRO code_name,stack_size
    MEMODEL = 4
    code_name_TEXT SEGMENT BYTE PUBLIC 'CODE'  ; поименованный
    code_name_TEXT ENDS  ; сегмент программы
    FAR_DATA SEGMENT PARA 'FAR_DATA'    ; личный далекий сегмент
    FAR_DATA ENDS     ; данных (DGROUP)
    FAR_BSS SEGMENT PARA 'FAR_BSS'      ; личный далекий непро-
    FAR_BSS ENDS      ; инициализированный сег-
    ; мент данных (DGROUP)
    _DATA SEGMENT WORD PUBLIC 'DATA'    ; сегмент данных
    _DATA ENDS        ; (DGROUP)
    CONST SEGMENT WORD PUBLIC 'CONST'   ; сегмент констант
    CONST ENDS        ; (DGROUP)
    _BSS SEGMENT WORD PUBLIC 'BSS'      ; сегмент непроинициа-
    _BSS ENDS; лизированных данных
    ; (DGROUP)
    STACK SEGMENT PARA STACK 'STACK'    ; сегмент стека
    STACK ENDS        ; (DGROUP)
    ;;
    IFNB 


@Stack stack_size
     ENDIF
     ;;
     DGROUP GROUP _DATA,CONST,_BSS,STACK  ; группирование
      ; сегмента данных
     ;;
     ;; Назначить физические сегменты
     ASSUME cs:_TEXT,ds:DGROUP, ss:DGROUP,es:DGROUP
     ;;
       ENDM   ;; конец макроопределения
   ENDIF  ;; конец обработки прохода
;;
;;** @HUGE ************* Mакрокоманды общего назначения **
;;  Управляющая макрокоманда для установки очень большой
;;  (HUGE) модели памяти. (Эта макрокоманда вызывается
;;  через "@Model huge". Эта макрокоманда может быть
;;  вызвана также непосредственно.)
;;  Oчень  большая (HUGE) модель памяти в настоящее время
;;  устанавливается так же как и Большая (LARGE) модель
;;  памяти.
IF1 ;; Ассемблировать только в процессе прохода 1
@HugeModel MACRO code_name,stack_size
        MEMODAL = 5
        @LargeModel code_name,stack_size
       ENDM  ;; конец макроопределения
ENDIF  ;;  конец обработки прохода
;;
;;** @Stack ************* Mакрокоманды общего назначения **
;; Управляющая  макрокоманда для установки размера стека
IF1   ;; Ассемблировать только в процессе прохода 1
@Stack MACRO stack_size,prog_type
  ;;
  IFB   ;;  если параметр типа программы пустой
    IF MEMODEL EQ 0
      PROGTYPE = 0
    ELSE
      IF MEMODEL EQ 1
PROGTYPE = 1
    ELSE
      IF MEMODEL EQ 2
PROGTYPE = 1
    ELSE
      IF MEMODEL EQ 4
PROGTYPE = 1
      ELSE
 IF MEMODEL EQ 5
    PROGTYPE = 1
 ELSE
     .ERR
     %OUT @Stack macro: модель памяти
     %OUT или тип программы не были установлены
 ENDIF;; конец проверки очень большой модели
        ENDIF ;; конец проверки большой модели
      ENDIF ;; конец проверки компактной модели
    ENDIF ;; конец проверки средней модели
  ENDIF ;; конец проверки малой модели
ENDIF ;; конец проверки очень маленькой модели
ELSE ;;  параметр типа программы был указан
  IF prog_type EQ 0  ;; установка программы типа .COM
     PROGTYPE = 0
  ELSE
    IF prog_type EQ 1
     PROGTYPE = 1
    ELSE
      .ERR     ;;  выход с сообщением об ошибке
      %OUT @Stack macro: указан некорректный тип программы
     ENDIF ;; конец проверки типа .EXE
   ENDIF ;; конец проверки типа  .COM
ENDIF ;;  конец проверки параметра "тип-программы"
;;
IFNB 
;;
   IF PROGTYPE EQ 0
;  Дополнительный стек. BHИМAHИЕ - вы должны ис-
;  пользовать функцию 4h для  завершения  данной
;  программы, если вы используете локальный стек.
       db    stack_size DUP ('стек    ')
top_of_stack EQU     $
   ELSE ;;  тип программы - .EXE
STACK SEGMENT
        db   stack_size DUP ('стек    ')
STACK ENDS
   ENDIF ;; конец проверки PROGTYPE
;;
ELSE  ;; параметр "размер-стека" не был указан
;;
  IF PROGTYPE EQ 0
; Дополнительный стек. ВНИМАНИЕ - вы должны исполь-
; зовать функцию 4h для завершения данной программы
; в  случае использования локального стека !
        db       32 DUP ('стек    ')
     top_of_stack       EQU    $
  ELSE ;; тип программы - .EXE
     STACK SEGMENT
     db     32 DUP ('стек    ')
     STACK ENDS
        ENDIF ;; конец проверки PROGTYPE
     ENDIF  ;; конец проверки "размера стека"
     ;;
     ENDM   ;; конец макроопределения
ENDIF  ;; конец выполнения прохода
;;
;;** @SwapNewStack ******** Mакрокоманды общего назначения **
;; Переключить стек на новый стек
IF1   ;; Ассемблировать только в процессе прохода 1
@SwapNewStack MACRO  tos
     LOCAL        bypass
     ;;
     jmp bypass       ;; пропустить область данных
old_stk_seg       dw      ?;; пространство для
;; сегмента стека вызывающей макрокоманды
old_stk_ptr       dw      ?;; пространство для
        ; указателя стека вызывающей макрокоманды
new_stk_seg       dw      ?;; пространство  для
    ;; нового сегмента   стека
new_stk_ptr       dw  offset tos    ;; пространство  для
    ;; нового указателя  стека
        ;;
bypass:
        mov       cs:new_stk_seg,cs ;; установить сегмент
;; нового стека
        mov       cs:old_stk_seg,ss ;; сохранить старые
;; значения стека
        mov       cs:old_stk_ptr,sp ;;їсохранить старый
;; указатель стека
        mov       ss,cs:new_stk_seg ;; получить новые
;; значения стека
        mov       sp,cs:new_stk_ptr ;; получить новый
;; указатель стека
        @PushAll  ;; сохранить признаки и
    ;; содержимое всех регистров
     ENDM   ;; конец макроопределения
ENDIF  ;; конец выполнения прохода
;;
;;**@SwapOldStack********** Mакрокоманды общего назначения **
;; Переключить с нового стека на исходный стек
        @Popall      ;; восстановить признаки и
   ;; содержимое всех регистров
        mov       ss,cs:old_stk_seg  ;; восстановить старые
 ;; значения стека
        mov       sp,cs:old_stk_ptr
     ENDM   ;; конец макроопределения
ENDIF  ;; конец выполнения прохода
;;
;;** @DosCall ************* Mакрокоманды общего назначения **
;; Bызвать функцию MS-DOS
   IF1     ;;  Ассемблировать только в процессе прохода 1
   @DosCall MACRO
   int      21h
ENDM   ;; конец макроопределения
   ENDIF  ;; конец выполнения прохода
   ;;
   ;;**@DirConChar 10 ***** Mакрокоманды общего назначения **
   @DirConCharIO MACRO       ; проверить состояние клавиатуры
  ; и считать
  push     dx     ; cохранить DX
  mov      dl,0FFh; нет символа для вывода
  mov      ah,06h ;
     @DosCall
     pop      dx       ; восстановить DX
     ENDM
   ;;
   ;;** @ReadCon_NoEcho **** Mакрокоманды общего назначения **
   @ReadCon_NoEcho MACRO
  mov     ah,08h     ; считать с клавиатуры без эхо
  @DosCall
  ENDM
   ;;
   ;;** @ReadBuffInput ***** Mакрокоманды общего назначения **
   @ReadBuffInput MACRO bufname   ; считать буферизованный
       ; ввод с клавиатуры
  mov    dx,offset bufname
  mov    ah,0Ah
  @DosCall
  ENDM
   ;;
   ;;**DisChr ************** Mакрокоманды общего назначения **
   ;; Отобразить на экране символ
   IF1    ;; Ассемблировать только в процессе прохода 1
  @DisChr MACRO   char
  IFNB      ;; аргумент символа был указан ?
;; да, поэтому вставить команду
  push    ax      ;; сохранить используемые регистры
  push    dx
  mov     dl,char ;; загрузить символ
  mov     ah,02h  ;; загрузить  номер функции
  @DosCall        ;; вызвать MS-DOS
  pop     dx      ;; восстановить содержимое регистров
  pop     ax
  ELSE   ;; в противном случае
  .ERR   ;; сгенерировать  и вывести
;; сообщение об ошибке
  %OUT @DisChr macro : "char" аргумент
        не указывается
    ENDIF
  ;;
ENDM   ;; конец макроопределения
   ENDIF  ;; конец выполнения прохода

   ;;
   ;;** @DisStr ************** Mакрокоманды общего назначения **
   ;; Oтобразить на экране строку памяти с  терминатором  кон-
   ;; ца-строки по умолчанию "$" или с указанным терминатором.
   ;; (Bызовы внутренних  макрокоманд @DisStr1 или @DisStr2.)
   IF1  ;; Ассемблировать только в процессе прохода 1
   @DisStr  MACRO  строка,терминатор
IFNB     ;; параметр строки был указан?
       ;; да, поэтому
 IFB ;; терминатор был указан?
      ;; нет, поэтому вставить команду по
      ;; умолчанию для  терминатора  "$"
      @DisStr1 string
ELSE  ;;  в противном случае терминатор был указан
      @DisStr2 string,terminator
ENDIF ;; конeц проверки "терминатора"
ELSE  ;; в противном случае,"строка" не была указана
.ERR  ;; сгенерировать и вывести сообщение об ошибке
%OUT @DisStr macro: "string" аргумент не
     указывается
      ENDIF
      ENDM   ;; конец макроопределения
   ENDIF  ;; конец выполнения прохода
   ;;
   ;;** @DisStr1 ********** Служебные макрокоманды *******
   ;; Вызваны макрокомандой @DisStr1 для отображения строки
   ;; памяти с терминатором конца-строки "$" по умолчанию.
   IF1    ;; Ассемблировать только в процессе прохода 1
   @DisStr1 MACRO  string
   push   ax    ;; сохранить используемые регистры
   push   dx
   mov    dx,offset ds:string ;; указать на  строку
   ;; в памяти
   mov    ah,09h ;; загрузить номер функции
   @DosCall      ;; обратиться к  MS-DOS
   pop    dx     ;; сохранить регистры
   pop    ax
ENDM   ;; конец макроопределения
   ENDIF  ;; конец выполнения прохода
   ;;** @DisStr2 ************ Служебные макрокоманды *******
   ;; Вызваны макрокомандой @DisStr1 для отображения строки
   ;; памяти с указанным терминатором конца-строки.
   IF1      ;; Ассемблировать только в процессе прохода 1
   @DisStr2 MACRO string,terminator
   LOCAL strloop,strloopdone ;; создать локальные метки
   push  si;; сохранить регистры
   push  ax
   push  bx
   push  dx
   xor   bh,bh      ;; очистить BX
   mov   bl,terminator       ;; получить терминатор
   mov   si,offset string    ;; указать  на строку
   xor   dx,dx
   strloop:
   mov   dl,byte ptr [si] ;; получить следующий символ
   cmp   dl,bl      ;; это терминатор?
   je    strloopdone;; да, мы сделали
   mov   ax,02h     ;; загрузить функцию
  ;; вывода символов
   @DosCall;; и вызвать DOS
   jnc   si  ;; указать на следующий символ
   jmp   short strloop       ;; и повторить
   strloopdone:
   pop   dx      ;; восстановить содержимое регистров
   pop   bx
   pop   ax
   pop   si
ENDM   ;; конец макроопределения
   ENDIF  ;; конец выполнения прохода
   ;;
   ;;** @TypeStr ********** Mакрокоманды общего назначения **
   ;; Отобразить ближайшую строку.
   ;; Примечание: "строка" должна быть представлена в кавычках
   ;; с тем, чтобы она обрабатывалась как один аргумент макро-
   ;; команды  и  чтобы гарантировать, что данные закодированы
   ;; корректно.
   IF1      ;; Ассемблировать только в процессе прохода 1
   @TypeStr MACRO   string;; определить и отобразить
        ;; строку
   LOCAL   TypeStrAddr    ;; установить локальную метку
   ;;
   IF MEMODEL NE 0        ;; если не тип .COM
   _TEXT    ENDS ;; конец сегмента программы
   _DATA    SEGMENT     ;; изменить на сегмент данных
   ENDIF
   TypeStrAddr  DB string,'$' ;; определить строку в сегменте
   ;; данных
   IF MEMODEL NE 0   ;; если не тип .COM
   _DATA    ENDS     ;; конец сегмента данных
   _TEXT    SEGMENT        ;; вернуться к сегменту программы
   ENDIF
   ;;
   @DisStr TypeStrAddr   ;; отобразить строку
ENDM   ;; конец макроопределения
   ENDIF  ;; конец выполнения прохода
   ;;
   ;;** @TypeStrCR ******** Mакрокоманды общего назначения **
   ;; Oтобразить ближайшую строку , завершаемую с
   ;; помощью GR/LF.
   IF1      ;; Ассемблировать только в процессе прохода 1
   ;; "строка" должна быть представлена в кавычках с тем, чтобы
   ;; она обрабатывалась как один аргумент макрокоманды.
   @TypeStrCR MACRO    string
   @TypeStr   string ;; определить и отобразить строку
   @NewLine ;; завершить с помощью GR/LF
ENDM   ;; конец макроопределения
   ENDIF  ;; конец выполнения прохода
   ;;
   ;;**@NewLine *********** Mакрокоманды общего назначения **
   ;; Oтобразить символ возврата каретки и перевода строки.
   IF1      ;; Ассемблировать только в процессе прохода 1
   @NewLine MACRO
   IFNDEF     EXT_NEWLINE     ;; символ EXT_NEWLINE
   ;; был определен?
   EXTRN      newLine:NEAR    ;; нет, вставьте EXTRN
   ;; только один раз
   EXT_NEWLINE EQU 0 ;; и опишите равенство
   ;; только один раз
   ENDIF        ;; верхние две строки не должны
       ;; в последующие вызовы макрокоманд вставляться
   call newLine ;; вызвать процедуру NEWLINE
ENDM   ;; конец макроопределения
   ENDIF  ;; конец выполнения прохода
   ;;
   ;;**@DisNum ************ Mакрокоманды общего назначения **
   ;; Отобразить двоичное число в десятичном или шестнадцати-
   ;; ричном виде кода ASCII.
   IF1      ;; Ассемблировать только в процессе прохода 1
   @DisNum MACRO number,type,digits,sign
   ;;
   ;; Проверьте сначала требуемые параметры
   IFB   ;; числовой параметр указан?
   .ERR ;; нет, завершить обработку
        ;; сообщением об ошибке
   %OUT @DisNum macro: "number" параметр не указан.
   ENDIF
   ;;
   IFNB    ;; тип вывода указан?
   ;;
 If type EQ 10;; десятичное  преобразование
     ;; указано?
   IFNDEF EXT_BIN2DEC  ;; было определеноEXT_BIN2DEC?
   EXTRN bin2dec:NEAR  ;; нет, вставьте определение
     ;; EXTRN
EXT_BIN2DEC EQU 0    ;; и только раз установите
   ;; равенство
ENDIF
;;
ELSE
;;
       IF type EQ 16       ;; шестнадцатиричное
    ;; преобразование  указано?
IFNDEF EXT_BIN2HEX    ;; было определено EXT_BIN2HEX?
EXTRN   bin2hex:NEAR  ;; нет, вставьте определение
EXT_BIN2HEX EQU 0     ;; EXTRN и только раз установите
    ;; равенство
ENDIF
       ;;
       ELSE
       ;;
        .ERR
        %OUT @DisNum Macro: указан "type" запрещенный  "тип"
        ENDIF        ;; окончить  проверку  для шестнадца-
   ;; тиричного   преобразования
    ;;
    ENDIF ;; окончить  проверку  для десятичного преобразования
;;
ELSE   ;; в противном  случае,  параметр пустой
;;
.ЕRR   ;; завершить выполнение сообщением об ошибке
%OUT @DisNum macro: "type" параметр не указан
ENDIF  ;;  окончить  проверку  пустого параметра
;; Oкoнчить проверку требуемых параметров
;;
;; Hачать вставку программы
push     ax   ;; сохранить содержимое регистров
push     cx
push     dx
;;
mov ax,number ;; поместить число в AX
;;
IFNB  ;; аргумент "разряды"  указан?
mov      ch,digits     ;; да, записать значение в CH
ELSE ;; в противном случае,  по  умолчанию
mov      ch,1 ;; отобразить по крайней мере 1 разряд
ENDIF
;;
IFNB    ;; аргумент "знак"  указан?
mov      dx,sign       ;; да, поэтому поместить его в DX
ELSE ;; в противном случае, по умолчанию знак
mov      dx,0 ;; будет  отсутствовать
ENDIF
;;
If type  EQ 10;; десятичное преобразование указано?
call     bin2dec
ELSE
   IF type EQ 16  ;; шестнадцатиричное преобразование
;; указано?
  call bin2hex
  ENDIF  ;; конец проверки по основанию 16
   ENDIF   ;; конец проверки по основанию 10
   ;;
   pop     dx   ;; восстановить содержимое регистров
   pop     cx
   pop     ax
   ;;
ENDM   ;; конец макроопределения
   ENDIF  ;; конец выполнения прохода
   ;;
   ;;
   ;;** @GetDate ********** Mакрокоманды общего назначения **
   ;; Получить  системную дату
   IF1      ;; Ассемблировать только в процессе прохода 1
   @GetDate MACRO
   mov      ah,2Ah ;; загрузить номер функции
   @DosCall        ;; вызвать  MS-DOS
ENDM   ;; конец макроопределения
   ENDIF  ;; конец выполнения прохода
   ;;
  ;;** @GetTime ********** Mакрокоманды общего назначения **
   ;; Получить  системное время
   IF1      ;; Ассемблировать только в процессе прохода 1
   @GetTime MACRO
   mov      ah,2Ch ;; загрузить номер функции
   @DosCall        ;; вызвать  MS-DOS
ENDM   ;; конец макроопределения
   ENDIF  ;; конец выполнения прохода
   ;;
   ;;** @DiskRead ******** Mакрокоманды общего назначения **
   ;; Считать логический  сектор(а)
   IF1      ;; Ассемблировать только в процессе прохода 1
   @DiskRead MACRO
   int     25h  ;; обработать абсолютное прерывание
       ;; по чтению диска
ENDM   ;; конец макроопределения
   ENDIF  ;; конец выполнения прохода
   ;;
   ;;** @DiskWrite ******* Mакрокоманды общего назначения **
   ;; Записать в логический сектор(а)
   IF1      ;;  Ассемблировать только в процессе прохода 1
@DiskWrite MACRO
int      26h     ;; обработать машинное прерывание
        ;; по записи на диск
      ENDM   ;; конец макроопределения
ENDIF  ;; конец выполнения прохода
;;
;;** @GetDOSVersion **** Mакрокоманды общего назначения **
;; Получить номер версии операционной  системы MS-DOS
IF1      ;; Ассемблировать только в процессе прохода 1
@GetDOSVersion MACRO
push     bx      ;; сохранить содержимое
        ;; уничтоженных  регистров
push     cx
mov      ah,30h  ;; загрузить номер функции
@DosCall;; вызвать MS-DOS
pop      cx      ;; восстановить содержимое регистров
pop      bx
      ENDM   ;; конец макроопределения
ENDIF  ;; конец выполнения прохода
;;
;;** @GetDOSVer ******* Mакрокоманды общего назначения **
;; Получить номер версии операционной  системы MS-DOS
IF1      ;; Ассемблировать только в процессе прохода 1
@GetDOSVer MACRO
IFNDEF   EXT_GDOSV     ;; символ определен?
EXTRN    GETDOSV:NEAR  ;; нет, вставить команду EXTRN
     ;; только  один  раз
EXT_GDOSV EQU 0        ;; и только раз определить
     ;; равенство
ENDIF;; (две верхние строки не
     ;; должны вставляться в
     ;; последующие вызовы
     ;; макроопределения)
call     dosver        ;; вызвать библиотечную
     ;; стандартную программу
      ENDM   ;; конец макроопределения
ENDIF  ;; конец выполнения прохода
;;
;;** @DisDOSVer ********* Mакрокоманды общего назначения **
;; Получить и отобразить номер версии DOS
IF1      ;; Ассемблировать только в процессе прохода 1
@DisDOSVer MACRO
IFNDEF   EXT_DDOSV     ;; символ определен?
EXTRN    DOSV2CON:NEAR ;; нет, вставить команду EXTRN
     ;; только  один  раз
EXT_DDOSV EQU 0        ;; и только раз определить
     ;; равенство
ENDIF;; (две верхние строки не
     ;; должны вставляться в
     ;; последующие вызовы
     ;; макроопределения)
call     dosv2con      ;; вызвать библиотечную
     ;; стандартную программу
      ENDM   ;; конец макроопределения
ENDIF  ;; конец выполнения прохода
;;
;;** @ChangeСase ******* Mакрокоманды общего назначения **
;; Изменить регистр  клавиатуры для  символа
IF1      ;; Bыполнять только в  процессе прохода 1
@ChangeCase MACRO  char,type
     IFB    ;; символ, подлежащий преобразованию,
;; указан ?
     .ERR       ;; нет, сгенерировать и
       ;; вывести сообщение  об  ошибке
     %OUT @ChangeCase macro: "char" параметр не определен !
     ELSE ;; в противном случае
     mov      al,char       ;; загрузите символ в AL
     ENDIF
     ;;
     IFB  ;; тип преобразования указан?
     mov   ah,0 ;; нет, поэтому загрузить 0 в AH
     ELSE
     mov   ah,type   ;; загрузить тип преобразования в AH
     ENDIF
     ;;
     IFNDEF EXT_CHGCASE  ;; символ EXT_CHGCASE определен?
     EXTRN  CHGCASE:NEAR ;; нет, вставить EXTRN только раз
     EXT_CHGCASE EQU 0   ;; и только раз определить равенство
     ENDIF    ;; (две верхние строки не должны вставляться в
     ;; последующие вызовы данной макрокоманды)
     ;;
     call     chgcase    ;; вызвать библиотечную процедуру
       ;; изменения регистра клавиатуры
  ENDM   ;; конец макроопределения
ENDIF  ;; конец выполнения прохода
;;
;;** @case ************* Mакрокоманды общего назначения **
;; Mакрокоманда CASE языка ассемблера
@Case    MACRO    key,case_list,jmp_labels
??tmp_1 = 0
IRP      match,<&case_list>  ;; упорядочить регистры
  ??tmp_1 = ??tmp_1 + 1  ;; установить номер индекса
  cmp    key,&&match       ;; регистр соответствует?
  ??tmp_2 = 0
  IRP    retl,<&jmp_labels>  ;; упорядочить переходы
    ??tmp_2 = ??tmp_2 + 1  ;; до тех пор, пока индекс
;; не будет соответствовать
    IF (??tmp_1 EQ ??tmp_2)
      je &&&retl    ;; да !
      EXITM
    ENDIF   ;; конец проверки условия
  ENDM      ;; конец второго блока IRP
ENDM        ;; конец первого блока IRP
ENDM        ;; конец макроопределения
;;
;;
;;*****************************************************
;; Используйте макрокоманды @PushAll и @PopAll вместо ко-
;; манд   PUSHA   и   POPA,   поддерживаемых  процессором
;; 80186/80188/80286/80386 для обеспечения  совместимости
;; с процессорами 8086/8088.
;;
;;** @PushAll ********** Mакрокоманды общего назначения **
;;  Поместить в стек содержимого всех регистров
IF1     ;; Выполнять только в процессе прохода 1
@PushAll MACRО  ;; сохранить содержимое всех регистров в стеке
        push      ax
        push      bx
        push      cx
        push      dx
        push      dp
        push      di
        push      si
      ENDM   ;; конец макроопределения
ENDIF  ;; конец выполнения прохода
;;
;;** @PopAll *********** Mакрокоманды общего назначения **
;; Снять со стека содержимое всех регистров
IF1     ;; Выполнять только в процессе прохода 1
@PopAll MACRO  ;; восстановить  содержимое всех
      ;; регистров из стеке
        pop       si
        pop       di
        pop       dp
        pop       dx
        pop       cx
        pop       bx
        pop       ax
      ENDM   ;; конец макроопределения
ENDIF  ;; конец выполнения прохода
;;
;;** @ExiToDos ********* Mакрокоманды общего назначения **
;;   Завершить процесс с необязательными установками
;;   значений переменной ERRORLEVEL
IF1     ;; Выполнять только в процессе прохода 1
@ExiToDOS MACRO errorcode
        IFB     ;; код ошибки был указан?
        mov       ax,4C00h ;; нет, загрузить функцию и значение
;; переменной ERRORLEVEL = "0" в AX
        ELSE      ;; в противном случае
        mov       ah,4Ch   ;; загрузить функцию и значение
        mov       al,errorcode  ;; переменной ERRORLEVEL отдельно
        ENDIF
        ;;
        @DosCall  ;; вызвать MS-DOS
      ENDM   ;; конец макроопределения
ENDIF  ;; конец выполнения прохода
;;
;;********************************************************
;; Конец макроопределений
;;********************************************************
.LIST      ; восстановить выдачу листингов в нормальном виде
;; Kонец файла включения макроопределений

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

НАЗАД СОДЕРЖАНИЕ ВПЕРЁД

Hosted by uCoz