; showdate.asm ; ; prints the date and time to stdout ; equivalent to the following C++ program: ; ;#include ;#include ; ;int main() ;{ ; time_t t; ; time(&t); // get the current time ; cout << ctime(&t); // convert to string and print ; return 0; ;} ; ; This code may be assembled and linked using Borland's TASM: ; tasm /la /m2 showdate ; tlink /Tdc showdate ; STDOUT equ 01h ; handle of standard output device DOS_GET_DATE equ 02ah ; get system date DOS_GET_TIME equ 02ch ; get system time DOS_WRITE_HANDLE equ 040h ; write to handle DOS_TERMINATE equ 04ch ; terminate with error code DOSINT macro function, subfunction IFB mov ah,(function AND 0ffh) ELSE mov ax,(function SHL 8) OR (subfunction AND 0ffh) ENDIF int 21h ; invoke DOS function endm MODEL tiny ;.STACK 100h .CODE ;**************************************************************************** ; main ; ; calls showdate routne and exists with 00 error code ; ; Entry: ; ; Exit: ; ; Trashed: ; none ; ;**************************************************************************** main proc far .STARTUP ; sets up DS and stack call showdate ; .EXIT 0 ; return with errcode=0 main endp ;**************************************************************************** ; showdate ; ; fetches the DOS system date, prints it to stdout and exits ; the format of the output is identical to that of the Posix ctime() ; function: ; ; Thu May 11 16:11:30 2000 ; ; The day of week and month are always 3 characters long. The time of ; day is in 24hour form (e.g. 16:11:30 is a few minutes after four in ; the afternoon) and the year is always four digits. The whole thing is ; followed by a newline character (line feed = 0ah), making 25 ; characters total. ; ; Note that ctime() returns 26 characters which is all of the above, ; followed by a terminating NUL char but this program does not emit a ; NUL.) ; ; Entry: ; DS points to segment for our data tables ; ; Exit: ; carry may be set if last write failed ; ; Trashed: ; none ; ;**************************************************************************** showdate proc push ax bx cx dx ; DOSINT DOS_GET_DATE ; ; returns the following ; cx = year (1980-2099) ; dh = month (1-12) == (Jan..Dec) ; dl = day (1-31) ; al = day of week (0-6) == (Sun..Sat) push cx ; push dx ; save the return values ; write the day of week mov dx, offset dayname ; mov cx,3 ; number of bytes to write call WriteSubstring ; ; write the month pop ax ; recall month/day push ax ; and save it again mov al,ah ; isolate just month mov dx, offset monthname - 3 ; monthname array is 1-based mov cx,3 ; number of bytes to write call WriteSubstring ; ; write the day of the month pop ax ; call WriteNumber ; call WriteSpace ; ; write the hour DOSINT DOS_GET_TIME ; ch = hour, cl = min, ; dh = sec, dl = hundredths push dx ; save seconds push cx ; save minutes mov al,ch ; call WriteNumber ; call WriteColon ; ; write the minutes pop ax ; call WriteNumber ; call WriteColon ; ; write the seconds pop ax ; mov al,ah ; call WriteNumber ; call WriteSpace ; ; write the year (century first) pop ax ; xor dx,dx ; clear other reg before divide mov cx,100 ; ax = ax/100, dx = remainder div cx ; push dx ; save remainder call WriteNumber ; ; write the year (year within century) pop ax ; call WriteNumber ; mov dx,offset newlinechar call PrintOne ; pop dx cx bx ax ; restore stack ret ; showdate endp ;**************************************************************************** ; WriteSubstring ; ; writes a short substring to stdout ; specifically, prints CL characters, starting at DS:(DX+CL*AL) ; ; Entry: ; DS:DX ==> pointer to base of string array ; CL = size of each string ; AL = string selector (i.e. which string) ; ; Exit: ; CY set if there was an error writing last byte ; if CY clear, ; AX = 1 (number of bytes written) ; else ; AX = error code ; ; Trashed: ; BX CX DX ; ;**************************************************************************** WriteSubstring proc mul cl ; ax = cl * al add dx,ax ; offset now points to appropriate day string call PrintIt ; WriteSubstring endp ; deliberately fall through ;**************************************************************************** ; WriteSpace ; ; writes a single space character (20h) to stdout ; ; Entry: ; DS points to data table segment ; ; Exit: ; CY set if there was an error writing last byte ; if CY clear, ; AX = 1 (number of bytes written) ; else ; AX = error code ; ; Trashed: ; BX CX DX ; ;**************************************************************************** WriteSpace proc mov dx,offset spacechar; WriteSpace endp ; deliberately fall through ;**************************************************************************** ; PrintOne ; ; prints a single character pointed to by DS:DX ; ; Entry: ; DS:DX ==> points to the character to be printed ; ; Exit: ; CY set if there was an error writing last byte ; if CY clear, ; AX = 1 (number of bytes written) ; else ; AX = error code ; ; Trashed: ; BX CX DX ; ;**************************************************************************** PrintOne proc mov cx,1 ; PrintOne endp ; deliberately fall through ;**************************************************************************** ; PrintIt ; ; prints the passed string to stdout ; ; Entry: ; DS:DX ==> points to string to be printed ; CX = number of bytes to be printed ; ; Exit: ; CY set if there was an error writing to stdout ; if CY clear, ; AX = number of bytes written ; else ; AX = error code ; ; Trashed: ; none ; ;**************************************************************************** PrintIt proc mov bx,STDOUT ; DOSINT DOS_WRITE_HANDLE ; write to the file ret ; PrintIt endp ;**************************************************************************** ; WriteColon ; ; writes a colon character to stdout ; ; Entry: ; DS points to data segment ; ; Exit: ; CY set if there was an error writing to stdout ; if CY clear, ; AX = 1 (number of bytes written) ; else ; AX = error code ; ; Trashed: ; none ; ;**************************************************************************** WriteColon proc mov dx,offset colonchar; jmp PrintOne ; WriteColon endp ;**************************************************************************** ; WriteNumber ; ; prints the number in AL to stdout as two decimal digits ; ; Entry: ; AL = number to be printed. It must be in the range 00-99 ; ; Exit: ; CY set if there was an error writing to stdout ; if CY clear, ; AX = 2 (number of bytes written) ; else ; AX = error code ; ; Trashed: ; BX CX DX ; ;**************************************************************************** WriteNumber proc xor ah,ah ; clear out high half mov cl,10 ; prepare to convert to decimal (base 10) div cl ; divide it out or ax,3030h ; convert to ASCII digits push ds ; remember DS for later push ax ; push converted chars on stack mov dx,ss ; mov ds,dx ; ds = ss mov dx,sp ; print data from stack mov cx,2 ; two characters only call PrintIt ; pop bx ; fix stack pop ds ; restore ds pointer ret ; WriteNumber endp ;.DATA dayname db "SunMonTueWedThuFriSat" monthname db "JanFebMarAprMayJunJulAugSepOctNovDec" spacechar db " " colonchar db ":" newlinechar db 0ah ; in C this is \n end