include sysp.inc

ExtMemMoveStruct  struc

 @Length      dd ?  ; количество пересылаемых байтов
 SourceHandle dw ? ; индекс исходного блока
 SourceOffset dd ? ; смещение в исходном блоке
 DestHandle  dw ?  ; индекс блока-назначения
 DestOffset  dd ?  ; смещение в блокe

ExtMemMoveStruct  ends


	.MODEL  tiny

	DOSSEG
	.STACK  100h

	.DATA

movestr ExtMemMoveStruct <0,0,0,0,0>

msg DB 13,10,"Использование блоков EMB", 13, 10
	 DB  "Copyright (C)Frolov A.,1991",13,10,13,10
	 DB "$"

noHMM    DB 13,10,"Драйвер HIMEM.SYS не установлен",13,10,"$"
yesHMM   DB 13,10,"Драйвер HIMEM.SYS установлен, ","$"
errmsg   DB 13,10,"Ошибка с кодом ", "$"
okmsg    DB 13,10,"Успех!!!", "$"
free_ext_mem DB 13,10,"Всего расширенной памяти, Кбайт: ","$"
max_ext_block DB 13,10,"Максимальный участок свободной"
				  DB " расширенной памяти, Кбайт: ", "$"
getEMBmsg  DB 13,10,"Получаем блок EMB","$"
freeEMBmsg DB 13,10,"Освобождаем блок EMB","$"

copymsg    DB 13,10,"Копируем блок данных в область EMB","$"
copymsg1   DB 13,10,"Копируем блок данных обратно","$"

testmsg DB 13,10,13,10,"Сообщение для копирования"
		  DB " в область EMB","$"

len_testmsg DW $-testmsg

; Буфер для копирования сообщения

testbuf DB 512 dup(?)

HMMEntry dd ?

EMBHandle dw ?

	.CODE
	.STARTUP

	mov     ah, 9h                ; Выводим заголовок
	mov     dx, OFFSET msg
	int     21h

; Проверяем, установлен ли драйвер HIMEM.SYS

	mov   ax, 4300h
	int   2fh
	cmp   al, 80h
	je    HMM_installed

; Если не установлен, выводим сообщение и завершаем
; работу программы

	mov   ah, 9h
	mov   dx, OFFSET noHMM
	int   21h

	jmp   terminate

HMM_installed:

	mov   ah, 9h
	mov   dx, OFFSET yesHMM
	int   21h

; Получаем адрес управляющей функции драйвера

	mov   ax, 4310h
	int   2fh
	mov   word ptr cs:[HMMEntry][0], bx
	mov   word ptr cs:[HMMEntry][2], es

; Определяем размер свободной расширенной памяти

	mov   ah, 9h
	mov   dx, OFFSET free_ext_mem
	int   21h

	mov   ax,0800h

	call  cs:[HMMEntry]

	push  ax
	mov   ax, dx
	call  Print_word

	mov   ah, 9h
	mov   dx, OFFSET max_ext_block
	int   21h

	pop   ax
	call  Print_word

; Получаем блок EMB

	mov   ah, 9h
	mov   dx, OFFSET getEMBmsg
	int   21h

	mov   ax,0900h
	mov   dx,1h

	call  cs:[HMMEntry]
	or    ax, ax
	jnz   getemb_ok
	jmp   error

getemb_ok:

	mov   EMBHandle, dx

	mov   ah, 9h
	mov   dx, OFFSET okmsg
	int   21h

; Копируем строку testmsg в блок EMB

	mov   ah, 9h
	mov   dx, OFFSET copymsg
	int   21h

; Заполняем управляющую структуру

; Длина копируемого массива памяти

	mov   ax, word ptr len_testmsg
	mov   word ptr movestr.@Length, ax

; Индекс основной памяти, должен быть = 0

	mov   ax, 0
	mov   word ptr movestr.SourceHandle, ax

; Задаем сегмент:смещение копируемого сообщения

	mov   ax, OFFSET testmsg
	mov   word ptr [movestr.SourceOffset][0], ax
	mov   ax, cs
	mov   word ptr [movestr.SourceOffset][2], ax

