;//--------------------------------------------------------------- ;// rtupdate.s ;// ;// This program uses the CPU's TimeStamp Counter to measure ;// the duration of the Real-Time Clock's update-cycle. ;// ;// assemble with: $ as86 rtupdate.s -b rtupdate.b ;// install using: $ dd if=rtupdate.b of=/dev/fd0 seek=1 ;// ;// NOTE: This code begins executing with CS:IP = 1000:0002. ;// ;// programmer: ALLAN CRUSE ;// date begun: 02 MAY 2004 ;//--------------------------------------------------------------- MACRO rdtsc .BYTE 0x0F, 0x31 MEND .SECT .TEXT ;----------------------------------------------------------------- .WORD 0xABCD ; programming signature ;----------------------------------------------------------------- main: mov ax, cs ; address this segment mov ds, ax ; with DS register pop dword return_address ; store return-address mov ss, ax ; adjust SS register lea esp, tos0 ; and set new stacktop call record_update_counts call compute_microseconds call display_microseconds push dword return_address ; recover our exit-address retf ; exit to program launcher ;----------------------------------------------------------------- return_address: .LONG 0 ; to store exit-address ;----------------------------------------------------------------- compute_microseconds: ; determine the fraction of a second, in millionths mov eax, duration_1 mul dword onemillion ; times one million mov ecx, duration_2 div ecx ; save quotient, rounding to the nearest millionth add edx, edx ; double the remainder cmp ecx, edx ; is 2*rem < divisor? cmc ; yes, carry was set adc eax, #0 ; but now is cleared mov micro_secs, eax ; save duration (us) ret ;----------------------------------------------------------------- ;----------------------------------------------------------------- duration_1: .LONG 0 ; cycles during update duration_2: .LONG 0 ; cycles during second micro_secs: .LONG 0 ; ratio, in millionths onemillion: .LONG 1000000 ; the ratio multiplier ;----------------------------------------------------------------- record_update_counts: ; wait for an update-cycle to begin mov al, #0x0A ; RTC Register A out #0x70, al ; selected for access wait1: in al, #0x71 ; read register A test al, #0x80 ; update in progress? jnz wait1 ; yes, wait till done wait2: in al, #0x71 ; read register A test al, #0x80 ; update in progress? jz wait2 ; no, wait till begin ; immediately read the current TimeStamp rdtsc ; get the TimeStamp mov ebx, eax ; save LoTimeStamp mov ecx, edx ; save HiTimeStamp ; then wait for that update-cycle to finish wait3: in al, #0x71 ; read register A test al, #0x80 ; update in progress? jnz wait3 ; yes, wait till done ; store the processor's cycle-count rdtsc ; get new TimeStamp sub eax, ebx ; minus saved value sbb edx, ecx ; of Stamp quadword mov duration_1, eax ; store cycle-count ; now wait for the next update-cycle to begin wait4: in al, #0x71 ; read register A test al, #0x80 ; update in progress? jz wait4 ; no, wait till begin ; store the processor's cycle-count rdtsc ; get new TimeStamp sub eax, ebx ; minus saved value sbb edx, ecx ; of Stamp qyadword mov duration_2, eax ; store cycle-count ; depart with read-only RTC register selected mov al, #0x0D ; select register D out #0x70, al ; in case of access ret ;----------------------------------------------------------------- msg: .ASCII "\n\r " ; report message-string .ASCII "Duration of Real-Time Clock\'s update-cycle: " buf: .ASCII " microseconds \n\n\r" ; output-buffer len: .WORD * - msg ; length of the message att: .BYTE 0x0E ; video attribute-byte ;----------------------------------------------------------------- ;----------------------------------------------------------------- display_microseconds: ; convert update-cycle's duration to a decimal value mov eax, micro_secs ; get duration (in us) lea di, buf+4 ; point to output buffer call ax2dec ; conversion to decimal ; display our report on the RTC update-cycle's duration mov ax, ds ; address data segment mov es, ax ; with ES register mov ah, #0x0F ; display-page in BH int 0x10 ; request BIOS service mov ah, #0x03 ; cursor locn in DH, DL int 0x10 ; request BIOS service lea bp, msg ; setup message offset mov cx, len ; setup message length mov bl, att ; setup display colors mov ax, #0x1301 ; write_string function int 0x10 ; request BIOS service ret ;----------------------------------------------------------------- ax2dec: pusha mov bx, #10 ; decimal-system radix mov cx, #5 ; maximum digit-count .L0: xor dx, dx ; setup 32-bit dividend div bx ; divide by the radix or dl, #0x30 ; convert to a numeral dec di ; adjust buffer pointer mov [di], dl ; put digit into buffer or ax, ax ; quotient was zero? loopnz .L0 ; no, get another digit popa ret ;----------------------------------------------------------------- .ALIGN 16 ; alignment at paragraph .SPACE 512 ; reserved for stack use tos0: ; label fop top-of-stack ;----------------------------------------------------------------- END