home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD1.mdf / assemblr / library / asm_kit / keybuff.asm < prev    next >
Assembly Source File  |  1983-11-14  |  8KB  |  252 lines

  1. VECTORS       SEGMENT    AT   0H
  2.   ORG          9H*4
  3.   KEYBOARD_INT_VECTOR    LABEL      DWORD
  4.   ORG          16H*4
  5.   KEYBOARD_IO_VECTOR    LABEL      DWORD
  6. VECTORS       ENDS
  7. ;
  8. ROM_BIOS_DATA SEGMENT    AT   40H
  9.   ORG          17H
  10.   KBD_FLAG        DB   ?
  11.   ORG          1AH
  12.   ROM_BUFFER_HEAD    DW   ?
  13.   ROM_BUFFER_TAIL    DW   ?
  14.   KB_BUFFER        DW   16 DUP (?)
  15.   KB_BUFFER_END     LABEL      WORD
  16. ROM_BIOS_DATA ENDS
  17. ;
  18. CODE_SEG      SEGMENT
  19.           ASSUME    CS:CODE_SEG
  20.           ORG    100H
  21.   BEGIN:      JMP    INIT_VECTORS        ;Initialize vectors and attach to
  22. ;                         DOS
  23.   ROM_KEYBOARD_INT    DD            ;Address for ROM routine
  24.   ROM_KEYBOARD_IO    DD
  25.   BUFFER_HEAD        DW   OFFSET KEYBOARD_BUFFER
  26.   BUFFER_TAIL        DW   OFFSET KEYBOARD_BUFFER
  27.   KEYBOARD_BUFFER    DW   160 DUP (0)    ;159 character input buffer
  28.   KEYBOARD_BUFFER_END    LABEL      WORD
  29. ;
  30. ; This procedure sends a short beep when the buffer fills:
  31. ;
  32.   KB_CONTROL        EQU  61H        ;Control bits for keyboard and
  33. ;                         speaker
  34. ERROR_BEEP        PROC NEAR
  35.           PUSH    AX
  36.           PUSH    BX
  37.           PUSH    CX
  38.           PUSHF                ;Save the old interrupt enable flag
  39.           CLI                ;Turn off beep during interrupt
  40.           MOV    BX,30            ;Number of cycles for 1/8 sec beep
  41.           IN    AL,KB_CONTROL        ;Get control info from speaker port
  42.           PUSH    AX            ;Save the control information
  43.   START_OF_ONE_CYCLE:
  44.           AND    AL,0FCH         ;Turn off the speaker
  45.           OUT    KB_CONTROL,AL
  46.           MOV    CX,60            ;Delay for one half cycle
  47.   OFF_LOOP:   LOOP    OFF_LOOP
  48.           OR    AL,2            ;Turn on the speaker
  49.           OUT    KB_CONTROL,AL
  50.           MOV    CX,60            ;Delay for second half of cycle
  51.   ON_LOOP:    LOOP    ON_LOOP
  52.           DEC    BX            ;200 cycles yet?
  53.           JNZ    START_OF_ONE_CYCLE
  54.           POP    AX            ;Recover old keyboard information
  55.           OUT    KB_CONTROL,AL
  56.           POPF                ;Restore interrupt flag
  57.           POP    CX
  58.           POP    BX
  59.           POP    AX
  60.           RET
  61. ERROR_BEEP        ENDP
  62. ;
  63. ; This procedure checks the ROM keyboard buffer to see if some program tried to
  64. ; clear this buffer.  We know it's been cleared when the ROM tail and header
  65. ; overlap.  Normally, the new procedures below keep the dummy character,
  66. ; word 0, in the buffer.
  67. ;
  68. ; Uses BX,DS
  69. ; Writes:     BUFFER_HEAD, BUFFER_TAIL, ROM_BUFFER_HEAD, ROM_BUFFER_TAIL
  70. ; Reads:      KEYBOARD_BUFFER, KB_BUFFER
  71. ;
  72. CHECK_CLEAR_BUFFER    PROC NEAR
  73.           ASSUME    DS:ROM_BIOS_DATA
  74.           MOV    BX,ROM_BIOS_DATA    ;Establish pointer to BIOS data
  75.           MOV    DS,BX
  76.           CLI                ;Turn of interrupts during check
  77.           MOV    BX,ROM_BUFFER_HEAD  ;Check to see if buffer cleared
  78.           CMP    BX,ROM_BUFFER_TAIL  ;Is the buffer empty?
  79.           JNE    BUFFER_OK        ;No, then everything is OK
  80. ;                         Yes, then clear internal buffer
  81.           MOV    BX,OFFSET KB_BUFFER ;Reset buffer with word 0 in buffer
  82.           MOV    ROM_BUFFER_HEAD,BX
  83.           ADD    BX,2
  84.           MOV    ROM_BUFFER_TAIL,BX
  85.           ASSUME    DS:CODE_SEG
  86.           MOV    BX,CS
  87.           MOV    DS,BX
  88.           MOV    BX,OFFSET KEYBOARD_BUFFER    ;Reset internal buffer
  89.           MOV    BUFFER_HEAD,BX
  90.           MOV    BUFFER_TAIL,BX
  91.   BUFFER_OK:
  92.           ASSUME    DS:CODE_SEG
  93.           STI                ;Interrupts back on
  94.           RET
  95. CHECK_CLEAR_BUFFER    ENDP
  96. ;
  97. ; This procedure intercepts the keyboard interrupt and moves any new characters
  98. ; to the internal, 80 character buffer
  99. ;
  100. INTERCEPT_KEYBOARD_INT    PROC NEAR
  101.           ASSUME    DS:NOTHING
  102.           PUSH    DS
  103.           PUSH    SI
  104.           PUSH    BX
  105.           PUSH    AX
  106.           CALL    CHECK_CLEAR_BUFFER  ;Check for buffer cleared
  107.           PUSHF
  108.           CALL    ROM_KEYBOARD_INT    ;Read scan code with BIOS routines
  109. ;
  110. ; Transfer any characters to the internal buffer
  111. ;
  112.           ASSUME    DS:ROM_BIOS_DATA
  113.           MOV    BX,ROM_BIOS_DATA
  114.           MOV    DS,BX
  115.           MOV    SI,BUFFER_TAIL
  116.           MOV    BX,ROM_BUFFER_HEAD  ;Check if real character in buffer
  117.           ADD    BX,2            ;Skip over dummy character
  118.           CMP    BX,OFFSET KB_BUFFER_END
  119.           JB    DONT_WRAP        ;No need to wrap pointer
  120.           MOV    BX,OFFSET KB_BUFFER
  121.   DONT_WRAP:
  122.           CMP    BX,ROM_BUFFER_TAIL  ;Is there a real character?
  123.           JE    NO_NEW_CHARACTERS   ;No, then return to caller
  124.           MOV    AX,[BX]         ;Yes, move char to internal buffer
  125.           MOV    CS:[SI],AX
  126.           ADD    SI,2            ;Move to next position
  127.           CMP    SI,OFFSET KEYBOARD_BUFFER_END
  128.           JB    NOT_AT_END
  129.           MOV    SI,OFFSET KEYBOARD_BUFFER
  130.   NOT_AT_END:
  131.           CMP    SI,BUFFER_HEAD        ;Buffer overrun?
  132.           JNE    WRITE_TO_BUFFER     ;Yes, beep and throw out character
  133.           CALL    ERROR_BEEP
  134.           JMP    SHORT NOT_AT_KB_END
  135.   WRITE_TO_BUFFER:
  136.           MOV    BUFFER_TAIL,SI
  137.   NOT_AT_KB_END:
  138.           MOV    ROM_BUFFER_HEAD,BX
  139. ;
  140. ; See if [Ctrl] + [Alt] pushed and clear buffer if so
  141. ;
  142.   NO_NEW_CHARACTERS:
  143.           MOV    AL,KBD_FLAG        ;Get status of shift keys into AL
  144.           AND    AL,0CH            ;Isolate Ctrl and Alt shift flags
  145.           CMP    AL,0CH            ;Both Ctrl and Alt keys pressed?
  146.           JNE    DONT_CLEAR_BUFFER   ;No, so don't clear buffer
  147.           MOV    AX,BUFFER_TAIL        ;Yes, so clear buffer
  148.           MOV    BUFFER_HEAD,AX
  149.   DONT_CLEAR_BUFFER:
  150.           POP    AX
  151.           POP    BX
  152.           POP    SI
  153.           POP    DS
  154.           IRET
  155. INTERCEPT_KEYBOARD_INT    ENDP
  156. ;
  157. ; This procedure replaces the ROM BIOS routines for reading a character
  158. ;
  159.           ASSUME    DS:CODE_SEG
  160. INTERCEPT_KEYBOARD_IO    PROC FAR
  161.           STI                ;Interrupts back on
  162.           PUSH    DS            ;Save current DS
  163.           PUSH    BX            ;Save BX temporarily
  164.           CALL    CHECK_CLEAR_BUFFER  ;Check for buffer cleared
  165.           MOV    BX,CS            ;Establish pointer to Data Area
  166.           MOV    DS,BX
  167.           OR    AH,AH            ;AH = 0?
  168.           JZ    READ_CHARACTER        ;Yes, read a character
  169.           DEC    AH            ;AH = 1?
  170.           JZ    READ_STATUS        ;Yes, return the status
  171.           DEC    AH            ;AH = 2?
  172.           JZ    READ_SHIFT_STATUS   ;Yes, return the shift status
  173.           POP    BX            ;Ignore other function numbers
  174.           POP    DS
  175.           IRET
  176. ;
  177. ; Read the character
  178. ;
  179.   READ_CHARACTER:                ;ASCII Read
  180.           STI                ;Interrupts back on
  181.           NOP                ;Allow an interrupt to occur
  182.           CLI                ;Interrupts back off
  183.           MOV    BX,BUFFER_HEAD        ;Get pointer to head of buffer
  184.           CMP    BX,BUFFER_TAIL        ;Test end of buffer
  185.           JE    READ_CHARACTER        ;Loop until something appears
  186.           MOV    AX,[BX]         ;Get scan code and ASCII code
  187.           ADD    BX,2            ;Move to next word in buffer
  188.           CMP    BX,OFFSET KEYBOARD_BUFFER_END      ;At end of buffer?
  189.           JNE    SAVE_POINTER        ;No, continue
  190.           MOV    BX,OFFSET KEYBOARD_BUFFER      ;Yes, reset to start
  191.   SAVE_POINTER:
  192.           MOV    BUFFER_HEAD,BX        ;Store value in variable
  193.           POP    BX
  194.           POP    DS
  195.           IRET                ;Return to caller
  196. ;
  197. ; ASCII status
  198. ;
  199.   READ_STATUS:
  200.           CLI                ;Interrupts off
  201.           MOV    BX,BUFFER_HEAD        ;Get head pointer
  202.           CMP    BX,BUFFER_TAIL        ;If equal then nothing there
  203.           MOV    AX,[BX]
  204.           STI                ;Interrupts back on
  205.           POP    BX            ;Recover registers
  206.           POP    DS
  207.           RET    2            ;Throw away flags
  208. ;
  209. ; Shift status
  210. ;
  211.   READ_SHIFT_STATUS:
  212.           JMP    ROM_KEYBOARD_IO     ;Let ROM routine do this
  213. INTERCEPT_KEYBOARD_IO    ENDP
  214. ;
  215. ; This procedure initializes the interrupt vectors
  216. ;
  217. INIT_VECTORS        PROC NEAR
  218.           ASSUME    DS:VECTORS
  219.           PUSH    DS            ;Save old Data Segment
  220.           MOV    AX,VECTORS        ;Set up Data Segment for vectors
  221.           MOV    DS,AX
  222.           CLI                ;Dont allow interrupts
  223.           MOV    AX,KEYBOARD_INT_VECTOR         ;Save addresses of BIOS
  224.           MOV    ROM_KEYBOARD_INT,AX         ;routines and set up new
  225.           MOV    AX,KEYBOARD_INT_VECTOR[2]    ;KEYBOARD_INT vector
  226.           MOV    ROM_KEYBOARD_INT[2],AX         ;
  227.           MOV    KEYBOARD_INT_VECTOR,OFFSET INTERCEPT_KEYBOARD_INT
  228.           MOV    KEYBOARD_INT_VECTOR[2],CS
  229.           STI                ;allow interrupts again
  230.           MOV    AX,KEYBOARD_IO_VECTOR         ;Set up KEYBOARD_IO vector
  231.           MOV    ROM_KEYBOARD_IO,AX
  232.           MOV    AX,KEYBOARD_IO_VECTOR[2]
  233.           MOV    ROM_KEYBOARD_IO[2],AX
  234.           MOV    KEYBOARD_IO_VECTOR,OFFSET INTERCEPT_KEYBOARD_IO
  235.           MOV    KEYBOARD_IO_VECTOR[2],CS
  236.           ASSUME    DS:ROM_BIOS_DATA    ;Now set up the keyboard buffer,
  237.           MOV    AX,ROM_BIOS_DATA    ;etc.
  238.           MOV    DS,AX
  239.           CLI                ;Dont allow interrupts
  240.           MOV    BX,OFFSET KB_BUFFER
  241.           MOV    ROM_BUFFER_HEAD,BX
  242.           MOV    WORD PTR[BX],0
  243.           ADD    BX,2
  244.           MOV    ROM_BUFFER_TAIL,BX
  245.           STI                ;Allow interrupts again
  246.           MOV    DX,OFFSET INIT_VECTORS         ;End of resident portion
  247.           INT    27H            ;Terminate but stay resident
  248. INIT_VECTORS        ENDP
  249. ;
  250. CODE_SEG        ENDS
  251.           END    BEGIN
  252.