Оперативная память

         

Для выполнения задачи не хватает



Пример Б.З. Вычисление значений переменных SwpSeg и GenSeg 1

.Alpha порядок расположения сегментов
Dosseg порядок расположения сегментов
stack Segment word stac : "stack" ; начало стекового сегмента
db 200h dup (?) размер области стека 200h байтов
stack Ends конец стекового сегмента
data Segment начало сегмента данных
prmpt db ODh,OAh, ' ! Для выполнения задачи не хватает памяти ! $ '
freeseg dw 0 первый свободный сегмент
msize dw 0 размер памяти в параграфах
needm dw 2000h требуемый размер памяти
SwpOffs dw 0 смещение в буфере обмена
SwpSeg dw 0 сегмент буфера обмена
GenOffs dw 0 смещение в буфере
GenSeg dw 0 сегмент буфера общего назначения
; Далее описываются другие используемые данные


data Ends конец сегмента данных
code Segment начало кодового сегмента
.386 набор команд процессора
start : mov ax, data ах = код сегмента данных
mov ds, ax ds = код сегмента данных
mov bx , sp bx = размер стека в байтах
shr bx, 04 превращаем его в параграфы
mov ax, ss ах = код стекового сегмента
add bx, ax bx = последний параграф стека
inc bx bx = первый свободный сегмент
mov freeseg, bx ireeseg = DX
mov ax, es: [02] ax = последний доступный сегмент
sub ax, bx ax = ax — bx
mov msize, ax размер памяти в параграфах
cmp ax, needm памяти достаточно ?
jae @F -> да
lea dx, prmpt dx = адрес аварийного сообщения
mov ah, 09 ah = код функции DOS
int 21h вывод текста сообщения
mov ax, 4COOh ah = 4С, код функции DOS
int 21h завершение выполнения задачи
@@: mov SwpSeg, bx SwpSeg = bx
add bx, lOOOh bx = bx + 65536/16
mov GenSeg, bx GenSeg = bx
; Далее расположен текст основной программы и подпрограмм
code Ends конец кодового сегмента
END start конец текста программы

В начале примера Б.З подряд расположены директивы .Alpha и Dosseg. При таком их сочетании стековый сегмент будет расположен в теле задачи последним, независимо от имен других сегментов (по крайней мере, так его располагает MASM 5.1).

Директива .386 определяет набор команд, которые можно использовать в программе. Если ее не указать, то по умолчанию будет выбран набор команд микропроцессора Intel 8086. В таком случае Макроассемблер обнаружит ошибку в записи команды shr bx, 04. Подробнее о назначении и месте расположения этой директивы сказано в приложении В.

После загрузки задачи DOS передает управление на метку start, для этого ее имя указано не только перед первой командой, но и после директивы END. Первые две команды записывают в регистр ds код сегмента данных, этот вопрос мы уже обсуждали. Шесть следующих команд вычисляют в регистре bx код первого свободного сегмента и сохраняют его в переменной freeseg. Затем в регистр ах считывается из 2-го слова PSP код последнего доступного для задачи сегмента, вычисляется размер свободной памяти в параграфах и сохраняется в переменной msize.

Реальный размер памяти сравнивается с необходимым (needm), и если он достаточен для выполнения задачи, то произойдет переход на локачьную метку @@. В противном случае на экран будет выведено аварийное сообщение и прекратится выполнение задачи. Способы вывода текстовых сообщений описаны в разделе основной части книги, а завершение выполнения задачи описано в разделе .

Если памяти достаточно, то в переменную SwpSeg копируется код первого доступного сегмента. Для буфера обмена отведено 65 536 байтов, что в параграфах составляет 1000h. Эта величина прибавляется к содержимому регистра bx, и результат записывается в GenSeg. Значения переменных swpoffs и GenOffs определяются в процессе выполнения задачи.

После выполнения команд примера Б.З размер буфера обмена ограничен, поскольку после него расположен буфер общего назначения, поэтому при работе с swpSeg нельзя выходить за пределы 65 536 байтов. Во всех ранее приведенных примерах такое ограничение нас вполне устраивало. Размер буфера общего назначения пока ограничен величиной (msize - ioooh)*16 байтов. В зависимости от конкретных особенностей задачи это пространство может быть разделено на блоки меньшего размера или использовано как большой буфер общего назначения.

При работе с блоками большого размера задача должна контролировать текущий адрес ОЗУ и при достижении границы 65 536 байтов изменять код в сегментном регистре, который используется для доступа к блоку (увеличивать его содержимое на 1000h). Необходимость работы с блоками ОЗУ большого размера возникает, например, при сохранении и восстановлении содержимого всей рабочей области экрана.

Мы описали простой пример размещения блоков в ОЗУ. Для выполнения более сложных функций, связанных с распределением памяти в текст задачи, придется включать специальные подпрограммы и поддерживать структуру данных, описывающих свободное и использованное пространство ОЗУ. Альтернативой является обращение к DOS для выполнения действий, связанных с распределением простраж тва оперативной памяти.

 


Содержание раздела