Форум программистов «Весельчак У»
  *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

  • Рекомендуем проверить настройки временной зоны в вашем профиле (страница "Внешний вид форума", пункт "Часовой пояс:").
  • У нас больше нет рассылок. Если вам приходят письма от наших бывших рассылок mail.ru и subscribe.ru, то знайте, что это не мы рассылаем.
   Начало  
Наши сайты
Помощь Поиск Календарь Почта Войти Регистрация  
 
Страниц: [1]   Вниз
  Печать  
Автор Тема: Многозадачность. Помогите справиться, пожалуйста.  (Прочитано 8591 раз)
0 Пользователей и 1 Гость смотрят эту тему.
Raiden
Гость
« : 09-12-2004 20:08 » 

Здрасьте, господа кодеры :о)

Такая проблемка... Нужно написать многозадачность: четыре процедуры, выводящие четыре своих сообщения; выполняются одновременно, для чего устанавливается обработчик прерывания системного таймера, который по кадому такту должен передавать управление следующей процедуре.

Я написал прогу, но она жутко глючная - ниче нормально вывести не может - какие-то каракули пишет вместо нужных сообщений, подвисает в конце, но это еще ерунда, главная проблема - процедуры выполняются почему-то последовательно, а не одновременно.

По моей задумке должно быть примерно так: обработчик проверяет, какую процедуру он прервал, сохраняет ее регистры и флаги в структуру этой процедуры, после чего восстанавливает регистры следующей процедуры, в частности загружает в стек ее 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


Заранее благодарю...
Записан
Xeysan
Гость
« Ответ #1 : 09-12-2004 21:16 » 

Минск? БГУИР? Улыбаюсь
Код:

; +---------------------------+
; | Task sheduler for RM, DOS |
; +---------------------------+

; Struct definition
CONTEXT struc
_ax     dw      0       ; + 00h
_bx     dw      0       ; + 02h
_cx     dw      0       ; + 04h
_dx     dw      0       ; + 06h
_si     dw      0       ; + 08h
_di     dw      0       ; + 0Ah
_bp     dw      0       ; + 0Ch
_sp     dw      9Ah     ; + 0Eh
_ds     dw      0       ; + 10h
_es     dw      0       ; + 12h
_ss     dw      0       ; + 14h
_cs     dw      0       ; + 16h
_ip     dw      100h    ; + 18h
_flags  dw      0       ; + 1Ah
_res    dw      2 dup)0:; Reserved
        ends

CR      =       0Dh
LF      =       0Ah

        .model  tiny
        .386
        .code
         org 80h
bCmdLen         db      ?
bCmdSpace       db      ?
bCmdLine        db      ?
         org 100h
