Главная · Поиск книг · Поступления книг · Top 40 · Форумы · Ссылки · Читатели

Настройка текста
Перенос строк


    Прохождения игр    
Demon's Souls |#13| Storm King
Demon's Souls |#11| Мaneater part 2
Demon's Souls |#10| Мaneater (part 1)
Demon's Souls |#9| Heart of surprises

Другие игры...


liveinternet.ru: показано число просмотров за 24 часа, посетителей за 24 часа и за сегодня
Rambler's Top100
Образование - Различные авторы Весь текст 2311.07 Kb

Программирование и кодирование

Предыдущая страница Следующая страница
1 ... 25 26 27 28 29 30 31  32 33 34 35 36 37 38 ... 198
                           программного префикса

             После того, как найден адрес блока памяти, необходимо опреде-
         лить общее количество памяти,  необходимое для сохранения. Разли-
         чия между программами .COM и программами  .EXE  здесь  становятся
         уже  более заметными.  Для программы типа .EXE размер должен быть
         определен путем вычитания адреса начала сегмента  PSP  из  адреса
         сегмента  фиктивного сегмента,  расположенного в конце программы,
         как показано в листинге 2-12.  Почему используются адреса сегмен-
         тов?  Функция  4Ah ожидает размер в параграфах,  а адрес сегмента
         обычно является адресом параграфа.

          Листинг 2-12. Функция 4Ah - "Модифицировать блок распределенной
                  памяти" - изменение размера программы типа .EXE
         -----------------------------------------------------------------

         resize PROC NEAR
                mov     ax,es           ; получение адреса PSP

                                      - 2-41 -
                mov     bx,SEG end_addr ; получение адреса сл. сегмента
                sub     bx,ax           ; разность - размер программы
                mov     ah,04Ah         ; модификация распредел-й памяти
                int     21h             ; вызов MS-DOS
                jnc     short resize_ok ; нет переноса => хорошо
                mov     ax,04C00h       ; перенос => сбой--авар. заверш.
                int     21h
         resize_ok:
                ret
         resize ENDP
         ;
         ; Оставшаяся  часть программного кода в этой программе END_ADDR
         ; является последним  элементом  перед  предложением  END.  Это
         ; сделано для того,  чтобы предложение END_ADDR связалось бы как
         ; последний сегмент, если используется более одного исходного
         ; файла.
         ;
          end_addr  SEGMENT
          end_addr  ENDS
                  END
         -----------------------------------------------------------------

             Для программы типа .COM требуется меньше хлопот. В отличие от
         программы типа .EXE,  которая имеет определенный размер, установ-
         ленный  компоновщиком  LINK,  программы  типа .COM могут изменять
         свой размер.  Размещение стека в программе типа .COM, которое ус-
         танавливается MS-DOS,  может изменяться от конца сегмента (FFFEh)
         на 256 байтов больше  программы  (минимальный  размер,  требуемый
         MSDOS для стека).  Пользователь может выбирать первое,  принимая,
         что MS-DOS обеспечила и изменила размер стека (установленный раз-
         мер 64 кбайт (1000h) параграфов) или все,  что осталось; или вто-
         рое, пересылая стек и изменяя размер, основываясь на этом. Второй
         выбор освобождает больше памяти и,  таким образом, является более
         предпочтительным и рекомендуемым  фирмами "Майкрософт"  и  "ИБМ".
         Листинг 2-13 содержит пример программы .COM, который устанавлива-
         ет свой собственный стек и изменяет размер своего начального бло-
         ка распределения на более умеренный размер.

          Листинг 2-13. Функция 4Ah - "Модифицировать блок распределенной
                  памяти" - изменение размера программы типа .COM
         -----------------------------------------------------------------

         code_seg  SEGMENT
                   ASSUME  cs:code_seg
                   ORG     0000h
         seg_org   EQU     $
                   ORG     0100h
         main      PROC    FAR
         start:
                   mov     sp,offset stack
                   call    resize
         ;
         ; здесь может выполняться оставшаяся часть программы
         ;
         main      ENDP
         resize    PROC    NEAR
                   mov     bx,(offset last_byte - seg_org + 15) shr 4

                                      - 2-42 -
                   mov     ah,04Ah        ; модификация распр-й памяти
                   int     21h            ; вызов MS-DOS
                   jnc     short resize_ok ; нет переноса => хорошо
                   mov     ax,04C00h      ; перенос => сбой--ав.заверш.
                   int     21h
         resize_ok:
                   ret
         resize    ENDP
                   db      32 DUP ('stack   ')
         stack:
         last_byte EQU     $
         code_seg  ENDS
                   END     start
         -----------------------------------------------------------------

             Интересной частью  этой программы является способ определения
         размера результирующей программы.  Для преобразования  количества
         байтов программы в количество параграфов  по-существу посредством
         деления на 16,  используется оператор SHR  макроассемблера  MASM.
         Что не является таким очевидным так это то,  почему seg_org вычи-
         тается из смещения last_byte.  Оператор SHR не выполняется, когда
         применяется  для смещения,  и он вырабатывает сообщение об ошибке
         "Constant was expected" (ожидалась константа).  Однако,  разность
         между двумя смещениями считается постоянной, делая выражение при-
         емлемым для макроассемблера MASM.  Заметим,  что  seg_org  должна
         иметь нулевое смещение так,  чтобы размер был относительно начала
         сегмента. Если бы использовалась метка start, то были бы потеряны
         последние 100 (шестнадцатиричное значение) байт программы. (Заме-
         тим,  что last_byte:  для вычислений работает также хорошо, как и
         last_byte equ $).
             Кроме того,  для успешного  использования освобождения памяти
         прием  вычитания двух смещений (либо метки,  либо количества) для
         получения константы,  может быть успешно использован для всех ти-
         пов  операций,  где  размер требуется в выражениях,  использующих
         константы.  Рассмотрение этого применения для задач  выравнивания
         буферы данных на границу параграфа будет приведено в главе 6.

                   Распределение памяти из языков высокого уровня

             Большинство языков  высокого  уровня  обрабатывает  проблемы,
         связанные с распределением или изменением размера  блоков памяти.
         Пользователю не нужно добавлять программы изменения размера блока
         начального распределения в процессе использования функций  управ-
         ления памятью языка высокого уровня. Например, в библиотеке языка
         программирования Си функции malloc и calloc  работают  независимо
         от начального распределения памяти.




                Защита данных и управление областью действия данных

             Технические приемы, используемые при повторно  входимом коди-
         ровании, подвели нас к другому аспекту модульного  программирова-
         ния:  защите данных в программе от случайного  изменения.  Разру-
         шение  ценных  данных  наиболее  часто  происходит  тогда, когда
         одна часть программы ошибочно изменяет данные, относящиеся к дру-

                                      - 2-43 -
         гой части программы. Путем следования некоторым основным правилам
         возможность такого события может быть значительно уменьшена.  Са-
         мое главное правило состоит в том,  что модульность данных  прог-
         раммы также хороша как и модульность программного кода, управляю-
         щая рядом данных,  к которым подпрограмма может иметь доступ. Это
         понятие очень часто называется "областью действия данных".  Обра-
         тимся к тому,  что мы уже изучили, и посмотрим как это можно при-
         менить для наших новых проблем.

                 Локальная память в сравнении с глобальной памятью

             Память человека в любое конкретное  время  может  иметь  дело
         только с ограниченным количеством понятий.  Для программистов это
         подразумевает то,  что с ростом количества манипулируемых и запо-
         минаемых элементов растет и количество сделанных ошибок.  При ис-
         пользовании локальной памяти для подпрограмм программист уменьша-
         ет  количество  элементов данных,  которое должно быть запомнено.
         Чем иметь дело с областями данных,  содержащими сотни переменных,
         программист может теперь иметь дело с областями данных,  содержа-
         щими небольшое количество данных.  Может  существовать  небольшое
         количество "узких" областей данных,  каждая из которых может быть
         проверена программой,  использующей ее, потому что каждая область
         безопасна только тогда,  когда есть уверенность, что другие прог-
         раммы не связаны с ней.  Любой из представленных способов для пов-
         торно-входимых программ служит для распределения временной локаль-
         ной памяти данных.
             Глобальные области данных, также известные как общие области,
         могут быть разбиты на модули. В этом случае вместо одной монолит-
         ной  области данных создается некоторое количество узких областей
         данных. После этого подпрограммы будут иметь дело только с такими
         участками глобальных данных, которые требуются для обработки. Это
         накладывает на часть программистов требование  быть внимательными
         и осторожными с директивами ASSUME в содержимом регистров сегмен-
         та,  но такая явная обработка общих данных к тому же делается чи-
         ще,  чем  доступ и затем изменение критических данных.  Например,
         общая область данных, содержащая строки текста и символьные конс-
         танты,  не нуждается в части подпрограмм вычисления чисел,  также
         как таблицы значений синуса и косинуса не нужны подпрограмме вво-
         да информации с терминала.
             В стек должно передаваться столько параметров,  сколько необ-
         ходимо  для  уменьшения количества внутренних обращений к данным.
         Всякий раз, когда несколько программ должны иметь доступ к облас-
         тям данных с целью передачи параметров, вероятность ошибки увели-
         чивается.
             Общие данные обычно должны быть определены с помощью директи-
         вы DEFINE DATA (определить данные) так,  чтобы содержимое области
         оставалось  без изменения и не было субъектом случайного удаления
         при ошибочном освобождении программой с помощью функции  "Освобо-
         дить распределенную память".

                          Использование регистров сегмента

             Регистры сегмента  позволяют программисту ограничивать диапа-
         зоны ссылок на данные. Путем изменения базы сегмента, содержащего
         данные,  архитектура  машины  автоматически вынуждает программу к
         "окну" доступа в 64 Кбайт.  Если более восприимчивые данные поме-
         щаются  в нижние  области памяти, то после того, как регистр сег-

                                      - 2-44 -
         мента изменится для указания на  высший  адресуемый  блок  памяти,
         данные в нижней области памяти будут полностью защищены от несанк-
         ционированного доступа.


                        Управление размером доступных данных

             Программист в дальнейшем может управлять размером окна данных
         путем установки bounds-checking (проверка границ)  в  массиве,  к
         которому осуществляется доступ.  Одна из наиболее типичных ошибок
         в данных происходит тогда, когда доступ к массиву выполняется че-
         рез его границы.  Все, что происходит на границе массива, теряет-
         ся. Проверка границы массива может быть выполнена с помощью прос-
         того  макроса,  как показано в листинге 2-14.  Для программистов,
         работающих с процессором 80x86, для выполнения этой проверки пре-
         дусмотрена инструкция BOUND (граница).  Для обеспечения совмести-
Предыдущая страница Следующая страница
1 ... 25 26 27 28 29 30 31  32 33 34 35 36 37 38 ... 198
Ваша оценка:
Комментарий:
  Подпись:
(Чтобы комментарии всегда подписывались Вашим именем, можете зарегистрироваться в Клубе читателей)
  Сайт:
 

Реклама