; Задаем индекс EMB, в который будем копировать
; сообщение из основной памяти

	mov   ax, EMBHandle
	mov   movestr.DestHandle, ax

; Копируем в начало EMB, поэтому
; смещение = 0

	mov   ax, 0
	mov   word ptr [movestr.DestOffset][0], ax
	mov   word ptr [movestr.DestOffset][2], ax

; Загружаем адрес управляющей структуры в DS:SI

	mov   ax, cs
	mov   ds, ax
	mov   ax, OFFSET movestr
	mov   si, ax
	mov   ax,0B00h

; Вызываем функцию копирования

	call  cs:[HMMEntry]
	or    ax, ax
	jnz   moveemb_ok
	jmp   error

moveemb_ok:

	mov   ah, 9h
	mov   dx, OFFSET okmsg
	int   21h

; Копируем сообщение обратно из блока EMB
; в буфер testbuf, расположенный в основной
; памяти

	mov   ah, 9h
	mov   dx, OFFSET copymsg1
	int   21h


; Подготавливаем управляющую структуру

	mov   ax, word ptr len_testmsg
	mov   word ptr movestr.@Length, ax

	mov   ax, 0
	mov   word ptr movestr.DestHandle, ax

	mov   ax, OFFSET testbuf
	mov   word ptr [movestr.DestOffset][0], ax
	mov   ax, cs
	mov   word ptr [movestr.DestOffset][2], ax

	mov   ax, EMBHandle
	mov   movestr.SourceHandle, ax

	mov   ax, 0
	mov   word ptr [movestr.SourceOffset][0], ax
	mov   word ptr [movestr.SourceOffset][2], ax

; Выполняем копирование

	mov   ax, cs
	mov   ds, ax
	mov   ax, OFFSET movestr
	mov   si, ax
	mov   ax,0B00h

	call  cs:[HMMEntry]
	or    ax, ax
	jnz   move1emb_ok
	jmp   error

move1emb_ok:

	mov   ah, 9h
	mov   dx, OFFSET okmsg
	int   21h

; Выводим скопированное сообщение на экран
; для проверки

	mov   ah, 9h
	mov   dx, OFFSET testbuf
	int   21h

; Освобождаем блок EMB

	mov   ah, 9h
	mov   dx, OFFSET freeEMBmsg
	int   21h

	mov   ax,0A00h
	mov   dx,EMBHandle

	call  cs:[HMMEntry]
	or    ax, ax
	jnz   freeemb_ok
	jmp   error

freeemb_ok:

	mov   EMBHandle, dx

	mov   ah, 9h
	mov   dx, OFFSET okmsg
	int   21h

	jmp   terminate

error:
	push  bx

	mov   ah, 9h
	mov   dx, OFFSET errmsg
	int   21h

	pop   ax
	call  Print_word


terminate:

	.EXIT   0


; Вывод на экран содержимого регистра AX

Print_word proc near
;--------------------
	  push ax
	  push bx
	  push dx
;
	  push ax
	  mov cl,8
	  rol ax,cl
	  call Byte_to_hex
	  mov bx,dx
	  @@out_ch bh
	  @@out_ch bl
;
	  pop ax
	  call Byte_to_hex
	  mov bx,dx
	  @@out_ch bh
	  @@out_ch bl
;
	  pop dx
	  pop bx
	  pop ax
	  ret
Print_word endp
;
Byte_to_hex proc near
;--------------------
; al - input byte
; dx - output hex
;--------------------
	  push ds
	  push cx
	  push bx
;
	  lea bx,tabl
	  mov dx,cs
	  mov ds,dx
;
	  push ax
	  and al,0fh
	  xlat
	  mov dl,al
;
	  pop ax
	  mov cl,4
	  shr al,cl
	  xlat
	  mov dh,al
;
	  pop bx
	  pop cx
	  pop ds
	  ret
;
tabl db '0123456789ABCDEF'
Byte_to_hex endp

		  END