start{
; Save task names from command line
        call    About
        call    SaveNames

; Free an extra memory and set new stack frame
        mov     ah, 4Ah
        mov     bx, offset PRG_END
        mov     cl, 4
        shr     bx, cl
        add     bx, 10h
        int     21h
        jc      Error

        shl     bx, cl
        mov     sp, bx

; Prepare Return data
        pushf
        pop     dx                      ; Now bx contains flags

; Alloc memory for three tasks
        mov     cx, 3
        mov     si, offset contexts
        mov     di, offset PB1
        push    es
Alloc{
        mov     ah, 48h
        mov     bx, 50h
        int     21h
        jc      Error
        mov     es, ax
        mov     word ptr [si + 10h(, ax
        mov     word ptr [si + 12h(, ax
        mov     word ptr [si + 14h(, ax
        mov     word ptr [si + 16h(, ax
        mov     word ptr [si + 1Ah(, dx         ; Save flags

        add     ax, 10h
        mov     word ptr [di(, ax
        add     si, type CONTEXT
        add     di, 2*2
        dec     cx
        jnz     Alloc
        pop     es

; Load three overlays
        mov     ax, 4B03h
        mov     dx, offset szTask1
        mov     bx, offset PB1
        int     21h
        jc      Error
        mov     ax, 4B03h
        mov     dx, offset szTask2
        mov     bx, offset PB2
        int     21h
        jc      Error
        mov     ax, 4B03h
        mov     dx, offset szTask3
        mov     bx, offset PB3
        int     21h
        jc      Error

; Set new interrrupt handlers for timer and kbd
        mov     ax, 3508h
        int     21h
        mov     word ptr dwTimerVec, bx
        mov     word ptr dwTimerVec+2, es
        inc     al
        int     21h
        mov     word ptr dwKbdVec, bx
        mov     word ptr dwKbdVec+2, es

        mov     ax, 2509h
        mov     dx, offset KbdHandler
        int     21h
        dec     al
        mov     dx, offset cs{TimerHandler
        int     21h

; Wait for key
        pushf
        cli
        mov     ax, PB3
        sub     ax, 10h
        push    ax
        push    100h
        iret

; Restore interrupt handler
ReturnHere{
        lds     dx, dword ptr cs{dwKbdVec
        mov     ax, 2509h
        int     21h

        int     20h
Error{
        mov     dx, offset szSomething
        call    ErrorExit
contexts        CONTEXT 3 dup)<>:       ; Program contexts
wContexts       dw      0               ; Number of contexts
szTask1         db      13 dup)0:       ; First task name
szTask2         db      13 dup)0:       ; Second task name
szTask3         db      13 dup)0:       ; Third task name
wNames          dw      szTask1
                dw      szTask2
                dw      szTask3
; Parameter blocks
PB1             dw      0
                dw      0
PB2             dw      0
                dw      0
PB3             dw      0
                dw      0

; Old interrupt vectors
dwTimerVec      dd      0
dwKbdVec        dd      0

; Error ) and about : messages
szAbout         db      "* Task sheduler. Sylph, Minsk 2003 *",'$'
szParams        db      CR, LF, "--> Not enough parameters in command line.",'$'
szSomething     db      CR, LF, "--> Something happened, during initialization", '$'


; Procedures
About   proc    near
        push    ax
        push    dx
        mov     ah, 09h
        mov     dx, offset szAbout
        int     21h
        pop     dx
        pop     ax
        ret
About   endp
SaveNames       proc    near
        pusha

        mov     bx, offset wNames
        movzx   cx, bCmdLen
        mov     dx, 3
        mov     si, offset bCmdLine
        mov     di, word ptr [bx(

SN_Find{
        lodsb
        cmp     al, ' '
        je      SN_Find
        cmp     al, CR
        je      SN_Finish
        jcxz    SN_Finish

SN_Store{
        stosb
        jcxz    SN_Finish
        lodsb
        cmp     al, CR
        je      SN_Stop
        cmp     al, ' '
        jne     SN_Store
        add     bx, 2
        mov     di, word ptr [bx(
SN_Stop{
        dec     dx
        jz      SN_Finish
        jmp     SN_Find
SN_Finish{
        test    dx, dx
        jz      SN_Return
        mov     dx, offset szParams
        call    ErrorExit
SN_Return{
        popa
        ret
SaveNames       endp

; dx keeps string with error message
ErrorExit       proc    near
        mov     ah, 09h
        int     21h
        int     20h
ErrorExit       endp

; Save context proc
SaveContext     proc    near
        push    bx
        mov     bx, cs{wTask
        shl     bx, 5
        add     bx, offset cs{contexts
; Save registers
        mov     word ptr cs{[bx + 00h(, ax ; load registers, see CONTEXT
        pop     word ptr cs{[bx + 02h(
        mov     word ptr cs{[bx + 04h(, cx
        mov     word ptr cs{[bx + 06h(, dx
        mov     word ptr cs{[bx + 08h(, si
        mov     word ptr cs{[bx + 0Ah(, di
        mov     word ptr cs{[bx + 0Ch(, bp
        mov     word ptr cs{[bx + 0Eh(, sp
        mov     word ptr cs{[bx + 10h(, ds
        mov     word ptr cs{[bx + 12h(, es
        mov     word ptr cs{[bx + 14h(, ss
        mov     bp, sp
        mov     ax, word ptr [bp(
        mov     word ptr cs{[bx + 18h(, ax      ; Save ip
        mov     ax, word ptr [bp + 2(
        mov     word ptr cs{[bx + 16h(, ax      ; Save cs
        mov     ax, word ptr [bp + 4(
        mov     word ptr cs{[bx + 1Ah(, ax      ; Save flags
        jmp     TH_SaveRet
SaveContext     endp

RestoreContext  proc    near
        mov     bx, cs{wTask
        shl     bx, 5
        add     bx, offset cs{contexts

        mov     ss, word ptr cs{[bx + 14h(
        mov     es, word ptr cs{[bx + 12h(
        mov     ds, word ptr cs{[bx + 10h(
        mov     sp, word ptr cs{[bx + 0Eh(
        mov     bp, word ptr cs{[bx + 0Ch(
        mov     di, word ptr cs{[bx + 0Ah(
        mov     si, word ptr cs{[bx + 08h(
        mov     dx, word ptr cs{[bx + 06h(
        mov     cx, word ptr cs{[bx + 04h(
        mov     ax, word ptr cs{[bx + 00h(

        push    ax
        push    bp
        mov     bp, sp
        mov     ax, word ptr cs{[bx + 18h(
        mov     word ptr [bp + 04h(, ax
        mov     ax, word ptr cs{[bx + 16h(
        mov     word ptr [bp + 06h(, ax
        mov     ax, word ptr cs{[bx + 1Ah(
        mov     word ptr [bp + 08h(, ax
        pop     bp
        pop     ax

        mov     bx, word ptr cs{[bx + 02h(
        jmp     short TH_NoSwitch
RestoreContext  endp

; Time proc data
QUANTUM         =       18      ; Full second
wTimeStay       dw      QUANTUM ; Second for each task
wTask           dw      2       ; Current task

; Timer handler
TimerHandler    proc    far
        dec     cs{wTimeStay
        jnz     TH_NoSwitch

        mov     word ptr cs{wTimeStay, QUANTUM
        jmp     SaveContext     ; Save context for current task
TH_SaveRet{

        dec     word ptr cs{wTask
        jns     TH_Restore
        mov     word ptr cs{wTask, 2

TH_Restore{
        jmp     RestoreContext

TH_NoSwitch{
        jmp     dword ptr cs{dwTimerVec
TimerHandler    endp

; Kbd proc
KbdHandler      proc    far
        pushf
        call    dword ptr cs{dwKbdVec

        lds     dx, dword ptr cs{dwTimerVec
        mov     ax, 2508h
        int     21h

        jmp     ReturnHere
KbdHandler      endp
PRG_END label   byte
end     start


Запускается так: shed.com task1.com task2.com task3.com

Задачи вот: ( в принципе, они близнецы )
Код:

; task 1
        .model  tiny
        .386
        .code
         org 100h
start{
        mov     ax, 0B800h
        mov     es, ax
        mov     cx, 80
        xor     di, di
        mov     al, '1'
        and     ah, 7Fh
        cld
_Loop{
        stosw
        dec     cl
        test    cl, cl
        jnz     _Loop
        xor     di, di
        xor     al, '1'
        mov     cl, 80
        jmp     _Loop
end     start


Код:

; task 2
        .model  tiny
        .386
        .code
         org 100h
start{
        mov     ax, 0B800h
        mov     es, ax
        mov     cx, 80
        mov     di, 80*2
        mov     al, '2'
        inc     ah
        and     ah, 7Fh
        cld
_Loop{
        stosw
        dec     cl
        test    cl, cl
        jnz     _Loop
        mov     di, 80*2
        xor     al, '2'
        mov     cl, 80
        jmp     _Loop
end     start


Код:

; task 3
        .model  tiny
        .386
        .code
         org 100h
start{
        mov     ax, 0B800h
        mov     es, ax
        mov     cx, 80
        mov     di, 80*4
        mov     al, '3'
        dec     ah
        and     ah, 7Fh
        cld
_Loop{
        stosw
        dec     cl
        test    cl, cl
        jnz     _Loop
        mov     di, 80*4
        xor     al, '3'
        mov     cl, 80
        jmp     _Loop
end     start


Заметь в задачах используются только регистры Ага. Это не ОС, поэтому есть ограничения... Успехов!

Да...на вопросы твои ( если они будут ), ответить быстро не смогу, у меня нет времени...
Записан
Raiden
Гость
« Ответ #2 : 10-12-2004 13:45 » 

Xeysan,
спасибо :о) не,я из Ростова, РИИЖТ Улыбаюсь
а почему тока регистры кстати? Не получится разве сделать так, чтоб они из памяти строку брали? У нас задание - написать какое-нить предложение... Конеш, можно это и в самой процедуре на одних регистрах сварганить, но как-то муторно... :о) И скорее всего скажут, что так низзя :о\
Записан
RXL
Технический
Администратор

ru
Offline Offline
Пол: Мужской

WWW
« Ответ #3 : 10-12-2004 16:25 » 

Raiden, почему у тебя нет ret в init_threads?
Записан

... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
Xeysan
Гость
« Ответ #4 : 10-12-2004 17:04 » 

Цитата: Raiden
спасибо :о) не,я из Ростова, РИИЖТ Улыбаюсь

Зерноград мой второй родной город Ага

Цитата: Raiden
а почему тока регистры кстати? Не получится разве сделать так, чтоб они из памяти строку брали?


Я уже не все помню, делалось это все год назад...там будут проблемы с адресацией, и может быть со стеком... В общем пробуй, смотри в отладчике, экспериментируй 8)
Записан
Raiden
Гость
« Ответ #5 : 10-12-2004 23:29 » 

RXL,
кхммм.. действительно... Если прога криво работала именно из-за этого, я буду ржать очень долго Улыбаюсь

Xeysan,
угу, пробую Улыбаюсь
Записан
p0et
Гость
« Ответ #6 : 07-04-2005 00:51 » 

хех. не чего даже добавить.
Записан
Страниц: [1]   Вверх
  Печать  
 

Powered by SMF 1.1.21 | SMF © 2015, Simple Machines