Копирование floppy диска на низком уровне используя расширеную память(asm)


Добавил:DMT
Дата создания:24 января 2008, 0:36
Дата обновления:25 апреля 2008, 14:13
Просмотров:6998 последний позавчера, 4:20
Комментариев: 1
Исследование памяти ПЭВМ.
изучение приемов работы с расширенной памятью в MS DOS

Теоретическое описание:

Использование драйвера HIMEM.SYS для программирования.
Спецификация XMS содержит описание программного интерфейса
драйвера HIMEM.SYS и рекомендации по использованию области памяти
НМА.

Проверка подключения драйвера.
Первое, что должна сделать программа, которая собирается вызывать
драйвер HIMEM.SYS, - проверить, был ли установлен этот драйвер при
загрузке операционной системы.
Для этого надо загрузить в регистр АХ значение 4300h и вызвать
прерывание INT 2Fh. Если регистр AL будет содержать значение 80h,
драйвер установлен, в противном случае - нет. Приведем фрагмент
программы, проверяющей подключение драйвера:

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

mov ax. 4300h
int 2fh
cmp aI, 80h
je hmm_installed; Выполняем переход, если драйвер установлен.

Получение адреса управляющей программы.
Для вызова драйвера программа должна получить адрес специальной
управляющей программы, которая выполняет все функции по обслуживанию
расширенной памяти и области НМА.
Этот адрес можно получить, если загрузить в регистр АХ значение
4310h и вызвать прерывание INT 2Fh. Прерывание возвратит адрес управляющей
программы в регистре ES, смещение - в регистре ВХ:

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

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

В дальнейшем полученный адрес используется для выполнения
функций по обслуживанию расширенной памяти. Программы, которые
обращаются к управляющей функции, должны перед вызовом функции
иметь размер стека не менее 256 байтов.

Описание функции драйвера HIMEM.SYS
Все функции драйвера HIMEM.SYS могут быть разделены на следующие
пять групп:
- функции получения информации о драйвере (0h);
- функции управления областью НМА (lh, 2h);
- функции управления линией А20 (3h...7h);
- функции управления расширенной памятью (8h,.Fh);
- функции управления блоками UMB (10h,.llh).
Приведем подробное описание этих функций в соответствии со
спецификацией XMS версии 2.0.

В программе использовались приведённые ниже функции драйвера
Himem.sys

Определение размера свободной расширенной памяти:
На входе: AH = 08h.
На выходе: AX = размер наибольшего свободного блока
расширенной памяти в килобайтах;
DX = общий размер свободной расширенной памяти в
килобайтах.
Ошибки: BL = 80h, 81h, AOh.
При определении размера свободной расширенной памяти в
возвращаемое значение не включается 64 килобайта области НМА, даже
если эта область не используется программами.

Получить блок ЕМВ
На входе: AH = 09h.
DX = размер требуемого блока в килобайтах.
На выходе: AX = 000lh - если функция выполнена успешно,
0000h - если произо 1e82 шла ошибка;
DX = 16-битовый индекс (handle) полученного блока ЕМВ.
Ошибки: BL = 80h, 81h, AOh, Alh.
Функция заказывает блок ЕМВ из пула свободной расширенной памяти.
При успешном выполнении запроса функция возвращает индекс
полученного блока, который должен использоваться программой для
выполнения всех операций с блоком ЕМВ. Если блок ЕМВ программе
больше не нужен, она должна освободить его с помощью функции OAh.
Количество блоков ЕМВ, которое может быть заказано, определяется в
командной строке драйвера H1MEM.SYS параметром /NUMHANDLES=.
Значение по умолчанию - 32, максимальное значение - 128.

Освободить блок ЕМВ
На входе: AH = 0Ah.
DX = 16-битовый индекс (handle) полученного блока EMB.
На выходе: AX = 000lh - если функция выполнена успешно,
0000h - если произошла ошибка.
Ошибки: BL = 80h, 81h, A2h, B2h.
Функция освобождает блок ЕМВ, заказанный предыдущей функцией. При
этом все данные, находившиеся в блоке, будут потеряны.

Копирование блоков ЕМВ
На входе: АН = Bh.
DS:SI = указатель на управляющую структуру, определяющую,
откуда, куда и как будет выполняться копирование.
На выходе: АХ = 000lh - если функция выполнена
успешно, 0000h - если произошла ошибка.
Ошибки: BL = 80h, 81h, 82h, A3h, A4h, A5h, A6h, A7h, A8h, A9h.

