Добрый день! Возникла проблема при написании программы чтения первого сектора жесткого диска в режиме DMA. Отправной точкой послужила статья http://www.wasm.ru/print.php?article=atazen02. Но мне необходимо было сделать проверку того, что передача закончилась в обработчике прерывания. Посадил я этот обработчик на int76h. В результате программа намертво зависает после запуска. Вот код: Код (Text): .386 ; Создаем таблицу PRDT из одной записи data segment use16 PRD_ADDR dd 0 PRD_COUNT dw 0 PRD_FLAG dw 0 BUFFER db 512 dup (0),'$' Old_Int dw 0,0 BlockReg dw 0 CPUtest db 'CPU test',13,10,'$' data ends ; Базовый адрес регистров контроллера первого канала BASE equ 1F0h stck segment stack use16 dw 1024 dup (?) stck ends code segment use16 assume cs:code,ss:stck,ds:data ;################################################ ;#Процедура определяющая адрес регистров PCI IDE# ;#с помощью функций PCI BIOS # ;################################################ PCI_DETECT PROC NEAR push esi push edi mov si,0 mov ecx,010180h try: mov ax,0B103h int 1Ah jnc next add ecx,5 jmp try next: mov ax,0B10Ah mov di,20h int 1Ah and cx,0FFF0h pop edi pop esi ret PCI_DETECT ENDP ;################################################### ;Считывание первого сектора ЖД в режиме DMA в буфер# ;Входные параметры # ;EDI[31:0] - указатель на PRDT # ;ESI[27:0] - LBA адрес # ;ESI[28] - Устройство (0 - Master, 1 - Slave) # ;################################################### READ_DMA PROC NEAR mov dx, BASE + 206h ;Разрешаем прерывания mov al, 0 out dx, al mov dx, BASE+7 ;Ждем BSY=0 BSY: in al, dx test al, 80h jnz BSY mov eax, esi ;Выбираем устройство и загружаем старшие разряды адреса shr eax, 24 or al, 0E0h mov dx, BASE+6 out dx, al mov dx, BASE+7 ;Ждем BSY=0 и DRDY=1 BSY_DRDY: in al, dx test al, 80h jnz BSY_DRDY test al, 40h jz BSY_DRDY mov eax, esi ;Загружаем LBA адрес mov dx, BASE+3 out dx, al shr eax, 8 inc dx out dx, al shr eax, 8 inc dx out dx, al mov dx, BASE+2 ; Количество секторов = 1 mov al, 1 out dx, al call PCI_DETECT ;В CX адрес блока регистров PCI IDE mov [BlockReg], cx call InitIRQ mov dx,cx ;Указатель на таблицу PRDT add dx,4 mov eax,edi out dx,eax mov dx,cx ;Направление обмена - "в память" mov al,8 out dx,al mov dx,BASE+7 ;Посылаем команду "READ SECTORS DMA" mov al,0C8h out dx,al mov dx,cx ;Разрешаем Bus Mastering (с этого момента начинается обмен) mov al,9 out dx,al ret READ_DMA ENDP ;########################################### ;Инициализация вектора прерываний IRQ14 # ;########################################### InitIRQ proc push AX push BX push CX push DX push ES ;считывание старого вектора mov AL, 76h mov AH, 35h int 21h mov [Old_Int], BX ;сохранили старый вектор mov [Old_Int+2], ES ;устанавливаем новый обработчик прерываний mov AL, 76h lea DX, IRQ_Int mov AH, 25h int 21h pop ES pop DX pop CX pop BX pop AX ret InitIRQ endp ;################################################# ;Программа обработки прерываний HDD0 # ;Когда происходит прерывание проверяется бит AC # ;если false, то уходим на стандартный обработчик,# ;иначе выходим. Данные в буфере # ;################################################# IRQ_Int proc far push AX push BX push CX push DX push ES mov dx,[BlockReg] ;Ждем AC=0 (DMA обмен закончен) add dx,2 in al,dx test al,1 jnz exit mov dx,[BlockReg] ;Запретить Bus Master mov al,0 out dx,al pop ES pop DX pop CX pop BX pop AX jmp end_ exit: pop ES pop DX pop CX pop BX pop AX jmp dword ptr [Old_Int] IRQ_Int endp start: mov ax,data mov ds,ax mov eax,data shl eax,4 mov edi,eax ;Получаем физический адрес таблицы и загружаем его в EDI add eax,8 mov PRD_ADDR,eax ;Заполняем саму таблицу mov PRD_COUNT,512 mov PRD_FLAG,08000h mov esi,0 ;Загрузочный сектор Master-устройства call read_dma Wait_: mov AH, 09h ;показываем занятость процессора lea DX, CPUtest int 21h jmp Wait_ ;Теперь в буфере лежит MBR end_: ;Восстановление старого вектора mov AL, 76h mov AH, 25h lea DX, dword ptr [Old_Int] int 21h mov ax,4c00h int 21h code ends end start Подскажите, пожалуйста, если есть возможность.
Может быть проблема в том, что когда вызываеться твой обработчик, нет гарантии, что ds указывает на твой сегмент даных. По этому я рекомендую дописать в твоем обработчике в самом начале: Код (Text): push ds mox ax,data mov ds,ax Ну и в конце не забудь возобновить сегментный регистр ds