Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Архитектура ЭВМ и систем. Лабораторная работа. Учебное пособие

.pdf
Скачиваний:
0
Добавлен:
06.09.2026
Размер:
1 Мб
Скачать
Комментарии
При вызове регистр ES указывает на начало блока памяти, воз­вращаемого в системный пул. В процессе выполнения функции этот блок памяти возвращается в системный пул. Код ошибки возвраща­ется в регистре AX.
Функция 4AH, прерывание 21H: Изменить размер
выделенного ранее блока
Назначение
Освобождает указанный блок выделенной памяти.
При вызове Содержимое регистров
AH 4AH ES Сегментная часть адреса блока BX Новый размер блока памяти в параграфах
После завершения
AX Код ошибки, если установлен флаг переноса BX Размер наибольшего доступного блока памяти (в пара-
Содержимое регистров
графах), если изменение размера блока памяти не вы­полнено и установлен флаг переноса
Комментарии
ДОС пытается увеличить или уменьшить размер блока памяти. Код ошибки возвращается в регистре AX.
Пример программы прямого доступа к памяти
Программа, листинг которой приведен ниже, выводит на экран список всех блоков памяти, указывания для каждого имя и адрес PSP программы-владельца, тип, адрес и размер в байтах. Результаты ее работы
приведены на рисунке 2.
"Программа Тип Адрес Размер PSP $"
;строка таблицы table_row label near db 0DH, 0AH
81
prog_name db 10 dup(' ') block_type db 4 dup(' ') block_addr db 12 dup(' ') block_size db 8 dup(' ') psp_addr db 5 dup(' ') tr_len = $-prog_name
db '$' ;длина строки таблицы end_of_line db 0DH, 0AH, '$' ;буфер для размещения числа перед переводом его в десятичный формат number dw 0,0 ;таблица перевода в шестнадцатеричный формат xt db "01234567890ABCDEF" dseg ends cseg segment para use16 assume cs:cseg,ds:dseg,ss:sseg start proc far
;сделаем данные адресуемыми
mov ax,dseg
mov ds,ax
;получим адрес списка списков DOS
mov ah,52H
int 21H
;es <- сегментный адрес первого MCB
mov es,es:[bx-2]
;выведем заголовок таблицы
mov ah,9
lea dx,table_header
int 21H next_mcb:
;очистим буфер со строкой таблицы
call clear_row
;владелец -- система
? cmp word ptr es:[1],8 je get_name ;блок свободен? cmp word ptr es:[1],0 je get_info
82
;это программный сегмент(MCB должен
быть прямо перед PSP)?
mov ax,es inc ax cmp ax,es:[1] je get_name ;найдем MCB перед программным
сегментом push es mov ax,es:[1] dec ax mov es,ax ;получим имя программы из MCB перед
ее программным сегментом call get_prog_name pop es jmp short get_info
get_name:
;получим имя программы call get_prog_name
get_info:
call get_mcb_info ;выведем очередную строку mov ah,9 lea dx,table_row int 21H
;это еще не последний блок? cmp byte ptr es:[0],'M' jne last_mcb ;перейдем к следующему MCB mov ax,es add ax,es:[3] inc ax mov es,ax jmp next_mcb
last_mcb:
;переведем курсор на две строки
вниз
83
mov ah,9 lea dx,end_of_line int 21H int 21H ;выйдем из программы mov ax,4C00H int 21H
start endp ;помещаем в буфер строки таблицы информацию по блоку MCB, адрес ;которого находится в ES get_mcb_info proc near
;скопируем тип блока mov al,es:[0] mov [block_type],al
;преобразуем адрес блока памяти lea di,block_addr ;сегментный адрес у него на 1
больше, чем у MCB mov dx,es inc dx call bin_to_hex ;поместим в буфер разделитель ':' mov byte ptr [di],':' inc di ;смещение нулевой -- граница
параграфа xor dx,dx call bin_to_hex
;
размер блока памяти задается в
параграфах,
;мы будем выводить его в байтах xor eax,eax mov ax,es:[3] shl eax,4 lea di,psp_addr-2
84
call bin_to_dec ;преобразуем адрес PSP владель-
ца блока памяти lea di,psp_addr mov dx,es:[1] call bin_to_hex ret
get_mcb_info endp ;переводит число из eax в десятичный формат и помещает в буфер, ;на конец которого указывает пара ds:di bin_to_dec proc near
mov ecx,10
next__digit:
xor edx,edx div ecx or dl,30H mov [di],dl dec di or eax,eax jnz next__digit ret
bin_to_dec endp ;переводит число из dx в шестнадцатеричный формат и помещает ;в буфер по адресу ds:di bin_to_hex proc near
lea bx,xt mov cx,4
next_digit:
mov al,dh shr al,4 shl dx,4 and al,0FH xlatb mov [di],al inc di loop next_digit mov byte ptr [di],'H'
85
inc di ret
bin_to_hex endp ;заполняет буфер для строки таблицы пробелами clear_row proc near
push es push ds pop es lea di,prog_name mov cx,tr_len mov al,' ' cld rep stosb pop es ret
clear_row endp ;копирует имя программы в буфер строки таблицы ;из MCB, на который указывает ES get_prog_name proc near
;смещение имени в MCB mov di,8 ;место для имени в буфере lea si,prog_name
next_symbol:
;переместим очередной символ mov al,es:[di] mov [si],al ;увеличим индексы inc si inc di ;нулевой символ -- конец имени? or al,al jz finish ;максимальная длина имени -- 8
байт cmp di,16 jne next_symbol
finish:
ret
86
get_prog_name endp cseg ends sseg segment para stack
dw 1024 dup(?)
sseg ends
end start
Программа Тип Адрес Размер PSP SD M 0217H:0000H 9904 0008H COMMAND M 0483H:0000H 2592 0483H M 0526H:0000H 112 0000H COMMAND M 052DH:0000H 1776 0483H NC M 059DH:0000H 1792 078CH KB16 M 060EH:0000H 6096 060EH NC M 078CH:0000H 7152 078CH COMMAND M 094CH:0000H 1808 09AEH COMMAND M 09AEH:0000H 2592 09AEH COMMAND M 0062H:0000H 1776 09AEH MCB M 00C2H:0000H 1808 0A44H MCB Z 0A44H:0000H 609200 0A44H
Рис. 2. Пример карты распределения оперативной памяти
Пример программы, работающей с оперативной памятью
посредством системных вызовов
Программа, листинг которой приведен ниже, рисует звездочка-
ми на экране зеленую ёлочку. Изображение формируется в буфере, полученном у операционной системы. Затем оно копируется в ви­деопамять. Результат ее работы можно видеть на рисунке 3.
; .486 LOCALS
;ширина и высота и цвет изображения fir_width = 11
программа рисования ёлочки на экране
87
fir_height = 12 fir_color = 00001010B dseg segment para use16 ;количество звездочек на разных уровнях елочки levels db 1,3,5,3,5,7,5,7,9,1,1,5 ;сообщения об ошибках err_ma db 0DH,0AH, «Ошибка выделения памя-
ти.», 0DH,0AH, "$"
err_msch db 0DH,0AH, «Ошибка изменения раз-
мера программного сегмента.», 0DH,0AH, "$"
err_frm db 0DH,0AH, «Ошибка освобождения
памяти.», 0DH,0AH, "$" dseg ends cseg segment para use16
assume cs:cseg, ds:dseg, ss:sseg
start proc far
;сделаем сегмент данных адресуемым mov ax,dseg mov ds,ax ;определим, какой размер в параг-
рафах программа
;в действительности занимает в па-
мяти ;начало программного сегмента mov bx,es ;отнимем адрес конца программы в
памяти sub bx,last_seg ;получим положительное значение neg bx ;уменьшим размер занимаемой опера-
тивной памяти ;до необходимого mov ah,4AH int 21H jnc memsch_ok ;выведем сообщение об ошибке mov ah,9
88
lea dx,err_msch int 21H
memsch_ok:
;выделим буфер под изображение ;определим размер буфера в параг-
рафах mov bx,fir_width*fir_height*2 add bx,000FH shr bx,4 mov ah,48H int 21H jnc ma_ok ;выведем сообщение об ошибке mov ah,9 lea dx,err_ma int 21H jmp finish
ma_ok:
;регистр es будет указывать ;на полученный буфер mov es,ax ;сформируем изображение в буфере xor si,si mov ah,fir_color xor di,di xor ch,ch cld
draw_level:
;вычислим, сколько на данном уровне ;пробелов слева и справа от ёлки mov cl,fir_width sub cl,levels[si] shr cl,1 push cx ;фон слева mov al,' '
draw_lb:
jcxz fir stosw
89
dec cx jmp draw_lb
fir:
;ёлка mov al,'*' mov cl,levels[si]
draw_fir:
jcxz rb stosw dec cx jmp draw_fir
rb:
;фон слева pop cx mov al,' '
draw_rb:
jcxz next_level stosw dec cx jmp draw_rb
next_level:
;перейдем к следующему уровню inc si ;дошли до последнего? cmp si,fir_height jb draw_level
;выведем изображение на экран push ds push es ;ds <-буфер с изображением push es pop ds ;es <- видеобуфер push 0B800H pop es
xor si,si mov di,(25-fir_height)/2*80*2 mov cx,fir_height
90
Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]