Управляющая структура:
ExtMemMoveStruct struct
Length dd ? ; количество посылаемых байтов
SourceHandle dw ? ; индекс исходного блока
SourceOffset dd ? ; смешение в исходном блоке
DestHandle dw ?; индекс блока назначения
DestOf-fset dd ? ; смещение блока назначения
ExtMemMoveStruct ends
Эта функция выполняет основную операцию с блоками ЕМВ -
копирование данных. Данные могут пересылаться между обычной
памятью и блоками ЕМВ, между различными блоками ЕМВ и даже внутри
обычной памяти.
Поле Length управляющей структуры указывает количество
пересылаемых байтов. Это количество должно быть четным.
Поля SourceHandle и DestHandle указывают соответственно
индексы исходного и результирующего блоков ЕМВ. Если в качестве
индекса задано значение 0000h, это означает, что в качестве
источника или приемника данных используется обычная память.
Поля SourceOffset и DestOffset указывают 32-битовое смещение в
блоке ЕМВ или адрес в обычной памяти. В последнем случае этот
адрес имеет стандартный формат сегмент: смещение.
Функция копирования сама управляет линией А20, восстанавливая ее
состояние после выполнения копирования. Поэтому программе не
требуется управлять линией А20.
Во время выполнения копирования разрешены прерывания.

Исходный текст программы:

