bits 16 cpu 386 org 0x100 freq equ 120 ; ticks per second mov ax, cs mov ds, ax cli mov word [low_level_ticks_per_tick], 0x1234DD / freq mov al, 8 mov ah, 0x35 int 0x21 mov [bios_handler], bx mov [bios_handler+2], es mov ah, 0x25 mov dx, handler_entry int 0x21 mov al, 0x34 out 0x43, al mov al, (0x1234DD / freq) % 256 out 0x40, al mov al, (0x1234DD / freq) / 256 out 0x40, al sti wait_init: mov al, [init] test al, al jz wait_init jmp timer prev_ticks: dq 0 next_ticks: dq 0 ticks_delta: dq 0 msg: db "000000", 0x0D, 0x0A, "$" timer: cli mov ax, [ticks] mov [prev_ticks], ax mov ax, [ticks+2] mov [prev_ticks+2], ax mov ax, [ticks+4] mov [prev_ticks+4], ax mov ax, [ticks+6] mov [prev_ticks+6], ax sti timer_loop: mov cx, 128 timer_nops: nop loop timer_nops cli mov ax, [ticks] mov [next_ticks], ax mov [ticks_delta], ax mov ax, [ticks+2] mov [next_ticks+2], ax mov [ticks_delta+2], ax mov ax, [ticks+4] mov [next_ticks+4], ax mov [ticks_delta+4], ax mov ax, [ticks+6] mov [next_ticks+6], ax mov [ticks_delta+6], ax sti mov bx, ticks_delta mov ax, [prev_ticks] sub [bx], ax mov ax, [prev_ticks+2] sbb [bx+2], ax mov ax, [prev_ticks+4] sbb [bx+4], ax mov ax, [prev_ticks+6] sbb [bx+6], ax cmp word [bx+6], 0 jg print cmp word [bx+4], 0 jg print cmp word [bx+2], 0 jg print cmp word [bx], freq jl timer_loop print: add byte [msg+5], 1 cmp byte [msg+5], '9' jle print_msg mov byte [msg+5], '0' add byte [msg+4], 1 cmp byte [msg+4], '9' jle print_msg mov byte [msg+4], '0' add byte [msg+3], 1 cmp byte [msg+3], '9' jle print_msg mov byte [msg+3], '0' add byte [msg+2], 1 cmp byte [msg+2], '9' jle print_msg mov byte [msg+2], '0' add byte [msg+1], 1 cmp byte [msg+1], '9' jle print_msg mov byte [msg+1], '0' add byte [msg], 1 cmp byte [msg], '9' jle print_msg mov byte [msg], '0' print_msg: mov dx, msg mov ah, 0x09 int 0x21 mov ax, [next_ticks] mov [prev_ticks], ax mov ax, [next_ticks+2] mov [prev_ticks+2], ax mov ax, [next_ticks+4] mov [prev_ticks+4], ax mov ax, [next_ticks+6] mov [prev_ticks+6], ax jmp timer_loop db 0 ticks: dq 0 low_level_ticks_per_tick: dw 0 low_level_ticks_mod_10000h: dw 0 init: db 0 handler_entry: pushf push ds push bx push ax mov ax, cs mov ds, ax mov byte [init], 1 mov bx, ticks add word [bx], 1 adc word [bx+2], 0 adc word [bx+4], 0 adc word [bx+6], 0 mov ax, [low_level_ticks_per_tick] add [low_level_ticks_mod_10000h], ax jnc skip_bios_handler pop ax pop bx pop ds popf db 0xEA bios_handler: dd 0 skip_bios_handler: mov al, 0x20 out 0x20, al pop ax pop bx pop ds popf iret