home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD1.mdf / assemblr / library / nor_asm / kbd_io.asm < prev    next >
Assembly Source File  |  1989-08-13  |  14KB  |  424 lines

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