Код на ASM
  1. .286
  2. .model small
  3.  
  4. .data
  5. buf db 32770 dup(0)
  6. ndrv db 0
  7. sec dw 0
  8. nsec dw 0
  9. handle dw 0
  10.  
  11. LenBlk dd 32768
  12. SrcHdl dw 0
  13. SrcOff dd 0
  14. DstHdl dw 0
  15. DstOff dd 0
  16.  
  17. HMMEntry dd 0
  18.  
  19. mes1 db 'Программа копирование floppy дисков', 10, 13, '$'
  20. mes2 db 'Драйвер himem.sys не установлен!', 10, 13, '$'
  21. mes3 db 'Ошибка обращения к диску!', 10, 13, '$'
  22. mes4 db 'Ошибка при работе с линией А20!', 10, 13, '$'
  23. mes5 db 'Нет свободной памяти!', 10, 13, '$'
  24. mes6 db 'Копируется диск исходник...', 10, 13, '$'
  25. mes7 db 'Ошибка при работе с расширенной памятью!', 10, 13, '$'
  26. mes8 db 'Вставьте диск приемник...', 10, 13, '$'
  27. mes9 db 'Идет запись на диск...', 10, 13, '$'
  28. mes10 db 'Ошибка при записи диска!', 10, 13, '$'
  29. mes11 db '000% $'
  30. mes12 db 'прочитано', 13, '$'
  31. mes13 db 'записано', 13, '$'
  32. mes99 db 'Диск успешно скопирован!', 10, 13, '$'
  33. mes14 db '', 10, 13, '$'
  34.  
  35. .code
  36. start: mov ax, @data
  37. mov ds, ax
  38. ; проверка наличия himem.sys
  39. mov ax, 4300h
  40. int 2fh
  41. cmp al, 80h
  42. je s1
  43. mov dx, offset mes2 ;Драйвер himem.sys не установлен
  44. jmp error
  45. ; получение адреса программы управления XMS
  46. s1: mov ax, 4310h
  47. int 2fh
  48. mov word ptr [HMMEntry][0], bx
  49. mov word ptr [HMMEntry][2], es
  50. ; считывание корневого сектора дискеты
  51. mov al, ndrv
  52. mov cx, 1
  53. xor dx, dx
  54. mov bx, offset buf
  55. int 25h
  56. pop ax
  57. jnb s2
  58. mov dx, offset mes3 ;Ошибка обращения к диску
  59. jmp error
  60.  
  61. s2: mov ax, word ptr [bx][13h]
  62. mov sec, ax
  63. ; локальное открывание линии A20
  64. mov ah, 05h
  65. call HMMEntry
  66. or ax, ax
  67. jnz s3
  68. mov dx, offset mes4 ;Ошибка при работе с линией А20
  69. jmp error
  70.  
  71. s3: mov ah, 08h
  72. call HMMEntry
  73. cmp ax, 1500
  74. jae s4
  75. mov dx, offset mes5 ;Нет свободной памяти
  76. jmp error
  77. ; запрос блока памяти
  78. s4: mov ah, 09h
  79. mov dx, 1500
  80. call HMMEntry
  81. or ax, ax
  82. jnz s5
  83. mov dx, offset mes5 ;Нет свободной памяти
  84. jmp error
  85. ; первоначальное заполнение таблицы для копирования
  86. s5: mov handle, dx
  87. mov bx, offset buf
  88. mov word ptr SrcOff[0], bx
  89. mov word ptr SrcOff[2], ds
  90. mov bx, handle
  91. mov DstHdl, bx
  92. mov word ptr DstOff[0], 0
  93. mov word ptr DstOff[2], 0
  94.  
  95. mov dx, offset mes6 ;Копируется диск исходник...
  96. mov ah, 09h
  97. int 21h
  98.  
  99. mov si, offset LenBlk
  100. xor cx, cx
  101. ; считывание группы секторов
  102. nexts: push cx
  103. mov al, ndrv
  104. mov dx, nsec
  105. mov cx, 64
  106. mov bx, offset buf
  107. int 25h
  108. pop ax
  109. jnc s6
  110. mov dx, offset mes3 ;Ошибка обращения к диску
  111. jmp err1
  112. ; копирование блока памяти в EMB
  113. s6: mov dx, offset mes12 ;прочитано
  114. call OutPer
  115. add nsec, 64
  116.  
  117. mov ah, 0bh ;ф-ия 0B - копирование блока
  118. call HMMEntry ;вызов драйвера
  119. or ax, ax ;проверка на ошибку
  120. jnz s7
  121. mov dx, offset mes7 ;Ошибка при работе с расширенной памятью
  122. jmp err1
  123.  
  124. s7: add word ptr DstOff[0], 32768 ;увеличение текущего смещения в EMB
  125. adc word ptr DstOff[2], 0 ;прибавляем 32кб в первое слово и 0 - во второе
  126.  
  127. pop cx
  128. add cx, 64
  129. cmp cx, sec
  130. jne nexts
  131.  
  132. mov ah, 09h ;вывод на экран сообщения
  133. mov dx, offset mes8 ;Вставьте диск приемник
  134. int 21h
  135. ; ожидание нажатия клавиши
  136. mov ah, 08h
  137. int 21h
  138.  
  139. mov nsec, 0
  140. mov DstHdl, 0
  141. mov bx, offset buf
  142. mov word ptr DstOff[0], bx
  143. mov word ptr DstOff[2], ds
  144. mov bx, handle
  145. mov SrcHdl, bx
  146. mov word ptr SrcOff[0], 0
  147. mov word ptr SrcOff[2], 0
  148.  
  149. mov ah, 09h
  150. mov dx, offset mes9 ;Идет запись на диск
  151. int 21h
  152.  
  153. mov si, offset LenBlk ;32768
  154. xor cx, cx
  155. ; копирование блока из EMB в память
  156. nextc: mov ah, 0bh
  157. call HMMEntry
  158. or ax, ax
  159. jnz s8
  160. mov dx, offset mes7 ;Ошибка при работе с расширенной памятью
  161. jmp err1
  162.  
  163. s8: add word ptr SrcOff[0], 32768
  164. adc word ptr SrcOff[2], 0
  165. push cx
  166. ; запись группы секторов на диск
  167. mov al, ndrv
  168. mov dx, nsec
  169. mov cx, 64
  170. mov bx, offset buf
  171. int 26h
  172. pop ax
  173. jnc s9
  174. mov dx, offset mes10 ;Ошибка при записи диска
  175. jmp err1
  176.  
  177. s9: mov dx, offset mes13 ;записано
  178. call OutPer
  179. add nsec, 64
  180. pop cx
  181. add cx, 64
  182. cmp cx, sec
  183. jne nextc
  184. mov dx, offset mes99 ;Диск успешно скопирован
  185.  
  186. err1: push dx ; освобождение блока памяти
  187. mov ah, 0ah
  188. mov dx, handle
  189. call HMMEntry
  190. pop dx
  191. or ax, ax
  192. jnz s10
  193. mov dx, offset mes7 ;Ошибка при работе с расширенной памятью
  194. jmp error
  195. s10: mov ah, 06h ; локальное закрывание линии A20
  196. call HMMEntry
  197.  
  198. error: mov ah, 09h
  199. int 21h
  200. mov ax, 4c00h
  201. int 21h
  202. ; вывод результатов копирования(записи) в процентах
  203. OutPer proc near
  204. pusha
  205. mov ax, sec
  206. mov bl, 100
  207. div bl
  208. mov bl, al
  209. mov ax, nsec
  210. div bl
  211. mov cx, 3
  212. mov di, 2
  213. mov bx, offset mes11 ;000%
  214. mov dl, 10
  215.  
  216. o10: xor ah, ah
  217. div dl
  218. add ah, 30h
  219. mov byte ptr [bx][di], ah
  220. dec di
  221. loop o10
  222. mov ah, 09h
  223. mov dx, offset mes11 ;000%
  224. int 21h
  225. popa
  226. mov ah, 09h
  227. int 21h
  228. ret
  229. OutPer endp
  230.  
  231. .stack
  232. db 100h dup(?)
  233. end start
