Assembler - язык неограниченных возможностей


Взаимодействие между процессами - часть 5


; процедура init_threads ; инициализирует обработчик прерывания 08h и заполняет структуры, описывающие ; обе нити init_threads proc near pushf pusha push es mov ax,3508h ; AH = 35h, AL = номер прерывания int 21h ; определить адрес обработчика, mov word ptr old_int08h,bx ; сохранить его mov word ptr old_int08h+2,es mov ax,2508h ; AH = 25h, AL = номер прерывания mov dx,offset int08h_handler ; установить наш int 21h pop es popa ; теперь регистры те же, что и при вызове процедуры popf

mov thread1._ax,ax ; заполнить структуры mov thread2._ax,ax ; threadl и thread2, mov thread1._bx,bx ; в которых хранится содержимое mov thread2._bx,bx ; всех регистров (кроме сегментных - mov thread1._cx,cx ; они в этом примере не изменяются) mov thread2._cx,cx mov thread1._dx,dx mov thread2._dx.dx mov thread1._si,si mov thread2._si,si mov thread1._di,di mov thread2._di,di mov thread1._bp,bp mov thread2._bp,bp mov thread1._sp,offset thread1_stack+512 mov thread2._sp,offset thread2_stack+512 pop ax ; адрес возврата (теперь стек пуст) mov thread1._ip,ax mov thread2._ip,ax pushf pop ax ; флаги mov thread1._flags,ax mov thread2._flags,ax mov sp,thread1._sp ; установить стек нити 1 jmp word ptr thread1._ip ; и передать ей управление init_threads endp

current_thread db 1 ; номер текущей нити

; Обработчик прерывания INT08h (IRQ0) переключает нити int08h_handler proc far pushf ; сначала вызвать старый обработчик db 9Ah ; код команды call far old_int08h dd 0 ; адрес старого обработчика ; Определить, произошло ли прерывание в момент исполнения нашей нити или ; какого-то обработчика другого прерывания. Это важно, так как мы не собираемся ; возвращать управление тому, кого прервал таймер, по крайней мере сейчас. ; Именно поэтому нельзя пользоваться прерываниями для задержек в наших нитях и ; поэтому программа не работает в окне DOS (Windows 95) mov save_di,bp ; сохранить ВР mov bp,sp push ax push bx pushf mov ax,word ptr [bp+2] ; прочитать сегментную часть mov bx,cs ; обратного адреса, cmp ax,bx ; сравнить ее с CS, jne called_far ; если они не совпадают - выйти, popf pop bx ; иначе - восстановить регистры pop ax mov bp,save_di mov save_di,di ; сохранить DI, SI mov save_si,si pushf ; и флаги ; определить, с какой нити на какую надо передать управление, cmp byte ptr current_thread,1 ; если с первой, je thread1_to_thread2 ; перейти на thread1_to_thread2, mov byte ptr current_thread,1 ; если с 2 на 1, записать ; в номер 1 mov si,offset thread1 ; и установить SI и DI mov di,offset thread2 ; на соответствующие структуры, jmp short order_selected thread1_to_thread2: ; если с 1 на 2, mov byte ptr current_thread,2 ; записать в номер нити 2 mov si,offset thread2 ; и установить SI и DI mov di,offset thread1 order_selected: ; записать все текущие регистры в структуру по адресу [DI] ; и загрузить все регистры из структуры по адресу [SI] ; начать с SI и DI: mov ax,[si]._si ; для MASM все выражения [reg]._reg надо push save_si ; заменить на (thread_struc ptr [reg])._reg pop [di]._si mov save_si,ax mov ax,[si]._di push save_di pop [di]._di mov save_di,ax ; теперь все основные регистры mov [di._ax],ax mov ax,[si._ax] mov [di._bx],bx mov bx,[si._bx] mov [di._cx],cx mov cx,[si._cx] mov [di._dx],dx mov dx,[si._dx] mov [di._bp],bp mov bp,[si._bp] ; флаги pop [di._flags] push [si._flags] popf ; адрес возврата pop [di._ip] ; адрес возврата из стека add sp,4 ; CS и флаги из стека - теперь он пуст ; переключить стеки mov [di._sp],sp mov sp,[si._sp] push [si._ip] ; адрес возврата в стек (уже новый) mov di,save_di ; загрузить DI и SI mov si,save_si retn ; и перейти по адресу в стеке ; управление переходит сюда, если прерывание произошло в чужом коде called_far: popf ; восстановить регистры pop bx pop ax mov bp,save_di iret ; и завершить обработчик int08h_handler endp




Начало  Назад  Вперед