Здрасьте, господа кодеры :о)
Такая проблемка... Нужно написать многозадачность: четыре процедуры, выводящие четыре своих сообщения; выполняются одновременно, для чего устанавливается обработчик прерывания системного таймера, который по кадому такту должен передавать управление следующей процедуре.
Я написал прогу, но она жутко глючная - ниче нормально вывести не может - какие-то каракули пишет вместо нужных сообщений, подвисает в конце, но это еще ерунда, главная проблема - процедуры выполняются почему-то последовательно, а не одновременно.
По моей задумке должно быть примерно так: обработчик проверяет, какую процедуру он прервал, сохраняет ее регистры и флаги в структуру этой процедуры, после чего восстанавливает регистры следующей процедуры, в частности загружает в стек ее cs, ip и флаги, затем вызывает команду iret.
Процедуры запускаются из основной программы последовательно и обработчик определяет, сколько раз он уже запускался, и если он впервые прервал данную процедуру, то сохраняет ее регистры, а управление передает в основную программу (а не в процедуру), в которой сразу же (после очистки стека от ip этой процедуры) идет вызов следующей процедуры. Если же он для данной процедуры уже вызывался (а это значит, что у него есть запись о следующей процедуре), то он входит так сказать в освной режим и выполняет загрузку регистров следующей процедуры из ее структуры, как я сказал в предыдущем абзаце.
Вот мой глючный код:
.model tiny
.code
.586p
org 100h
start{
mov ax,03h
int 10h
call init_threads
cld
call thread1
add sp,2
call thread2
add sp,2
call thread3
add sp,2
call thread4
call shutdown_mt
int 20h
thread struc
_cx dw ?
_si dw ?
_di dw ?
_ip dw ?
_cs dw ?
_flags dw ?
thread ends
;;;;;;;///////;;;;;инициализация обработчика
init_threads proc near
pushf
pusha
push es
mov ax,3508h
int 21h
mov word ptr old_int,bx
mov word ptr old_int+2,es
mov ax,2508h
mov dx,offset new_int
int 21h
pop es
popa
popf
init_threads endp
;;;;;;;;///////;;;;;шатдаун многозадачности
shutdown_mt proc near
mov ax,2508h
lds dx,dword ptr old_int
int 21h
ret
shutdown_mt endp
;;;;;;////////;;;;;;;;новый обработчик
new_int proc far
pushf
pusha
db 9ah ;код команды call far - вызываем
old_int dd 0 ;старый обработчик вначале
;передаем управление нужной процедуре - в зависимости от значения
;current_thread
mov bx,current_thread
shl bx,1
jmp cs{jump_table[bx(
jump_table dw m1,m2,m3,m4
m1{
call n1
jmp endcase
m2{
call n2
jmp endcase
m3{
call n3
jmp endcase
m4{
call n4
jmp endcase
n1{
mov current_thread,2
;сохраняем регистры. С первой тройкой все просто - остальные
;берем из стека
mov thread_1._cx,cx
mov thread_1._si,si
mov thread_1._di,di
push ax
push bp
mov bp,sp
mov ax,word ptr [bp+22(
mov thread_1._ip,ax
mov ax,word ptr [bp+26(
mov thread_1._flags,ax
mov ax,word ptr [bp+24(
mov thread_1._cs,ax
pop bp
pop ax
cli
;если счетчик больше нуля, то есть, мы тут уже были, то прыжок
cmp counter,0
ja next1
;если мы в этой процедуре впервые, то
;запишем в стек, на место где у нас сейчас записан адрес возврата из
;обработчика в прерванную процедуру, адрес возврата процедуры
;в главный модуль, так, чтобы команда iret вернула нас не
;в прерванную процедуру, а в главный модуль.
inc counter
sti
push bp
push ax
mov bp,sp
mov ax,word ptr [bp+28(
mov word ptr [bp+22(,ax
pop ax
pop bp
ret
next1{
;если мы в этой процедуре уже были )значит у нас заполнена структура второй процедуры:{
sti
mov cx,thread_2._cx
mov si,thread_2._si
mov di,thread_2._di
push bp
push ax
mov bp,sp
mov ax, word ptr [bp+26(
mov ax,thread_2._flags
mov ax, word ptr [bp+22(
mov ax,thread_2._ip
mov ax, word ptr [bp+24(
mov ax,thread_2._cs
pop ax
pop bp
ret
n2{
mov current_thread,3
mov thread_2._cx,cx
mov thread_2._si,si
mov thread_2._di,di
push ax
push bp
mov bp,sp
mov ax,word ptr [bp+22(
mov thread_2._ip,ax
mov ax,word ptr [bp+26(
mov thread_2._flags,ax
mov ax,word ptr [bp+24(
mov thread_2._cs,ax
pop bp
pop ax
cli
cmp counter,1
ja next2
inc counter
sti
push bp
push ax
mov bp,sp
mov ax,word ptr [bp+28(
mov word ptr [bp+22(,ax
pop ax
pop bp
ret
next2{
sti
mov cx,thread_3._cx
mov si,thread_3._si
mov di,thread_3._di
push bp
push ax
mov bp,sp
mov ax, word ptr [bp+26(
mov ax,thread_3._flags
mov ax, word ptr [bp+22(
mov ax,thread_3._ip
mov ax, word ptr [bp+24(
mov ax,thread_3._cs
pop ax
pop bp
; mov [sp+24(,thread_3._flags
; mov [sp+20(,thread_3._ip
; mov [sp+22(,thread_3._cs
ret
n3{
mov current_thread,4
mov thread_3._cx,cx
mov thread_3._si,si
mov thread_3._di,di
push ax
push bp
mov bp,sp
mov ax,word ptr [bp+22(
mov thread_3._ip,ax
mov ax,word ptr [bp+26(
mov thread_3._flags,ax
mov ax,word ptr [bp+24(
mov thread_3._cs,ax
pop bp
pop ax
cli
cmp counter,2
ja next3
inc counter
sti
push bp
push ax
mov bp,sp
mov ax,word ptr [bp+28(
mov word ptr [bp+22(,ax
pop ax
pop bp
ret
next3{
sti
mov cx,thread_4._cx
mov si,thread_4._si
mov di,thread_4._di
push bp
push ax
mov bp,sp
mov ax, word ptr [bp+26(
mov ax,thread_4._flags
mov ax, word ptr [bp+22(
mov ax,thread_4._ip
mov ax, word ptr [bp+24(
mov ax,thread_4._cs
pop ax
pop bp
ret
n4{
mov current_thread,1
mov thread_4._cx,cx
mov thread_4._si,si
mov thread_4._di,di
push ax
push bp
mov bp,sp
mov ax,word ptr [bp+22(
mov thread_4._ip,ax
mov ax,word ptr [bp+26(
mov thread_4._flags,ax
mov ax,word ptr [bp+24(
mov thread_4._cs,ax
pop bp
pop ax
cli
cmp counter,3
ja next4
inc counter
sti
push bp
push ax
mov bp,sp
mov ax,word ptr [bp+28(
mov word ptr [bp+22(,ax
pop ax
pop bp
ret
next4{
sti
mov cx,thread_1._cx
mov si,thread_1._si
mov di,thread_1._di
push bp
push ax
mov bp,sp
mov ax, word ptr [bp+26(
mov ax,thread_1._flags
mov ax, word ptr [bp+22(
mov ax,thread_1._ip
mov ax, word ptr [bp+24(
mov ax,thread_1._cs
pop ax
pop bp
ret
endcase{
popa
popf
iret
new_int endp
;;;;////////////;;;;; закруглили обработчик.
;--------------------------------------
;сами процедуры
thread1 proc near
push 0b800h
pop es
xor di,di
mov si,offset string1
mov cx,ml1
cy1{
movsb
inc si
inc di
push cx
;длииииииииииинная пауза чтоб виден был процесс.
mov cx,-1
loop $
mov cx,-1
loop $
mov cx,-1
loop $
mov cx,-1
loop $
mov cx,-1
loop $
mov cx,-1
loop $
mov cx,-1
loop $
mov cx,-1
loop $
mov cx,-1
loop $
mov cx,-1
loop $
mov cx,-1
loop $
mov cx,-1
loop $
pop cx
loop cy1
ret
thread1 endp
thread2 proc near
push 0b800h
pop es
xor di,di
add di,100
mov si,offset string2
mov cx,ml2
cy2{
movsb
inc si
inc di
push cx
mov cx,-1
loop $
mov cx,-1
loop $
mov cx,-1
loop $
mov cx,-1
loop $
mov cx,-1
loop $
mov cx,-1
loop $
mov cx,-1
loop $
mov cx,-1
loop $
mov cx,-1
loop $
mov cx,-1
loop $
mov cx,-1
loop $
mov cx,-1
loop $
mov cx,-1
loop $
mov cx,-1
loop $
mov cx,-1
loop $
pop cx
loop cy2
ret
thread2 endp
thread3 proc near
push 0b800h
pop es
xor di,di
add di,200
mov si,offset string3
mov cx,ml3
cy3{
movsb
inc si
inc di
push cx
mov cx,-1
loop $
mov cx,-1
loop $
mov cx,-1
loop $
mov cx,-1
loop $
mov cx,-1
loop $
mov cx,-1
loop $
mov cx,-1
loop $
mov cx,-1
loop $
mov cx,-1
loop $
mov cx,-1
loop $
mov cx,-1
loop $
mov cx,-1
loop $
mov cx,-1
loop $
mov cx,-1
loop $
mov cx,-1
loop $
pop cx
loop cy3
ret
thread3 endp
thread4 proc near
push 0b800h
pop es
xor di,di
add di,300
mov si,offset string4
mov cx,ml4
cy4{
movsb
inc si
inc di
push cx
mov cx,-1
loop $
mov cx,-1
loop $
mov cx,-1
loop $
mov cx,-1
loop $
mov cx,-1
loop $
mov cx,-1
loop $
mov cx,-1
loop $
mov cx,-1
loop $
mov cx,-1
loop $
mov cx,-1
loop $
mov cx,-1
loop $
mov cx,-1
loop $
mov cx,-1
loop $
mov cx,-1
loop $
mov cx,-1
loop $
pop cx
loop cy4
ret
thread4 endp
;тут я пытался строки задавать сразу с атрибутами, и без атрибутов
;и вообще, по-всякому {о:
string1 db "Y",1fh,'o',1fh,'u',1fh,'a',1fh,'r',1fh
db "e",1fh,' ',1fh,'j',1fh,'u',1fh,'s',1fh
db "t",1fh,' ',1fh,'0',1fh,'`',1fh,'s',1fh
db "`",1fh,'a',1fh,'n',1fh,'d',1fh,'`',1fh
db "1",1fh,'`',1fh,'s',1fh
ml1 = $-string1
string2 db "He just only human$"
ml2 = $-string2
string3 db "Knock-knock, Neo!$"
ml3 = $-string3
string4 db "Follow the white rabbit$"
ml4 = $-string4
current_thread dw 1
counter db 0
thread_1 thread <>
thread_2 thread <>
thread_3 thread <>
thread_4 thread <>
end start
Заранее благодарю...