Retro video games delivered to your door every month!
Click above to get retro games delivered to your door ever month!
X-Hacker.org- DOS 5.0 Ref. - Norton Guide http://www.X-Hacker.org [<<Previous Entry] [^^Up^^] [Next Entry>>] [Menu] [About The Guide]

; Miscellaneous DOS I/O macros

        StdIn  = 0000h
        StdOut = 0001h


macro DosCall Function
        if Function LT 100h
        mov     ah,Function
        else
        mov     ax,Function
        endif
        int     21h
        endm

;
; Set character device in binary ("raw") mode
; - disables recognition of ctrl-c, ctrl-p, ctrl-s, ctrl-z
; - disables DOS's editing keys during input from StdIn
; Entry : bx = handle of character device (e.g. StdOut)
; Exit  : cf = 1: error on DOS call
;         cf = 0: char. device in binary mode
; Used  : ax,dx,flags
; Note  : Use SetCooked before program termination to
;         restore the I/O mode of a standard device
;         (handle 0..4) to the default ascii mode.
;
macro SetRaw
        local   ahead
        DosCall 4400h           ; Get Device Data (into dx)
        jc      ahead
        or      dl,20h          ; Bit 5 = 1 sets binary mode
        sub     dh,dh           ; Clear bits 8-15
        DosCall 4401h           ; Set Device Data
        ahead:
        endm

;
; Set character device in ascii ("cooked") mode
; - enables recognition of ctrl-c, ctrl-p, ctrl-s, ctrl-z
; - enables DOS's editing keys during input from StdIn
; Entry : bx = handle of character device (e.g. StdIn)
; Exit  : cf = 1: error on DOS call
;         cf = 0: char. device in ascii mode
; Used  : ax,dx,flags
;
macro SetCooked
        local   ahead
        DosCall 4400h           ; Get Device Data (into dx)
        jc      ahead
        and     dx,11011111b    ; Clear bits 5, 8-15
        DosCall 4401h           ; Set Device Data
        ahead:
        endm

;
; Test redirection of standard input/output
; Entry : Handle = 0 (StdIn) or 1 (StdOut)
; Exit  : cf = 1     Error on DOS call
;         else zf=0  Device is redirected
;              zf=1  Device is not redirected
; Used  : ax,bx,dx,flags
;
macro isDeviceRedirected Handle
        local ahead
        mov     bx,Handle       ; StdIn (Stdout)
        DosCall 4400h           ; Get Device Data (into dx)
        jc      ahead           ; cf set on error
        mov     al,81h + Handle ; 81h (82h)
        and     dl,al           ; Isolate bits 7,0 (7,1)
        cmp     al,dl           ; zf=1 if original device
        ahead:                  ;   attributes, cf=0
        endm

;
; Has a key been pressed?
; Entry : N/A
; Exit  : zf = 1 if no key available
; Used  : flags
;
macro isKey
        push    ax
        DosCall 0Bh             ; Check StdIn status
        test    al,al
        pop     ax
        endm

;
; (Wait for and) Read key from keyboard
; Entry : N/A
; Exit  : zf=0: normal key  : ah = 0, al = ASCII code
;         zf=1: extended key: ah = extended code, al = 0
; Used  : ax,flags
; Note  : ax = 0003h if Ctrl-C/Ctrl-Break pressed.
;         Doesn't display the character read.
;
macro ReadKey
        local ahead
        DosCall 07h             ; Direct console input
        sub     ah,ah
        cmp     al,ah
        jnz     ahead
        DosCall 07h             ; Extended: get 2nd code
        mov     ah,al
        sub     al,al
        ahead:
        endm

;
; Same as ReadKey, but uses fnx 3fh
; Used  : ax,bx,cx,dx,flags
;
macro ReadKey3F
        local ahead
        push    ds
        mov     bx,StdIn
        SetRaw                  ; Set keyboard in binary mode
        mov     dx,ss
        mov     ds,dx
        push    dx
        mov     dx,sp           ; ds:dx -> 1-byte buffer
        mov     cx,1            ;   on the stack
        DosCall 3fh             ; Read Device
        xchg    bx,dx
        mov     al,[bx]
        xchg    bx,dx
        sub     ah,ah           ; Assume normal key code
        cmp     al,ah
        jnz     ahead
        DosCall 3fh             ; Extended: get 2nd code
        xchg    bx,dx
        mov     ah,[bx]
        xchg    bx,dx
        sub     al,al
        ahead:
        pop     dx              ; Clean up stack
        push    ax              ; Save key pressed
        pushf                   ;   and flags
        SetCooked               ; Restore keyboard
        popf                    ;   to ascii mode
        pop     ax
        pop     ds
        endm

