//------------------------------------------------------------------- // cmosdump.s // // This program inputs and displays the current contents of the // Real-Time Clock's battery-powered memory-storage locations. // It relies upon a side-effect of the 'open()' function in our // 'dosio.c' device-driver to adjust this task's IOPL so it can // execute the CPU's privileged 'in' and 'out' instructions. // // assemble using: $ as cmosdump.s -o cmosdump.o // and link using: $ ld cmosdump.o -o cmosdump // // programmer: ALLAN CRUSE // written on: 03 MAY 2006 //------------------------------------------------------------------- # manifest constants .equ sys_exit, 1 .equ sys_write, 4 .equ sys_open, 5 .equ STDOUT, 1 .equ STDERR, 2 .equ O_RDWR, 3 .section .data device: .asciz "/dev/dos" # null-terminated filename hexnum: .ascii "0123456789ABCDEF" # the hexadecimal numerals newlin: .ascii "\n\n" # ascii-codes for newlines errmsg: .ascii "could not open '/dev/dos' device-file\n" errlen: .int . - errmsg # length for error-message .section .bss rtcbuf: .space 128 # storage for RTC's values outbuf: .space 8 # .section .text _start: # open the '/dev/dos' device-file mov $sys_open, %eax # system-call ID-number lea device, %ebx # device-file pathname mov $O_RDWR, %ecx # flags for access-mode int $0x80 # enter Linux kernel cmp $-1, %eax # system-call succeeded? jne input # yes, we can do in/out # show error-message and exit mov $sys_write, %eax # system-call ID-number mov $STDERR, %ebx # device-file ID-number lea errmsg, %ecx # message-string address mov errlen, %edx # message-string length int $0x80 # enter Linux kernel jmp exit # jump to program exit input: # loop to read the entries from CMOS ram xor %edi, %edi # initialize array-index mov $128, %ecx # initialize loop-counter nxelt: mov %edi, %eax # select the RTC register outb %al, $0x70 # output to Address Port inb $0x71, %al # input from Data Port mov %al, rtcbuf(%edi) # store as array entry inc %edi # increment array-index loop nxelt # again for other entries # loop to display the entries from CMOS ram xor %esi, %esi # initialize array-index nxlin: # start a new line if array-index is a multiple of 16 test $0x0F, %esi # sixteen divides index? jnz nxitm # no, continue same line mov $sys_write, %eax # system-call ID-number mov $STDOUT, %ebx # device-file ID-number lea newlin, %ecx # address of string mov $1, %edx # length of string int $0x80 # enter Linux kernel nxitm: lea outbuf, %edi # setup the buffer pointer movb $' ', (%edi) # store a blank character inc %edi # and advance the pointer mov rtcbuf(%esi), %dl # fetch next array-element .rept 2 rol $4, %dl # next nybble to low bits mov %dl, %al # and copy nybble to AL andl $0x0F, %eax # isolate nybble's bits movb hexnum(%eax), %al # lookup nybble's digit mov %al, (%edi) # store digit in buffer inc %edi # and advance the pointer .endr mov $sys_write, %eax # system-call ID-number mov $STDOUT, %ebx # device-file ID-number lea outbuf, %ecx # string's address mov $3, %edx # string's length int $0x80 # enter Linux kernel inc %esi # increment array-index cmp $128, %esi # beyond array bounds? jb nxlin # no, show next element mov $sys_write, %eax # system-call ID-number mov $STDOUT, %ebx # device-file ID-number lea newlin, %ecx # string's address mov $2, %edx # string's length int $0x80 # enter Linux kernel exit: # terminate this program mov $sys_exit, %eax # system-call ID-number mov $0, %ebx # device-file ID-number int $0x80 # enter Linux kernel .global _start # make entry-point visible .end # nothing more to assemble