.586
            public beg_scan_
            public end_scan_
            public size_free_mem_
            public info_pc_
            public pause_
            public test_t_

            extern malloc_    :near
            extern free_      :near
            extern _eprintf   :near

;            .data?

           .DATA
old_09      label   fword           ; in CSEG to allow addressing
ofs09       dd      ?
seg09       dw      ?

            .code

tkeyb       proc
            cli
            push    eax          ;сохранение регистров
            push    ebx          ;
            push    ds
; получение скан-кода
            in      al,60h      ;получение скан-кода из порта
            mov     ah,al
            in      al,61h
            mov     bl,al
            or      al,80h
            out     61h,al
            mov     al,bl
            out     61h,al
;загрузка регистра ES
            push    ax
            mov     ax,seg ofs09
            mov     ds,ax
            pop     ax
            mov     al,ah


            test    ah,80h
            jnz     quit
            mov     word ptr ds:[41ah],30h
            mov     word ptr ds:[41ch],32h
            mov     al,20h
            mov     ds:[430h],ax
quit:
            mov     al,20h
            out     20h,al

            pop     ds
            pop     ebx
            pop     eax
            iretd
;
tkeyb       endp

;***** void beg_scan()
beg_scan_   proc

            push    eax
            push    ebx
            push    edx
            push    ecx

            mov     bl,09h
            mov     ax,204h             ;Чтение вектора прерывания 8 = es:ebx
            int     31h
            mov     ofs09,edx
            mov     seg09,cx

            cli
            mov     bl,09h
            mov     ax,205h
            mov     edx,offset tkeyb
            mov     cx,cs
            int     31h
;-------------------------------------------
;            mov     bl,10h
;            mov     ax,203h
;            mov     edx,offset isk_0Fh
;            mov     cx,cs
;            int     31h
;-------------------------------------------
;------------- Обработчик на int 24 --------
            mov     bl,24h
            mov     ax,205h
            mov     edx,offset int_24h
            mov     cx,cs
            int     31h

            sti
            pop     ecx
            pop     edx
            pop     ebx
            pop     eax
            ret
beg_scan_   endp
;******* void end_scan()
end_scan_   proc
            push    eax
            push    ebx
            push    edx
            push    ecx

            mov     bl,09h
            mov     ax,205h
            mov     edx, ofs09
            mov     cx, seg09
            int     31h

            pop     ecx
            pop     edx
            pop     ebx
            pop     eax
            ret
end_scan_   endp
;-----------------------------------------------------
int_24h     proc

;            push    offset err_24mes1
;            push    0000000eH
;            call    _eprintf
;            add     esp,00000008H

            mov ax,3
            sti
            iretd
err_24mes1           db "Критическая ошибка DOS",00
int_24h     endp
;-----------------------------------------------------
isk_0Fh     proc
            push    eax

            mov     eax,[esp+4]
            cmp     word ptr cs:[eax],75D8h         ;fdiv
            je      mfdiv
            cmp     word ptr cs:[eax],70D8h         ;fdiv
            je      mfdiv
            cmp     word ptr cs:[eax],0F1DEh        ;fdivp
            je      mfdivp
            cmp     word ptr cs:[eax],0F9DEh        ;fdivp
            je      mfdivp
            cmp     word ptr cs:[eax],35DCh        ;fdiv_p
            je      mfdiv_p
            mov     eax,offset err_01mes2
            jmp     err_other
mfdiv:
            add     dword ptr [esp+4],3
            jmp     err_div
mfdivp:
            add     dword ptr [esp+4],2
            jmp     err_div
mfdiv_p:
            add     dword ptr [esp+4],6
err_div:
            mov     eax,offset err_01mes1
err_other:
            push    eax
            mov     eax,0000000cH
            push    eax
            call    _eprintf
            add     esp,00000008H

            pop     eax
            iretd
err_01mes1  db "Ошибка: Деление на ноль",00
err_01mes2  db "Ошибка: Другие ошибки FPU",00
isk_0Fh     endp
;-----------------------------------------------------
info_pc_    proc
            push   ebx
            push   ecx
            push   edx

            cli                        ; disable interrupts
            pushfd                     ; push flags to look at
            pop     eax                ; get eflags
            mov     ebx, eax           ; save for later
            xor     eax, 200000h       ; toggle bit 21
            push    eax
            popfd                      ; load modified eflags to CPU
            pushfd                     ; push eflags to look at
            pop     eax                ; get current eflags
            push    ebx                ; push original onto stack
            popfd                      ; restore original flags
            sti                        ; enable interrupts
            xor     eax, ebx           ; check if bit changed
            jnz     upPentium          ; changed, it's a Pentium
            mov     ax, 4              ; set 80486 flag
            jmp     uP_Exit

upPentium:
            mov     eax, 1             ; get family info function
            CPUID                      ; macro for CPUID instruction
            and     eax, 0F00h         ; find family info
            shr     eax, 8             ; move to al
up_Exit:

;            mov    ax,00400h
;            int    31h
;            movzx  eax,cl
            movzx    eax,al

            pop    edx
            pop    ecx
            pop    ebx
            ret
info_pc_    endp
;-----------------------------------------------------
size_free_mem_   proc
            push edi

            mov eax,30h
            call malloc_
            mov edi,eax
            mov ax,0500h
            int 31h
            mov eax,[edi]
            push eax
            mov eax,edi
            call free_
            pop eax

            pop edi
            ret
size_free_mem_   endp
;----------------------------------------------------
;test()
test_t_     proc

            db     0Fh,31h        ;RDTSC
            mov    ebx,eax
            mov    ax,100
            call   pause_
            db     0Fh,31h        ;RDTSC
            sub    eax,ebx
            ret
test_t_     endp
;-----------------------------------------------------
;pause(eax)
pause_      proc
            pushad

            mov     cx,ax
            call    READ_PIT
            mov     bx, ax          ;сохраняем текуще значение таймера
waitRD:                             ;ждем CX тиков PIT
            call    READ_PIT
            sub     ax, bx          ;разница с начальным значением
            neg     ax              ;то корректируем
            cmp     ax, cx
            jc      waitRD          ;если еще нет, то ждем

;            mov   dx,ax
;            shr   eax,16
;            mov   cx,ax
;            mov   ah,86h
;            int   15h

            popad
            ret
pause_      endp
;-----------------------------------------------------
READ_PIT        proc near
        xor     al, al          ;0 = читать 0 канал
        out     43h,al          ;порт управления
        in      al,40h          ;читаем LSB
        mov     ah,al
        in      al,40h          ;читаем MSB
        xchg    ah,al
        ret
READ_PIT        ENDP

end