Страница 1 из 1
Intel APIC
Добавлено: 04 май 2008, 20:09
Draeden
Меня не пускают в раздел ассемблера, поэтому пишу здесь.
Я пишу программу на ассемблере для Intel x86: нужно каждые 30 сек. сохранять экран в файл. Для этого я делаю перехват IRQ 0 и запускаю счётчик. Каждый раз при достижении нуля я пытаюсь сохранить 64 kb данных экрана с адресов A000:XXXX в файл, но при этом используется диск IRQ 14/15. Диск не может быть использован пока обрабатывается таймер: программа падает. Можно ли решить проблему ?
Re: Intel APIC
Добавлено: 05 май 2008, 18:14
Draeden
Мда... видимо APIC не вызывает ажиотажа...
Re: Intel APIC
Добавлено: 07 май 2008, 17:06
somewhere
Перед записью скажите контроллеру что вы уже закончили с таймером. Либо поменяйте на стеке адрес возврата, предварительно его сохранив. Потом по IRET свободно выйдите к процедуре записи на диск, а оттуда пошлете туда, где произошло аппаратное прерывание. Тему можно было бы разместить в разделе "Вопрошайка", здесь редко кто бывает.
Re: Intel APIC
Добавлено: 08 май 2008, 08:06
Draeden
1. Сообщить
APIC о завершении
IRQ0:
Код: Выделить всё
int8handler:
mov al, 20h
out 20h, al
call writetofile
jmp dword ptr cs : oldint8handler
Две команды с портами разрешают прерывания более низкого приоритета на
APIC0, или я не прав ? Я пробовал так делать, но всё равно не работает.
2. Насчёт смены адреса возврата не совсем понятно: чем это будет отличатся от простого прыжка в другую область кода ?
Код: Выделить всё
int8handler:
pop eax
push offset writetofile
push cs
iret
Re: Intel APIC
Добавлено: 08 май 2008, 09:33
somewhere
" писал(а):2. Насчёт смены адреса возврата не совсем понятно: чем это будет отличатся от простого прыжка в другую область кода ?
Почти ничем, кроме того что сменится IOPL в регистре флагов. В защищенном режиме это важно, обычно я использую этот способ для "подвешивания" собственных обработчиков на системные дабы получить привелегии на выполнение собственного кода.
Вообще по хорошему перед записью на диск нужно освободить оба контроллера
потом не совсем понятно в каком режиме работает контроллер у вас. По умолчанию он работает в режиме приоритетов, а это значит что все прерывания второго контроллера (IRQ8 – IRQ15) оказыжутся между IRQ1 и IRQ3, так как именно IRQ2 используется для каскада двух контроллеров. Тогда значит надо перевести контроллер прерываний в режим специальной маски и
отключить на время записи на диск прерывния IRQ0. Что посылать - я уже не помню, в порт 21h кинуть маску, в ней каждый бит соответствует прерыванию IRQ0 - IRQ7.
Re: Intel APIC
Добавлено: 08 май 2008, 18:09
Draeden
Я попробовал отключать
IRQ0 на время работы диска. Для контроля я запустил резидента, который ставит обработчик на
IRQ0 и выводит время в левый верхний угол экрана. После чего я запустил резидента который должен сохранять данные экрана в файл. Время, показываемое в левом верхнем углу, останавливалось, а на диск
обычно ничего не попадало ( иногда удавалось сохранить, иногда нет ). Не могли бы посмотреть код ?
P.S. извиняюсь за такой наглый вопрос, но это, видимо, самый простой вариант, к тому же я постарался убрать всё лишнее.
Код: Выделить всё
<...>
main:
jmp init
; timer handler: saves screen every -time- ticks
timerhandler:
pushf
call dword ptr cs : oldtimer
cmp cs : elapsed, 0
je save
dec cs : elapsed
iret
save:
push ax
in al, 21h
or al, 1
out 21h, al
call savescreen
in al, 21h
and al, not 1
out 21h, al
pop ax
mov cs : elapsed, time
iret
<...>
savescreen:
<...>
; Resident data
oldtimer dw ?, ? ; original timer handler
time = 18 ; save to a file every 3 seconds
elapsed dw time ; elapsed ticks
; Initialization: set hooks and stay resident
init:
<...>
; Set hook on timer
<...>
; Stay resident
<...>
end main
Также я попытался менять адрес возврата, результат тот же.
Код: Выделить всё
timerhandler:
<...>
pop dword ptr cs : oldretaddr
push cs
push offset savescr
iret
savescr:
call savescreen
jmp dword ptr cs : oldretaddr
Re: Intel APIC
Добавлено: 09 май 2008, 11:02
somewhere
лучше выложите полный код проги - иногда все может быть правильно, но из-за всего одной ошибки может не работать вся прога. Например здесь в обработчике стоит pushf, который потом не снимается со стека и указатель постоянно уменьшается на 2 каждое прерывание.
Re: Intel APIC
Добавлено: 09 май 2008, 15:26
Draeden
Спасибо за внимание. Вот весь код (tasm):
Код: Выделить всё
.model tiny
.386
.code
org 80h
cllen = $
org 82h
cldata = $
org 100h
; Main entry
main:
jmp init
; timer handler: saves screen every -time- ticks
timerhandler:
pushf
call dword ptr cs : oldtimer
cmp cs : elapsed, 0
je save
dec cs : elapsed
iret
save:
pop dword ptr cs : oldretaddr
push cs
push offset savescr
iret
savescr:
call savescreen
jmp dword ptr cs : oldretaddr
; kb handler: loads screen at Ctrl + L pressed
kbhandler:
push ax
in al, 60h
cmp al, 26h ; 'L' key
jne exitkbh
call loadscreen
exitkbh:
pop ax
jmp dword ptr cs : oldkb
; Saves screen to buffer
savescreen:
pusha
push ds
mov ah, 3Ch
xor cx, cx
push cs
pop ds
mov dx, offset cldata
int 21h
jc ssexit
mov bx, ax
mov ah, 40h
mov cx, -1
push 0A000h
pop ds
xor dx, dx
int 21h
mov ah, 3Eh
int 21h
ssexit:
pop ds
popa
retn
; Loads screen from buffer
loadscreen:
; Resident data
oldtimer dw ?, ? ; original timer handler
oldkb dw ?, ? ; original kb handler
time = 18 ; save to a file every 3 seconds
elapsed dw time ; elapsed ticks
oldretaddr dw ?, ? ; used in INT 8 handler
; Initialization: set hooks and stay resident
init:
xor bx, bx
mov bl, byte ptr ds : [ offset cllen ]
test bx, bx
jz showusage
mov byte ptr ds : [ offset cldata - 1 + bx ], 0
; Set hook on timer
mov bx, 8
mov ax, offset timerhandler
mov dx, offset oldtimer
call hook
; Set hook on keyboard
mov bx, 9
mov ax, offset kbhandler
mov dx, offset oldkb
call hook
call savescreen
; Stay resident
mov ah, 27h
mov dx, offset init
int 27h
showusage:
mov ah, 9
mov dx, offset usage
int 21h
retn
usage db 13, 10
db 'Resident screen saver', 13, 10
db 'Written by Draeden', 13, 10
db 13, 10
db 'Usage: rss filename', 13, 10
db ' filename - some file to keep the screen data', 13, 10
db 36
; Sets a hook on interrupt
;
; Arguments:
;
; BX = interrupt
; AX = new handler
; DI = ( dword ) place for old handler
hook:
push bx
push ds
push 0
pop ds
shl bx, 2
push dword ptr ds : [ bx ]
pop dword ptr cs : [ di ]
push cs
push ax
pop dword ptr ds : [ bx ]
pop ds
pop bx
retn
end main
Re: Intel APIC
Добавлено: 09 май 2008, 17:27
somewhere
Основная ошибка - процедуре hook передавался параметр в DX хотя надо было в DI
Я не знаю как у вас тут "периодически" работало, т.к. работать вообще не должно было. Вот подправленый и рабочий код. Я убрал хук с клавы (для тестов не нужен был) и добавил индикатор записи для себя. А так вроде все
Код: Выделить всё
.model tiny
.386
.code
org 80h
cllen = $
org 82h
cldata = $
org 100h
; Main entry
main:
jmp init
; timer handler: saves screen every -time- ticks
timerhandler:
pusha
cmp cs : elapsed, 0
jz save
dec cs : elapsed
jmp @exitint
save:
in al, 21h
or al, 1
out 21h, al
call savescreen
in al, 21h
and al, not 1
out 21h, al
mov cs:elapsed, time
@exitint:
popa
jmp dword ptr cs : oldtimer
; kb handler: loads screen at Ctrl + L pressed
kbhandler:
push ax
in al, 60h
cmp al, 26h ; 'L' key
jne exitkbh
call loadscreen
exitkbh:
pop ax
jmp dword ptr cs : oldkb
; Saves screen to buffer
savescreen:
pusha
push ds
mov ax, 0B800h
mov ds, ax
mov word ptr ds:[0], 0F41h
mov ah, 3Ch
xor cx, cx
push cs
pop ds
mov dx, offset cldata
int 21h
jc ssexit
mov bx, ax
mov ah, 40h
mov cx, -1
push 0A000h
pop ds
xor dx, dx
int 21h
mov ah, 3Eh
int 21h
ssexit:
pop ds
popa
retn
; Loads screen from buffer
loadscreen:
; Resident data
oldtimer dw ?, ? ; original timer handler
oldkb dw ?, ? ; original kb handler
time = 18 ; save to a file every 3 seconds
elapsed dw time ; elapsed ticks
oldretaddr dw ?, ? ; used in INT 8 handler
; Initialization: set hooks and stay resident
init:
xor bx, bx
mov bl, byte ptr ds : [ offset cllen ]
test bx, bx
jz showusage
mov byte ptr ds : [ offset cldata - 1 + bx ], 0
; Set hook on timer
mov bx, 8
mov ax, offset timerhandler
mov di, offset oldtimer
call hook
; Set hook on keyboard
mov bx, 9
mov ax, offset kbhandler
mov dx, offset oldkb
;call hook
;call savescreen
; Stay resident
mov ah, 27h
mov dx, offset init
int 27h
showusage:
mov ah, 9
mov dx, offset usage
int 21h
retn
usage db 13, 10
db 'Resident screen saver', 13, 10
db 'Written by Draeden', 13, 10
db 13, 10
db 'Usage: rss filename', 13, 10
db ' filename - some file to keep the screen data', 13, 10
db 36
; Sets a hook on interrupt
;
; Arguments:
;
; BX = interrupt
; AX = new handler
; DI = ( dword ) place for old handler
hook:
push bx
push ds
push 0
pop ds
shl bx, 2
push dword ptr ds : [ bx ]
pop dword ptr cs : [ di ]
push cs
push ax
pop dword ptr ds : [ bx ]
pop ds
pop bx
retn
end main
Re: Intel APIC
Добавлено: 10 май 2008, 13:28
Draeden
Спасибо, наконец то всё работает.