home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD1.mdf / assemblr / library / nor_asm / kbd_io24.asm < prev    next >
Assembly Source File  |  1989-05-17  |  12KB  |  379 lines

  1. .MODEL    SMALL
  2.  
  3.  
  4. BS    EQU    8            ;Backspace character
  5. CR    EQU    13            ;Carriage-return character
  6. ESCAPE    EQU    27            ;Escape character
  7.  
  8.  
  9. .DATA
  10.  
  11. KEYBOARD_INPUT    LABEL BYTE
  12. CHAR_NUM_LIMIT    DB    0        ;Length of input buffer
  13. NUM_CHARS_READ    DB    0        ;Number of characters read
  14. CHARS        DB    80 DUP (0)    ;A buffer for keyboard input
  15.  
  16. .CODE
  17.  
  18.     PUBLIC    STRING_TO_UPPER
  19. ;-----------------------------------------------------------------------;
  20. ; This procedure converts the stinrg, using the DOS format for strings,    ;
  21. ; to all uppercase letters.                        ;
  22. ;                                    ;
  23. ;    DS:DX    Address of string buffer                ;
  24. ;-----------------------------------------------------------------------;
  25. STRING_TO_UPPER        PROC
  26.     PUSH    AX
  27.     PUSH    BX
  28.     PUSH    CX
  29.     MOV    BX,DX
  30.     INC    BX            ;Point to character count
  31.     MOV    CL,[BX]            ;Character count in 2nd byte of buffer
  32.     XOR    CH,CH            ;Clear upper byte of count
  33. UPPER_LOOP:
  34.     INC    BX            ;Point to next character in buffer
  35.     MOV    AL,[BX]
  36.     CMP    AL,'a'            ;See if it is a lowercase letter
  37.     JB    NOT_LOWER        ;Nope
  38.     CMP    AL,'z'
  39.     JA    NOT_LOWER
  40.     ADD    AL,'A'-'a'        ;Convert to uppercase letter
  41.     MOV    [BX],AL
  42. NOT_LOWER:
  43.     LOOP    UPPER_LOOP
  44.     POP    CX
  45.     POP    BX
  46.     POP    AX
  47.     RET
  48. STRING_TO_UPPER        ENDP
  49.  
  50. ;-----------------------------------------------------------------------;
  51. ; This procedure converts a character from ASCII (hex) to a nibble (4    ;
  52. ; bits).                                ;
  53. ;                                    ;
  54. ;        AL    Character to convert                ;
  55. ; Returns:    AL    Nibble                        ;
  56. ;        DF    Set for error, cleared otherwise        ;
  57. ;-----------------------------------------------------------------------;
  58. CONVERT_HEX_DIGIT    PROC
  59.     CMP    AL,'0'            ;Is it a legal digit?
  60.     JB    BAD_DIGIT        ;Nope
  61.     CMP    AL,'9'            ;Not sure yet
  62.     JA    TRY_HEX            ;Might be hex digit
  63.     SUB    AL,'0'            ;Is decimal digit, convert to nibble
  64.     CLC                ;Clear the carry, no error
  65.     RET
  66. TRY_HEX:
  67.     CMP    AL,'A'            ;Not sure yet
  68.     JB    BAD_DIGIT        ;Not hex
  69.     CMP    AL,'F'            ;Not sure yet
  70.     JA    BAD_DIGIT        ;Not hex
  71.     SUB    AL,'A'-10        ;Is hex, convert to nibble
  72.     CLC                ;Clear the carry, no error
  73.     RET
  74. BAD_DIGIT:
  75.     STC                ;Set the carry, error
  76.     RET
  77. CONVERT_HEX_DIGIT    ENDP
  78.  
  79.     PUBLIC    HEX_TO_BYTE
  80. ;-----------------------------------------------------------------------;
  81. ; This procedure converts the two characters at DS:DX from hex to one    ;
  82. ; byte.                                    ;
  83. ;                                    ;
  84. ;    DS:DX    Address of two characters for hex number        ;
  85. ; Returns:                                ;
  86. ;    AL    Byte                            ;
  87. ;    CF    Set for error, clear if no error            ;
  88. ;-----------------------------------------------------------------------;
  89. HEX_TO_BYTE    PROC
  90.     PUSH    BX
  91.     PUSH    CX
  92.     MOV    BX,DX            ;Put address in BX for indirect addr
  93.     MOV    AL,[BX]            ;Get first digit
  94.     CALL    CONVERT_HEX_DIGIT
  95.     JC    BAD_HEX            ;Bad hex digit if carry set
  96.     MOV    CX,4            ;Now multiply by 16
  97.     SHL    AL,CL
  98.     MOV    AH,AL            ;Retain a copy
  99.     INC    BX            ;Get second digit
  100.     MOV    AL,[BX]
  101.     CALL    CONVERT_HEX_DIGIT
  102.     JC    BAD_HEX            ;Bad hex digit if carry set
  103.     OR    AL,AH            ;Combine two nibbles
  104.     CLC                ;Clear carry for no error
  105. DONE_HEX:
  106.     POP    CX
  107.     POP    BX
  108.     RET
  109. BAD_HEX:
  110.     STC                ;Set carry for error
  111.     JMP    DONE_HEX
  112. HEX_TO_BYTE    ENDP
  113.  
  114.     PUBLIC    READ_STRING
  115.     EXTRN    WRITE_CHAR:PROC
  116. ;-----------------------------------------------------------------------;
  117. ; This procedure performs a function very similar to the DOS 0Ah    ;
  118. ; function.  But this function will return a special character if a    ;
  119. ; function or keyboard key is pressed--no return for these keys.  And    ;
  120. ; ESC will erase the input and start over again.            ;
  121. ;                                    ;
  122. ;    DS:DX    Address for keyboard buffer.  The first byte must    ;
  123. ;        contain the maximum number of characters to read (plus    ;
  124. ;        one for the return).  And the second byte will be used    ;
  125. ;        by this procedure to return the number of characters    ;
  126. ;        actually read.                        ;
  127. ;            0    No characters read            ;
  128. ;            -1    One special character read        ;
  129. ;            otherwise number actually read (not including    ;
  130. ;                Enter key)                ;
  131. ;                                    ;
  132. ; Uses:        BACK_SPACE, WRITE_CHAR, READ_KEY            ;
  133. ;-----------------------------------------------------------------------;
  134. READ_STRING    PROC
  135.     PUSH    AX
  136.     PUSH    BX
  137.     PUSH    SI
  138.     MOV    SI,DX            ;Use SI for index register and
  139. START_OVER:
  140.     MOV    BX,2            ;BX for offset to beginning of buffer
  141.     CALL    READ_KEY        ;Read one key from the keyboard
  142.     OR    AH,AH            ;Is character extended ASCII?
  143.     JNZ    EXTENDED        ;Yes, then process it.
  144. STRING_NOT_EXTENDED:            ;Extnd char is error unless buf empty
  145.     CMP    AL,CR            ;Is this a carriage return?
  146.     JE    END_INPUT        ;Yes, we are done with input
  147.     CMP    AL,BS            ;Is it a backspace character?
  148.     JNE    NOT_BS            ;Nope
  149.     CALL    BACK_SPACE        ;Yes, delete character
  150.     CMP    BL,2            ;Is buffer empty?
  151.     JE    START_OVER        ;Yes, can now read extended ASCII again
  152.     JMP    SHORT READ_NEXT_CHAR    ;No, continue reading normal characters
  153. NOT_BS:    CMP    AL,ESCAPE        ;Is it an ESC--purge buffer?
  154.     JE    PURGE_BUFFER        ;Yes, then purge the buffer
  155.     CMP    BL,[SI]            ;Check to see if buffer is full
  156.     JA    BUFFER_FULL        ;Buffer is full
  157.     MOV    [SI+BX],AL        ;Else save char in buffer
  158.     INC    BX            ;Point to next free character in buffer
  159.     PUSH    DX
  160.     MOV    DL,AL            ;Echo character to screen
  161.     CALL    WRITE_CHAR
  162.     POP    DX
  163. READ_NEXT_CHAR:
  164.     CALL    READ_KEY
  165.     OR    AH,AH            ;An extended ASCII char is not valid
  166.                     ; when the buffer is not empty
  167.     JZ    STRING_NOT_EXTENDED    ;Char is valid
  168.  
  169. ;-----------------------------------------------;
  170. ; Signal an error condition by sending a beep    ;
  171. ; character to the display: chr$(7).        ;
  172. ;-----------------------------------------------;
  173. SIGNAL_ERROR:
  174.     PUSH    DX
  175.     MOV    DL,7            ;Sound the bell by writing chr$(7)
  176.     MOV    AH,2
  177.     INT    21h
  178.     POP    DX
  179.     JMP    SHORT READ_NEXT_CHAR    ;Now read next character
  180.  
  181. ;-----------------------------------------------;
  182. ; Empty the string buffer and erase all the    ;
  183. ; characters displayed on the screen.        ;
  184. ;-----------------------------------------------;
  185. PURGE_BUFFER:
  186.     PUSH    CX
  187.     MOV    CL,[SI]            ;Backspace over maximum number of
  188.     XOR    CH,CH
  189. PURGE_LOOP:                ; characters in buffer.  BACK_SPACE
  190.     CALL    BACK_SPACE        ; will keep the cursor from moving too
  191.     LOOP    PURGE_LOOP        ; far back
  192.     POP    CX
  193.     JMP    START_OVER        ;Can now read extended ASCII characters
  194.                     ; since the buffer is empty
  195.  
  196. ;-----------------------------------------------;
  197. ; The buffer was full, so can't read another    ;
  198. ; character.  Send a beep to alert user of    ;
  199. ; buffer-full condition.            ;
  200. ;-----------------------------------------------;
  201. BUFFER_FULL:
  202.     JMP    SHORT SIGNAL_ERROR    ;If buffer full, just beep
  203.  
  204. ;-----------------------------------------------;
  205. ; Read the extended ASCII code and place this    ;
  206. ; in the buffer as the only character, then    ;
  207. ; return -1 as the number of characters read.    ;
  208. ;-----------------------------------------------;
  209. EXTENDED:                ;Read an extended ASCII code
  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:PROC
  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            ;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    0 if read ASCII char            ;
  265. ;                1 if read a special key            ;
  266. ;                -1 if no characters read        ;
  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
  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.     XOR    AH,AH            ;Signal read one byte
  287. DONE_READ:
  288.     POP    DX
  289.     RET
  290. NO_CHARACTERS:
  291.     XOR    AH,AH            ;Set to 'no characters read'
  292.     NOT    AH            ;Return -1 in AH
  293.     JMP    DONE_READ
  294. ASCII_INPUT:
  295.     MOV    AL,CHARS        ;Load character read
  296.     XOR    AH,AH            ;Signal read one byte
  297.     JMP    DONE_READ
  298. SPECIAL_KEY:
  299.     MOV    AL,CHARS[0]        ;Return the scan code
  300.     MOV    AH,1            ;Signal special key with 1
  301.     JMP    DONE_READ
  302. READ_BYTE    ENDP
  303.  
  304.  
  305.     PUBLIC    READ_KEY
  306. ;-----------------------------------------------------------------------;
  307. ; This procedure reads one key from the keyboard.            ;
  308. ;                                    ;
  309. ; Returns:    AL    Character code (unless AH = 1)            ;
  310. ;        AH    0 if read ASCII char                ;
  311. ;            1 if read a special key                ;
  312. ;-----------------------------------------------------------------------;
  313. READ_KEY    PROC
  314.     XOR    AH,AH            ;Ask for keyboard read function
  315.     INT    16h            ;Read character/scan code from keyboard
  316.     OR    AL,AL            ;Is it an extended code?
  317.     JZ    EXTENDED_CODE        ;Yes
  318. NOT_EXTENDED:
  319.     XOR    AH,AH            ;Return just the ASCII code
  320. DONE_READING:
  321.     RET
  322.  
  323. EXTENDED_CODE:
  324.     MOV    AL,AH            ;Put scan code into AL
  325.     MOV    AH,1            ;Signal extended code
  326.     JMP    DONE_READING
  327. READ_KEY    ENDP
  328.  
  329.  
  330.     PUBLIC    READ_DECIMAL
  331. ;-----------------------------------------------------------------------;
  332. ; This procedure takes the output buffer of READ_STRING and converts    ;
  333. ; the string of decimal digits to a word.                ;
  334. ;                                    ;
  335. ;    AX    Word converted from decimal                ;
  336. ;    CF    Set if error, clear if no error                ;
  337. ;                                    ;
  338. ; Uses:        READ_STRING                        ;
  339. ; Reads:    KEYBOARD_INPUT, etc.                    ;
  340. ; Writes:    KEYBOARD_INPUT, etc.                    ;
  341. ;-----------------------------------------------------------------------;
  342. READ_DECIMAL    PROC
  343.     PUSH    BX
  344.     PUSH    CX
  345.     PUSH    DX
  346.     MOV    CHAR_NUM_LIMIT,6    ;Max number is 5 digits (65535)
  347.     LEA    DX,KEYBOARD_INPUT
  348.     CALL    READ_STRING
  349.     MOV    CL,NUM_CHARS_READ    ;Get number of characters read
  350.     XOR    CH,CH            ;Set upper byte of count to 0
  351.     CMP    CL,0            ;Return error if no characters read
  352.     JLE    BAD_DECIMAL_DIGIT    ;No chars read, signal error
  353.     XOR    AX,AX            ;Start with number set to 0
  354.     XOR    BX,BX            ;Start at beginning of string
  355. CONVERT_DIGIT:
  356.     MOV    DX,10            ;Multiply number by 10
  357.     MUL    DX            ;Multiply AX by 10
  358.     JC    BAD_DECIMAL_DIGIT    ;CF set if MUL overflowed one word
  359.     MOV    DL,CHARS[BX]        ;Get the next digit
  360.     SUB    DL,'0'            ;And convert to a nibble (4 bits)
  361.     JS    BAD_DECIMAL_DIGIT    ;Bad digit if < 0
  362.     CMP    DL,9            ;Is this a bad digit?
  363.     JA    BAD_DECIMAL_DIGIT    ;Yes
  364.     ADD    AX,DX            ;No, so add it to number
  365.     INC    BX            ;Point to next character
  366.     LOOP    CONVERT_DIGIT        ;Get the next digit
  367. DONE_DECIMAL:
  368.     POP    DX
  369.     POP    CX
  370.     POP    BX
  371.     RET
  372. BAD_DECIMAL_DIGIT:
  373.     STC                ;Set carry to signal error
  374.     JMP    DONE_DECIMAL
  375. READ_DECIMAL    ENDP
  376.  
  377.  
  378.     END
  379.