;
; Read one line from keyboard (StdIn) into memory buffer,
; permitting the use of DOS's editing keys.
; Entry : ds = segment of Buffer
;         The byte size of Buffer must be >= BufLen
; Exit  : Buffer updated, ax = no. of characters typed
; Used  : ax,bx,cx,dx,flags
; Note  :
;   DOS's line editor is active during input:
;   - F1..F6, left, right, backspace, ins, del, esc, enter
;     available for editing
;   - responds to ctrl-c, ctrl-p, ctrl-s, ctrl-z
;   - pressing F5 or Esc, or typing more characters than can
;     fit within one line will cause line wrap (scroll down)
;   - pressing Enter completes the function
;   - max. 127 characters can be input
;   Input is echoed to StdOut during editing.
;
;   If BufLen = 0, no input is read. If the no. of characters
;   typed is less than BufLen, a CR/LF pair (a CR character,
;   if one less) is returned as the last byte(s) and included
;   in the count. If the no. of characters typed is equal to
;   or greater than BufLen, AX is returned = BufLen, and the
;   rest of the characters (plus a CR/LF pair) remain in the
;   input and must be removed, for example, by flushing the
;   keyboard.
;         
macro ReadLine Buffer, BufLen
        mov     bx,StdIn
        SetCooked               ; Set keyboard in ascii mode
        lea     dx,[&Buffer]
        mov     cx,BufLen
        DosCall 3Fh             ; Read Device
        endm

;
; Write one character to StdOut
; Entry : al = character
; Used  : bx,cx,dx,flags
;
macro WriteCh
        push    ds
        push    ax              ; Store character on stack
        mov     dx,ss
        mov     ds,dx
        mov     dx,sp
        mov     cx,1
        mov     bx,StdOut
        DosCall 40h             ; Write to Handle
        pop     ax
        pop     ds
        endm

;
; Write one CR/LF pair to StdOut
; Entry : N/A
; Used  : al and registers used by WriteCh
;
macro WriteCRLF
        mov     al,0dh
        WriteCh
        mov     al,0ah
        WriteCh
        endm

;
; Write zero-terminated string to StdOut
; Entry : ds = segment of string (AsciizID)
; Exit  : cx = string length
; Used  : ax,bx,cx,dx,flags
;
        EOS = 00h               ; End-of-string marker
macro WriteZ AsciizID
        local count, done
        lea     dx,[&AsciizID]
        mov     al,EOS
        mov     bx,dx
        dec     bx
        count:
        inc     bx
        cmp     al,[bx]
        jnz     count
        mov     cx,bx
        sub     cx,dx
        jz      done
        mov     bx,StdOut
        DosCall 40h             ; Write to Handle
        done:
        endm

;
; Convert binary byte value to hex ascii
; Entry : al = binary value
; Exit  : al = low nibble, ah = high nibble
; Used  : ax,flags
;
macro HexB
        mov     ah,al
        if @Cpu and 2
        shr     al,4
        else
        shr     al,1
        shr     al,1
        shr     al,1
        shr     al,1
        endif
        cmp     al,10d          ; Convert to hex ascii
        sbb     al,69h
        das
        xchg    ah,al           ; ah = converted high nibble
        and     al,0fh          ; Repeat for low nibble
        cmp     al,10d
        sbb     al,69h
        das                     ; al = converted low nibble
        endm

;
; Write binary byte value to StdOut as hex ascii
; Entry : al = binary value
; Used  : ax and registers used by WriteCh
;
macro WriteHexB
        HexB
        push    ax
        mov     al,ah           ; Output high nibble
        WriteCh
        pop     ax              ; Output low nibble
        WriteCh
        endm                                                               Me

See Also: 4400h

Online resources provided by: http://www.X-Hacker.org --- NG 2 HTML conversion by Dave Pearson