;//--------------------------------------------------------------- ;// usertick.s ;// ;// This program installs a custom interrupt service routine ;// for the user timer-tick interrupt (INT-0x1C), then waits ;// until a key is pressed before de-installing this handler ;// and returning control to our 'trackldr.s' boot-loader. ;// ;// assemble with: $ as86 usertick.s -b usertick.b ;// install using: $ dd if=usertick.b of=/dev/fd0 seek=1 ;// ;// NOTE: This code begins executing with CS:IP = 1000:0002, ;// assuming our 'trackldr.b' resides in diskette sector #0. ;// ;// programmer: ALLAN CRUSE ;// date begun: 11 FEB 2004 ;//--------------------------------------------------------------- .SECT .TEXT ;----------------------------------------------------------------- .WORD 0xABCD ; programming signature ;----------------------------------------------------------------- main: push ds ; preserve caller's DS xor ax, ax ; address zero segment mov ds, ax ; with DS register ; save the original INT-0x1C interrupt-vector mov esi, #0x1C ; interrupt vector ID mov eax, [esi*4] ; fetch current vector CSEG mov oldvect, eax ; and save vector here ; install a new INT-0x1C interrupt vector mov eax, #0x10000000 ; compose the vector lea ax, isr0x1C ; in register EAX mov [esi*4], eax ; and store into IVT ; wait for user's keypress xor ah, ah ; get_keyboard_input int 0x16 ; request BIOS service ; restore the original INT-0x1C interrupt-vector CSEG mov eax, oldvect ; fetch saved vector mov [esi*4], eax ; and store into IVT pop ds ; recover caller's DS retf ; return to 'trackldr' ;----------------------------------------------------------------- oldvect: .LONG 0 ; stores original vector ;----------------------------------------------------------------- ;----------------------------------------------------------------- secs: .LONG 0 ; holds number of seconds mins: .LONG 0 ; holds number of minutes hour: .LONG 0 ; holds number of hours hday: .LONG 0 ; holds halfday flag-bit ;----------------------------------------------------------------- report: .ASCII " xx:xx:xx xm " ; formatted output-string rptlen: .WORD * - report ; length of output-string ampm: .ASCII "ap" ; morning/afternoon ascii ;----------------------------------------------------------------- isr0x1C: ; ; This interrupt service routine will be invoked by the system's ; timer-tick interrupt-handler. (It must preserve the values in ; all CPU registers.) It obtains the current value of the timer ; tick-counter from the ROM-BIOS DATA-AREA (dword at 0040:006C), ; then computes and displays the current time-of-day (by writing ; directly to the video memory) at screen's upper-right corner. ; pushad ; preserve CPU registers push ds push es ; setup sement-registers to address our program data mov ax, cs ; address this segment mov ds, ax ; with DS register ; get current count of timer-ticks mov ax, #0x40 ; address rombios data mov es, ax ; with ES register ESEG mov eax, [0x006C] ; get timer-tick count ; total_seconds = 10 * tick_count / 182 mov ecx, #10 ; setup multiplier mul ecx ; perform multiply mov ecx, #182 ; setup divisor div ecx ; perform division ; secs = total_seconds % 60 xor edx, edx ; extend to quadword mov ecx, #60 ; seconds-per-minute div ecx ; perform division mov secs, edx ; store remainder ; mins = secs % 60 xor edx, edx ; extend to quadword mov ecx, #60 ; minutes-per-hour div ecx ; perform division mov mins, edx ; store remainder ; hour = mins % 12 xor edx, edx ; extend to quadword mov ecx, #12 ; hours-per-halfday div ecx ; perform division mov hour, edx ; store remainder mov hday, eax ; also quotient ; develop the report-string's format mov eax, hour ; load 'hours' value lea di, report+1 ; point to its field call al2hex ; convert to decimal mov eax, mins ; load 'mins' value lea di, report+4 ; point to its field call al2hex ; convert to decimal mov eax, secs ; load 'secs' value lea di, report+7 ; point to its field call al2hex ; convert to decimal mov eax, hday ; load halfday value lea di, report+10 ; point to its field mov dl, ampm[eax] ; fetch 'a' or 'p' mov [di], dl ; store the character ; draw current time-of-day to video screen mov ax, #0xB800 ; address video memory mov es, ax ; with ES register mov di, #134 ; point ES:DI to destn lea si, report ; point DS:SI to string cld ; do forward processing mov ah, #0x1F ; colors: white-on-blue mov cx, rptlen ; number of characters nxch: lodsb ; fetch next character stosw ; draw char and colors loop nxch ; process another char pop es ; recover saved registers pop ds popad iret ; return from this ISR ;----------------------------------------------------------------- al2hex: ; converts value in AL to 2-digit decimal-string at DS:DI mov cl, #10 ; setup the 8-bit divisor div cl ; divide AX by radix ten or ax, #0x3030 ; convert binary to ascii mov [di], ax ; store the digit-pair ret ; return to the caller ;----------------------------------------------------------------- END