home *** CD-ROM | disk | FTP | other *** search
- title UNIXCLIB - UNIX/C FUNCTIONS FOR PC/MS-DOS
- page 55,131
-
- ; UNIXCLIB - Routines for providing UNIX-like functions for PC/MS-DOS
- ;
- ; Date of last update: 10/9/85
- ;
- ; This is a package of routines that
- ;
- ; (1) emulate routines found in the standard C function libraries on
- ; UNIX systems, and/or
- ; (2) help bridge the gap between MS-DOS and Unix.
- ;
- ;
- ; Author credit summary:
- ;
- ; Function Author Organization
- ;
- ; sleep Lawrence B. Afrin Clemson University
- ; file_exists " "
- ; set_jmp " "
- ; long_jmp " "
- ;
- ;
- ; This package was conceived by Lawrence B. Afrin of Clemson University.
- ; Please send all questions, comments, suggestions, and new routines to
- ; LBAFRIN@CLEMSON (CSNet) or LBAFRIN.CLEMSON@CSNET-RELAY (ARPANet). These
- ; routines were principally written for support of DeSmet C, although
- ; they can probably be easily interfaced to any C compiler if you know
- ; the compiler's mechanism(s) or protocol(s) for calling assembler
- ; routines.
- ;
- ; The current catalog of routines in UNIXCLIB.ASM follows:
- ;
- ; sleep(x) functionally equivalent to UNIX sleep(3) -
- ; int x pauses execution for x seconds
- ;
- ; file_exists(s) determines whether the named PC/MS-DOS file
- ; char *s exists - helps in building support for the
- ; UNIX System V O_CREAT feature (create/open
- ; file only if it doesn't already exist)
- ;
- ; long_jmp(j) major enhancement to DeSmet longjmp() -
- ; jmp_buf j; provides functionality identical to the
- ; standard UNIX longjmp() (which DeSmet doesn't)
- ;
- ; set_jmp(j) major enhancement to DeSmet setjmp() -
- ; jmp_buf j; provides functionality identical to the
- ; standard UNIX setjmp() (which DeSmet doesn't)
- ;
- ;
- ; Remember, send your contributions to this library to LBAFRIN@CLEMSON.
- ; I'm happy to receive DeSmet-related and non-DeSmet-related routines for
- ; review. I can usually respond to submissions within a day or two, but
- ; please don't complain if you see my response time lagging. As a
- ; medical student I have to put my academic and patient responsibilities
- ; at a higher priority than the public service of supervising this library.
- ;
- ; -- Larry Afrin
- ; Dept. of Computer Science
- ; Clemson University
-
-
-
- ; Implementation notes for the following 4 routines: All were tested under
- ; MASM v1.00, DeSmet C 2.41, and PC-DOS 3.10. Most versions of MASM and
- ; DeSmet C should work. I expect that PC/MS-DOS 2.x and 3.0 work fine,
- ; too, but I don't think 1.10 will hack it.
-
- ;
- ; DeSmet puts all code segments in the `pgroup' group and all data segments
- ; in the `dgroup' group.
- ;
- pgroup group prog
- dgroup group data
-
- prog segment para public 'prog'
- assume cs:prog,ds:data,es:nothing
-
- public sleep
- public file_exists
- public set_jmp
- public long_jmp
-
- ;
- ; sleep - written by Lawrence B. Afrin of Clemson University
- ; (lbafrin@clemson). Provides UNIX-like sleep(3) functionality.
- ;
- ; calling mechanism is: push <number of seconds to sleep>
- ; call sleep
- ;
- ; note that this limits the maximum sleep time to 65535 seconds
- sleep proc near
- push bp ; enter in a DeSmet-approved (more or
- mov bp,sp ; less) manner
- sub sp,10
- push ax ; save regs
- push bx
- push cx
- push dx
- cmp ax,0 ; test for sleep(x) where x <= 0
- jg sleep8
- jmp sleep7 ; ignore call if such is the case
- sleep8: mov ah,2ch ; get the current time from DOS
- int 21h
- mov [bp-2],cx ; [bp-4:bp-2] hold the original time
- mov [bp-4],dx
- mov [bp-6],cx ; [bp-8:bp-6] will hold the target
- mov [bp-8],dx ; time (when we end our sleep)
- mov word ptr [bp-10],60
- mov ax,[bp+4]
- xor dx,dx
- div word ptr [bp-10]
- add dl,[bp-7] ; add num of secs (mod 60) to orig secs
- cmp dl,60
- jl sleep0
- sub dl,60 ; overflow of targ secs, so take mod 60
- inc byte ptr [bp-6] ; and increment target minutes
- sleep0: mov [bp-7],dl
- cmp ax,0
- je sleep3
- xor dx,dx
- div word ptr [bp-10]
- add dl,[bp-6] ; add num of mins (mod 60) to targ mins
- cmp dl,60
- jl sleep1
- sub dl,60 ; overflow of targ mins, so take mod 60
- inc byte ptr [bp-5] ; and increment target hours
- sleep1: mov [bp-6],dl
- cmp ax,0
- je sleep3
- add al,[bp-5]
- cmp al,24
- jl sleep2
- sub al,24
- sleep2: mov [bp-5],al ; by now we know our target time
- ; now let's start looping until we hit
- ; the target time
- sleep3: mov ah,2ch ; top of loop: get current time
- int 21h
- mov ax,[bp-6]
- mov bx,[bp-8]
- cmp cx,[bp-2] ; if current time >= original time (don't have
- jg sleep4 ; to worry about 24 hour wraparound because
- jl sleep6 ; max number of sleep secs = 65535, which
- cmp dx,[bp-4] ; is < 24 hours (= 86400))
- jl sleep6
- sleep4: cmp ax,[bp-2] ; then if target time <= original time
- jg sleep5
- jl sleep3
- cmp bx,[bp-4]
- jle sleep3 ; then loop again
- sleep5: cmp cx,ax ; else if current time >= target time
- jg sleep7 ; then exit
- jl sleep3 ; else loop again
- cmp dx,bx
- jl sleep3
- jmp sleep7
- sleep6: cmp ax,[bp-2] ; else if target time > original time
- jg sleep7
- cmp bx,[bp-4]
- jg sleep7 ; then exit
- cmp cx,ax ; else if current time >= target time
- jg sleep7 ; then exit
- jl sleep3 ; else loop again
- cmp dx,bx
- jl sleep3
- sleep7: pop dx ; exit
- pop cx
- pop bx
- pop ax
- mov sp,bp
- pop bp
- ret
- sleep endp
-
-
- ;
- ; file_exists - written by Lawrence B. Afrin of Clemson University
- ; (lbafrin@clemson). Tells caller whether specified PC/MS-DOS file
- ; already exists. Helpful in building higher level file system support
- ; such as for the O_CREAT flag in the UNIX System V open(2) call.
- ;
- ; calling mechanism is: push <address (in data seg) of filename string>
- ; call file_exists
- ;
- ; returns AX = 0 if file does not exist
- ; AX = 1 if file does exist
- ;
- ; Note that file_exists temporarily establishes a new Disk Transfer Address.
- ;
-
- data segment para public 'data'
-
- file_exists_dta db 128 dup (?)
- old_dta_seg dw ?
- old_dta_off dw ?
-
- data ends
-
- file_exists proc near
- push bp ; play DeSmet games
- mov bp,sp
- push bx
- push cx
- push dx
- push es
- mov ah,2fh ; get old dta
- int 21h
- mov old_dta_seg,es ; save old dta
- mov old_dta_off,bx
- mov dx,offset dgroup:file_exists_dta
- mov ah,1ah
- int 21h ; set up temp dta
- mov dx,[bp+4]
- mov ah,4eh
- mov cx,0
- int 21h ; ask DOS if file exists
- mov cx,1 ; assume it does
- cmp ax,0 ; does it?
- je file_exists_x ; yup
- mov cx,0 ; whoops, no it doesn't
- file_exists_x:
- push cx ; save return code
- push ds
- mov dx,old_dta_off
- mov ax,old_dta_seg
- mov ds,ax
- mov ah,1ah
- int 21h ; restore old dta
- pop ds
- pop ax ; restore return code
- pop es
- pop dx
- pop cx
- pop bx
- mov sp,bp
- pop bp
- ret
- file_exists endp
-
-
- ; set_jmp and long_jmp - written by Lawrence B. Afrin of Clemson University
- ; (lbafrin@clemson). Provides UNIX-like setjmp(3) and longjmp(3) function-
- ; ality, significantly extends functionality of DeSmet counterparts.
- ;
- ; Note that the type of the "jmp_buf"-type variable in this implementation
- ; is a three-element one-dimensional integer array. (The C statement would be
- ; "typedef int jmp_buf[3];".
- ;
- ; set_jmp:
- ; calling mechanism is: push <address (in data seg) of jmp_buf var>
- ; call set_jmp
- ;
- ; returns AX = 0
- ;
- ; long_jmp:
- ; calling mechanism is: push <value to be faked as set_jmp return val>
- ; push <address (in data seg) of jmp_buf var>
- ; call long_jmp
- ;
- ; causes a return with AX = "fake return val" to the instruction follow-
- ; ing the call to set_jmp that was made specifying the same jmp_buf
- ; variable
- ;
- ; IMPORTANT NOTES!!!
- ;
- ; (1) These routines are specific for DeSmet C and probably no other C
- ; compilers. They depend heavily on the DeSmet protocol used
- ; to manage stack frames.
- ; (2) The same warnings as in the DeSmet manual apply here. A long_jmp
- ; into a routine containing the corresponding set_jmp, when the
- ; target routine is no longer "active" (i.e., on the stack), has
- ; a totally unguaranteed result.
- ; (3) The performance of these routines under the DeSmet debugger has
- ; not been tested. Use at your own risk!
- ;
- ;
- ; How It Works
- ;
- ; The DeSmet "environment" that needs to be saved and restored by
- ; set_jmp/long_jmp consists of an address to jump/return to, the
- ; current frame pointer (found in BP), and the current stack
- ; pointer (you guessed it, SP). set_jmp saves these values into
- ; the jmp_buf, and long_jmp restores SP and BP and then plays a
- ; trick so that when it returns, it actually is as if the
- ; corresponding set_jmp were returning (except that the return value
- ; is as specified in the call to long_jmp).
- ;
-
- set_jmp proc near
- push bp ; we're going to do this without disturbing
- push bx ; regs except the return value reg, AX
- mov bp,sp ; let's get some addressability here
- mov bx,[bp+6] ; load the jmp_buf address into BX
- mov ax,[bp+4] ; load the target jump address into AX
- mov [bx],ax ; tuck this address away in (int) jmp_buf[0]
- lea ax,[bp+6] ; load into AX the value that we're going to
- ; want to give SP in the long_jmp
- mov [bx+2],ax ; tuck that away in (int) jmp_buf[1]
- mov ax,[bp+2] ; load into AX the BP (frame ptr) we saved above
- mov [bx+4],ax ; save that, too, in (int) jmp_buf[2]
- pop bx ; that's it! now restore regs,
- pop bp
- mov ax,0 ; set the return code
- ret ; and get out of here
- set_jmp endp
-
- long_jmp proc near ; notice that we get away with this without
- ; having to play with any registers not
- ; intimately involved in the concept of
- ; a long_jmp; neat, huh?
- mov bp,sp ; use bp for work variable
- mov ax,[bp+4] ; load long_jmp's 2nd argument as the return val
- mov bp,[bp+2] ; now point bp at the jmp_buf
- mov sp,ds:[bp+2] ; load SP
- push ds:[bp+0] ; push the target address onto the `new' stack
- mov bp,ds:[bp+4] ; load BP
- ; (The stack should now be looking *exactly*
- ; as if it's ready for a NEAR-type return
- ; from the corresponding set_jmp call, except
- ; that AX has the return value specified in
- ; the long_jmp call.)
- ret ; let's get back to work
- long_jmp endp
-
- prog ends
-
- end
-