home *** CD-ROM | disk | FTP | other *** search
/ Programming Languages Suite / ProgLangD.iso / Assembly / KBD_IO.ASM < prev    next >
Assembly Source File  |  1986-10-07  |  13KB  |  413 lines

  1. CGROUP    GROUP    CODE_SEG, DATA_SEG
  2.     ASSUME    CS:CGROUP, DS:CGROUP
  3.  
  4.  
  5. ;-----------------------------------------------------------------------;
  6. ; This file contains procedures for working with the keyboard:        ;
  7. ;                                    ;
  8. ; READ_CHAR            Read a character from the keyboard    ;
  9. ; STRING_TO_UPPER        Converts a string to upper case        ;
  10. ; CHAR_TO_UPPER            Converts a character to upper case    ;
  11. ; READ_STRING            Reads in a string of characters        ;
  12. ; READ_DECIMAL            Reads a decimal number            ;
  13. ; READ_BYTE            Reads a single byte            ;
  14. ; HEX_TO_BYTE            Converts to characters to a hex byte    ;
  15. ; CONVERT_HEX_DIGIT        Converts a hex digit to a nibble    ;
  16. ;-----------------------------------------------------------------------;
  17.  
  18.  
  19. BS    EQU    8            ;Back space character
  20. CR    EQU    13            ;Carriage return character
  21. ESC    EQU    27            ;Escape character
  22.  
  23.  
  24. DATA_SEG    SEGMENT PUBLIC
  25. KEY_BOARD_INPUT    LABEL    BYTE
  26. CHAR_NUM_LIMIT    DB    0        ;Length of input buffer
  27. NUM_CHARS_READ    DB    0        ;Number of characters read
  28. CHARS        DB    80 DUP (0)    ;A buffer for keyboard input
  29. DATA_SEG    ENDS
  30.  
  31. CODE_SEG    SEGMENT PUBLIC
  32.  
  33.  
  34.     PUBLIC    READ_CHAR
  35. ;-----------------------------------------------------------------------;
  36. ; This procedure reads a single character from the keyboard, without    ;
  37. ; echoing it to the screen.                        ;
  38. ;                                    ;
  39. ; Returns:    AL    Character, or 0 for special keys.        ;
  40. ;        AH    Extended code of the special key        ;
  41. ;-----------------------------------------------------------------------;
  42. READ_CHAR    PROC    NEAR
  43.     MOV    AH,7            ;Call for input with no checking
  44.     INT    21h            ;for CTRL_BREAK and no echo.
  45.     OR    AL,AL            ;Is this a special key?
  46.     JNZ    DONE_READ_CHAR        ;No, then we're all done
  47.     INT    21h            ;Yes, then read the extended code
  48.     MOV    AH,AL            ;Save this in AH
  49.     XOR    AL,AL            ;Signal that we have an extended code
  50. DONE_READ_CHAR:
  51.     RET
  52. READ_CHAR    ENDP
  53.  
  54.  
  55.     PUBLIC    STRING_TO_UPPER
  56. ;-----------------------------------------------------------------------;
  57. ; This procedure converts the string, using the DOS format for strings    ;
  58. ; to all upper-case letters.                        ;
  59. ;                                    ;
  60. ;    DS:DX    Address of string buffer.                ;
  61. ;                                    ;
  62. ; Uses:        CHAR_TO_UPPER                        ;
  63. ;-----------------------------------------------------------------------;
  64. STRING_TO_UPPER        PROC    NEAR
  65.     PUSH    AX
  66.     PUSH    BX
  67.     PUSH    CX
  68.     MOV    BX,DX
  69.     INC    BX            ;Point to character count
  70.     MOV    CL,[BX]            ;Character count in 2nd byte of buffer
  71.     XOR    CH,CH            ;Clear upper byte of count
  72. UPPER_LOOP:
  73.     INC    BX            ;Point to next character in buffer
  74.     MOV    AL,[BX]            ;Get one character from the string
  75.     CALL    CHAR_TO_UPPER        ;Convert to upper-case letter
  76.     MOV    [BX],AL            ;Save this character back to the string
  77.     LOOP    UPPER_LOOP
  78.     POP    CX
  79.     POP    BX
  80.     POP    AX
  81.     RET
  82. STRING_TO_UPPER        ENDP
  83.  
  84.  
  85.     PUBLIC    CHAR_TO_UPPER
  86. ;-----------------------------------------------------------------------;
  87. ; This procedure converts a single character to upper case.        ;
  88. ;                                    ;
  89. ; On entry:    AL    Character to convert                ;
  90. ; Returns:    AL    Upper-case version of the letter        ;
  91. ;-----------------------------------------------------------------------;
  92. CHAR_TO_UPPER    PROC    NEAR
  93.     CMP    AL,'a'            ;Is this a lower-case letter?
  94.     JB    NOT_LOWER        ;No, then we're all done
  95.     CMP    AL,'z'            ;Is this a lower-case letter?
  96.     JA    NOT_LOWER        ;No, then we're all done
  97.     ADD    AL,'A'-'a'        ;Convert to upper-case letter
  98. NOT_LOWER:
  99.     RET
  100. CHAR_TO_UPPER    ENDP
  101.  
  102.  
  103.     PUBLIC    READ_STRING
  104.     EXTRN    WRITE_CHAR:NEAR
  105. ;-----------------------------------------------------------------------;
  106. ; This procedure performs a function very similar to the DOS 0AH    ;
  107. ; function.  But this function will return a special character if a    ;
  108. ; function or key pad key is pressed -- no return for these keys.  And    ;
  109. ; ESC will erase the input and start over again.            ;
  110. ;                                    ;
  111. ;    DS:DX    Address for keyboard buffer.  The first byte must    ;
  112. ;        contain the maximum number of characters to read (plus    ;
  113. ;        one for the return).  And the second byte will be used    ;
  114. ;        by this procedure to return the number of characters    ;
  115. ;        actually read.                        ;
  116. ;            0    No characters read            ;
  117. ;            -1    One special character read        ;
  118. ;            otherwise number actually read (not including    ;
  119. ;                return key).                ;
  120. ;                                    ;
  121. ; Uses:        READ_CHAR, BACK_SPACE, WRITE_CHAR            ;
  122. ;-----------------------------------------------------------------------;
  123. READ_STRING    PROC    NEAR
  124.     PUSH    AX
  125.     PUSH    BX
  126.     PUSH    SI
  127.     MOV    SI,DX            ;Use SI for index register and
  128. START_OVER:
  129.     MOV    BX,2            ;BX for offset to beginning of buffer
  130.     CALL    READ_CHAR
  131.     OR    AL,AL            ;Is character extended ASCII?
  132.     JZ    EXTENDED        ;Yes, then handle it.
  133. NOT_EXTENDED:                ;Extnd char is error unless buff empty
  134.     CMP    AL,CR            ;Is this a carriage return?
  135.     JE    END_INPUT        ;Yes, we are done with input
  136.     CMP    AL,BS            ;Is it a back space character?
  137.     JNE    NOT_BS            ;Nope
  138.     CALL    BACK_SPACE        ;Yes, delete character
  139.     CMP    BL,2            ;Is buffer empty?
  140.     JE    START_OVER        ;Yes, can now read extended ASCII again
  141.     JMP    SHORT READ_NEXT_CHAR    ;No, continue reading normal characters
  142. NOT_BS:    CMP    AL,ESC            ;Is it an ESC -- purge buffer?
  143.     JE    PURGE_BUFFER        ;Yes, then purge the buffer
  144.     CMP    BL,[SI]            ;Check to see if buffer is full
  145.     JA    BUFFER_FULL        ;Buffer is full
  146.     MOV    [SI+BX],AL        ;Else save char in buffer
  147.     INC    BX            ;Point to next free character in buffer
  148.     PUSH    DX
  149.     MOV    DL,AL            ;Echo character to screen
  150.     CALL    WRITE_CHAR
  151.     POP    DX
  152. READ_NEXT_CHAR:
  153.     CALL    READ_CHAR
  154.     OR    AL,AL            ;An extended ASCII char is not valid
  155.                     ;when the buffer is not empty.
  156.     JNZ    NOT_EXTENDED        ;Char is valid
  157.                     ;Char is extended, signal error
  158.  
  159. ;-----------------------------------------------;
  160. ; Signal an error condition by sending a beep    ;
  161. ; character to the display: chr$(7).        ;
  162. ;-----------------------------------------------;
  163. SIGNAL_ERROR:
  164.     PUSH    DX
  165.     MOV    DL,7            ;Sound the bell by writing chr$(7)
  166.     MOV    AH,2
  167.     INT    21H
  168.     POP    DX
  169.     JMP    SHORT READ_NEXT_CHAR    ;Now read next character.
  170.  
  171. ;-----------------------------------------------;
  172. ; Empty the string buffer and erase all the    ;
  173. ; characters displayed on the screen.        ;
  174. ;-----------------------------------------------;
  175. PURGE_BUFFER:
  176.     PUSH    CX
  177.     MOV    CL,[SI]            ;Backspace over maximum number of
  178.     XOR    CH,CH
  179. PURGE_LOOP:                ;characters in buffer.  BACK_SPACE
  180.     CALL    BACK_SPACE        ;will keep the cursor from moving too
  181.     LOOP    PURGE_LOOP        ;far back.
  182.     POP    CX
  183.     JMP    START_OVER        ;Can now read extended ASCII characters
  184.                     ;since the buffer is empty
  185.  
  186. ;-----------------------------------------------;
  187. ; The buffer was full, so can't read another    ;
  188. ; character.  Send a beep to alert user of    ;
  189. ; buffer full condition.            ;
  190. ;-----------------------------------------------;
  191. BUFFER_FULL:
  192.     JMP    SHORT SIGNAL_ERROR    ;If buffer full, just beep.
  193.  
  194. ;-----------------------------------------------;
  195. ; Read the extended ASCII code and place this    ;
  196. ; in the buffer as the only character, then    ;
  197. ; return -1 as the number of characters read.    ;
  198. ;-----------------------------------------------;
  199. EXTENDED:
  200.     MOV    [SI+2],AH        ;Place extended code into the buffer
  201.     MOV    BL,0FFH            ;Num chars read = -1 for special
  202.     JMP    SHORT END_STRING
  203.  
  204. ;-----------------------------------------------;
  205. ; Save the count of the number of characters    ;
  206. ; read and return.                ;
  207. ;-----------------------------------------------;
  208. END_INPUT:                ;Done with input.
  209.     SUB    BL,2            ;Count of characters read
  210. END_STRING:
  211.     MOV    [SI+1],BL        ;Return number of chars read
  212.     POP    SI
  213.     POP    BX
  214.     POP    AX
  215.     RET
  216. READ_STRING    ENDP
  217.  
  218.  
  219.     PUBLIC    BACK_SPACE
  220.     EXTRN    WRITE_CHAR:NEAR
  221. ;-----------------------------------------------------------------------;
  222. ; This procedure deletes characters, one at a time, from the buffer and    ;
  223. ; the screen when the buffer is not empty.  BACK_SPACE simply returns    ;
  224. ; when the buffer is empty.                        ;
  225. ;    DS:SI+BX    most recent character still in buffer.        ;
  226. ;                                    ;
  227. ; Uses:        WRITE_CHAR                        ;
  228. ;-----------------------------------------------------------------------;
  229. BACK_SPACE    PROC    NEAR        ;Delete one character
  230.     PUSH    AX
  231.     PUSH    DX
  232.     CMP    BX,2            ;Is buffer empty
  233.     JE    END_BS            ;Yes, read the next character
  234.     DEC    BX            ;remove one character from buffer
  235.     MOV    AH,2            ;Remove character from screen
  236.     MOV    DL,BS
  237.     INT    21H
  238.     MOV    DL,20H            ;Write space there
  239.     CALL    WRITE_CHAR
  240.     MOV    DL,BS            ;Back-up again
  241.     INT    21H
  242. END_BS:    POP    DX
  243.     POP    AX
  244.     RET
  245. BACK_SPACE    ENDP
  246.  
  247.  
  248.     PUBLIC    READ_DECIMAL
  249. ;-----------------------------------------------------------------------;
  250. ; This procedure takes the output buffer of READ_STRING and converts    ;
  251. ; the string of decimal digits to a word.                ;
  252. ;                                    ;
  253. ;    AX    Word converted from decimal                ;
  254. ;    CF    Set if error, clear if no error                ;
  255. ;                                    ;
  256. ; Uses:        READ_STRING                        ;
  257. ; Reads:    KEY_BOARD_INPUT, etc.                    ;
  258. ;-----------------------------------------------------------------------;
  259. READ_DECIMAL    PROC    NEAR
  260.     PUSH    BX
  261.     PUSH    CX
  262.     PUSH    DX
  263.     MOV    CHAR_NUM_LIMIT,6    ;Max number is 5 digits (65535)
  264.     LEA    DX,KEY_BOARD_INPUT
  265.     CALL    READ_STRING
  266.     MOV    CL,NUM_CHARS_READ    ;Get number of characters read
  267.     XOR    CH,CH            ;Set upper byte of count to zero
  268.     CMP    CL,0            ;Return error if no characters read
  269.     JLE    BAD_DECIMAL_DIGIT    ;No chars read, signal error
  270.     XOR    AX,AX            ;Start with number set to zero
  271.     XOR    BX,BX            ;Start at beginning of string
  272. CONVERT_DIGIT:
  273.     MOV    DX,10            ;Multiply number by 10
  274.     MUL    DX            ;Multiply AX by 10
  275.     JC    BAD_DECIMAL_DIGIT    ;CF set if MUL overflowed one word
  276.     MOV    DL,CHARS[BX]        ;Get the next digit
  277.     SUB    DL,'0'            ;And convert to a nibble (4 bits)
  278.     JS    BAD_DECIMAL_DIGIT    ;Bad digit if < 0.
  279.     CMP    DL,9            ;Is this a bad digit?
  280.     JA    BAD_DECIMAL_DIGIT    ;Yes
  281.     ADD    AX,DX            ;No, so add it to number
  282.     INC    BX            ;Point to next character
  283.     LOOP    CONVERT_DIGIT        ;Get the next digit
  284. DONE_DECIMAL:
  285.     POP    DX
  286.     POP    CX
  287.     POP    BX
  288.     RET
  289. BAD_DECIMAL_DIGIT:
  290.     STC                ;Set carry to signal error
  291.     JMP    DONE_DECIMAL
  292. READ_DECIMAL    ENDP
  293.  
  294.  
  295.     PUBLIC    READ_BYTE
  296. ;-----------------------------------------------------------------------;
  297. ; This procedure reads either a single ASCII character.  This is just    ;
  298. ; a test version of READ_BYTE.                        ;
  299. ;                                    ;
  300. ; Returns byte in    AL    Character code (unless AH = 0)        ;
  301. ;            AH    1 if read ASCII char            ;
  302. ;                0 if no characters read            ;
  303. ;                -1 if read a special key        ;
  304. ;                                    ;
  305. ; Uses:        HEX_TO_BYTE, STRING_TO_UPPER, READ_STRING        ;
  306. ; Reads:    KEY_BOARD_INPUT, etc.                    ;
  307. ;-----------------------------------------------------------------------;
  308. READ_BYTE    PROC    NEAR
  309.     PUSH    DX
  310.     MOV    CHAR_NUM_LIMIT,3    ;Allow only two characters (plus enter)
  311.     LEA    DX,KEY_BOARD_INPUT
  312.     CALL    READ_STRING
  313.     CMP    NUM_CHARS_READ,1    ;See how many characters
  314.     JE    ASCII_INPUT        ;Just one, treat as ASCII character
  315.     JB    NO_CHARACTERS        ;Only enter key hit
  316.     CMP    NUM_CHARS_READ,0FFH    ;Special function key?
  317.     JE    SPECIAL_KEY        ;Yes.
  318.     CALL    STRING_TO_UPPER        ;No, convert string to upper-case
  319.     LEA    DX,CHARS        ;Address of string to convert
  320.     CALL    HEX_TO_BYTE        ;Convert string from hex to byte
  321.     JC    NO_CHARACTERS        ;Error, so return 'no characters read'
  322.     MOV    AH,1            ;Signal read one character
  323. DONE_READ:
  324.     POP    DX
  325.     RET
  326. NO_CHARACTERS:
  327.     XOR    AH,AH            ;Set to 'no characters read'
  328.     JMP    DONE_READ
  329. ASCII_INPUT:
  330.     MOV    AL,CHARS        ;Load character read
  331.     MOV    AH,1            ;Signal read one character
  332.     JMP    DONE_READ
  333. SPECIAL_KEY:
  334.     MOV    AL,CHARS[0]        ;Return the scan code
  335.     MOV    AH,0FFH            ;Signal special key with -1
  336.     JMP    DONE_READ
  337. READ_BYTE    ENDP
  338.  
  339.  
  340.     PUBLIC    HEX_TO_BYTE
  341. ;-----------------------------------------------------------------------;
  342. ; This procedure converts the two characters at DS:DX from hex to one    ;
  343. ; byte.                                    ;
  344. ;                                    ;
  345. ;    DS:DX    Address of two characters for hex number        ;
  346. ;Returns:                                ;
  347. ;    AL    Byte                            ;
  348. ;    CF    Set for error, clear if no error            ;
  349. ; AH changed                                ;
  350. ;                                    ;
  351. ; Uses:        CONVERT_HEX_DIGIT                    ;
  352. ;-----------------------------------------------------------------------;
  353. HEX_TO_BYTE    PROC    NEAR
  354.     PUSH    BX
  355.     PUSH    CX
  356.     MOV    BX,DX            ;Put address in BX for indirect addr
  357.     MOV    AL,[BX]            ;Get first digit
  358.     CALL    CONVERT_HEX_DIGIT
  359.     JC    BAD_HEX            ;Bad hex digit if carry set
  360.     MOV    CX,4            ;Now multiply by 16
  361.     SHL    AL,CL
  362.     MOV    AH,AL            ;Retain a copy
  363.     INC    BX            ;Get second digit
  364.     MOV    AL,[BX]
  365.     CALL    CONVERT_HEX_DIGIT
  366.     JC    BAD_HEX            ;Bad hex digit if carry set
  367.     OR    AL,AH            ;Combine two nibbles
  368.     CLC                ;Clear carry for no error
  369. DONE_HEX:
  370.     POP    CX
  371.     POP    BX
  372.     RET
  373. BAD_HEX:
  374.     STC                ;Set carry for error
  375.     JMP    DONE_HEX
  376. HEX_TO_BYTE    ENDP
  377.  
  378.  
  379.     PUBLIC    CONVERT_HEX_DIGIT
  380. ;-----------------------------------------------------------------------;
  381. ; This procedure converts a character from ASCII (hex) to a nibble (4    ;
  382. ; bits).                                ;
  383. ;                                    ;
  384. ;        AL    character to convert                ;
  385. ; Returns:    AL    nibble                        ;
  386. ;        CF    Set for error, cleared otherwise        ;
  387. ;-----------------------------------------------------------------------;
  388. CONVERT_HEX_DIGIT    PROC    NEAR
  389.     CMP    AL,'0'            ;Is it a legal digit?
  390.     JB    BAD_DIGIT        ;Nope
  391.     CMP    AL,'9'            ;Not sure yet
  392.     JA    TRY_HEX            ;Might be hex digit
  393.     SUB    AL,'0'            ;Is decimal digit, convert to nibble
  394.     CLC                ;Clear the carry, no error
  395.     RET
  396. TRY_HEX:
  397.     CMP    AL,'A'            ;Not sure yet
  398.     JB    BAD_DIGIT        ;Not hex
  399.     CMP    AL,'F'            ;Not sure yet
  400.     JA    BAD_DIGIT        ;Not hex
  401.     SUB    AL,'A'-10        ;Is hex, convert to nibble
  402.     CLC                ;Clear the carry, no error
  403.     RET
  404. BAD_DIGIT:
  405.     STC                ;Set the carry, error
  406.     RET
  407. CONVERT_HEX_DIGIT    ENDP
  408.  
  409.  
  410. CODE_SEG    ENDS
  411.  
  412.     END
  413.