home *** CD-ROM | disk | FTP | other *** search
/ Programming Languages Suite / ProgLangD.iso / Assembly / KBD_IO24.ASM < prev    next >
Assembly Source File  |  1986-09-25  |  11KB  |  361 lines

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