При использовании обязательна ссылка на http://DMTSoft.ru
Копирование всех файлов дискеты в память
Код на C++
  1. #include <iostream.h>
  2. #include <dos.h>
  3. #include <sys\stat.h>
  4. #include <fcntl.h>
  5. #include <io.h>
  6. #include <stdio.h>
  7. #include <conio.h>
  8. #include <windows.h>
  9. #define MEGA_BYTE 1048576
  10. unsigned long i=0; // счетчик считанных байтов
  11. unsigned long sum=0; //контрольная сумма
  12. //возвращает сумму байтов в массиве
  13. unsigned long SumByte(char *p,unsigned long i)
  14. {
  15. unsigned long s=0;
  16. p--;
  17. for(unsigned long j=i;j>0;j--,p--)
  18. {
  19. unsigned int b=*p;
  20. s+=b;
  21. }
  22. return s;
  23. }
  24. //копируе файл в память по заданному адресу
  25. char *CopyFileInMem(char *p,char *name,unsigned long size)
  26. {
  27. FILE *in;
  28. int handle;
  29. if ((handle =
  30. open(name, O_RDONLY | O_BINARY, S_IWRITE | S_IREAD)) == -1)
  31. {
  32. printf("Error Opening File\n");
  33. exit(1);
  34. }
  35. //выделяем зарезервировнную область
  36. VirtualAlloc(p,size,MEM_COMMIT,PAGE_READWRITE);
  37. int s=read(handle,p,size);//считываем весь файл в буфер
  38. p+=s;
  39. i+=s;
  40. close(handle);
  41. return p;
  42. }
  43. //копирует всю дискету в память по заданному адресу
  44. char *CopyA_InMem(char *p)
  45. {
  46. struct ffblk ffblk;//структура найденого файла в текущем каталоге
  47. if(findfirst("*.*",&ffblk,16)==-1)return p;
  48. if(strcmp(ffblk.ff_name,".")!=0&&strcmp(ffblk.ff_name,".."))
  49. if(!(ffblk.ff_attrib&FA_DIREC))
  50. { //если это файл то копируем его в память
  51. p=CopyFileInMem(p,ffblk.ff_name,ffblk.ff_fsize);
  52. }
  53. else
  54. { //если это каталог то меняем директорию
  55. chdir(ffblk.ff_name);
  56. p=CopyA_InMem(p);
  57. //возврат в предыдущий каталог
  58. chdir("..");
  59. }
  60. while(findnext(&ffblk)!=-1)
  61. if(strcmp(ffblk.ff_name,".")!=0&&strcmp(ffblk.ff_name,".."))
  62. if(!(ffblk.ff_attrib&FA_DIREC))
  63. {
  64. p=CopyFileInMem(p,ffblk.ff_name,ffblk.ff_fsize);
  65. }
  66. else
  67. {
  68. chdir(ffblk.ff_name);
  69. p=CopyA_InMem(p);
  70. chdir("..");
  71. }
  72. return p;
  73. }
  74. //---------------------------------------------------------------------------
  75. #pragma argsused
  76. int main(int argc, char **argv)
  77. {
  78. //резервирование памяти в 30 мегабайт для чтения и записи
  79. char *p=(char *)VirtualAlloc(NULL,30*MEGA_BYTE,MEM_RESERVE,PAGE_READWRITE);
  80. char C;
  81. cout<<"Input first disk (Yes/No):";
  82. C=getch();
  83. fputc(C,stdout);
  84. int j=2;
  85. if(C=='y')
  86. do{
  87. setdisk(0);
  88. p=CopyA_InMem(p);
  89. //предлагается вставить следующую дискету
  90. cout<<"\nInput next disk "<<j<<"(Yes/No):";
  91. C=getch();
  92. fputc(C,stdout);
  93. j++;
  94. }while(C=='y'&&j<20);
  95. sum=SumByte(p,i);//конторольная сумма считанных байт
  96. //освобождаем память
  97. VirtualFree(p,30*MEGA_BYTE,MEM_DECOMMIT);
  98. cout<<"\nControl sum:"<<sum<<" i="<<i;
  99. getch();
  100. return 0;
  101. }
При использовании обязательна ссылка на http://DMTSoft.ru
up

Комментарии для "Копирование floppy диска на низком уровне используя расширеную память(asm)"


Пользователь: sam
Сообщений: 4
Статус: Пользователь
Зарегистрирован:
9 января 2009, 19:13
Был:12 января 2009, 3:16
sam
smsup
Дата: 11 января 2009, 16:38 Сообщение № 1
Почему выводится сообщение о нехватки памяти?
; копирование блока из EMB в память
nextc: mov ah, 0bh
call HMMEntry
or ax, ax
jnz s8
mov dx, offset mes7 ;Ошибка при работе с расширенной памятью
jmp err1
Что помещается в ах?