home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD1.mdf / assemblr / library / nor_asm / kbd_io30.asm < prev    next >
Assembly Source File  |  1989-06-09  |  12KB  |  382 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.     EXTRN    UPDATE_REAL_CURSOR:PROC
  117. ;-----------------------------------------------------------------------;
  118. ; This procedure performs a function very similar to the DOS 0Ah    ;
  119. ; function.  But this function will return a special character if a    ;
  120. ; function or keyboard key is pressed--no return for these keys.  And    ;
  121. ; ESC will erase the input and start over again.            ;
  122. ;                                    ;
  123. ;    DS:DX    Address for keyboard buffer.  The first byte must    ;
  124. ;        contain the maximum number of characters to read (plus    ;
  125. ;        one for the return).  And the second byte will be used    ;
  126. ;        by this procedure to return the number of characters    ;
  127. ;        actually read.                        ;
  128. ;            0    No characters read            ;
  129. ;            -1    One special character read        ;
  130. ;            otherwise number actually read (not including    ;
  131. ;                Enter key)                ;
  132. ;                                    ;
  133. ; Uses:        BACK_SPACE, WRITE_CHAR, READ_KEY, UPDATE_REAL_CURSOR    ;
  134. ;-----------------------------------------------------------------------;
  135. READ_STRING    PROC
  136.     PUSH    AX
  137.     PUSH    BX
  138.     PUSH    SI
  139.     MOV    SI,DX            ;Use SI for index register and
  140. START_OVER:
  141.     CALL    UPDATE_REAL_CURSOR    ;Move to position of virtual cursor
  142.     MOV    BX,2            ;BX for offset to beginning of buffer
  143.     CALL    READ_KEY        ;Read one key from the keyboard
  144.     OR    AH,AH            ;Is character extended ASCII?
  145.     JNZ    EXTENDED        ;Yes, then process it.
  146. STRING_NOT_EXTENDED:            ;Extnd char is error unless buf empty
  147.     CMP    AL,CR            ;Is this a carriage return?
  148.     JE    END_INPUT        ;Yes, we are done with input
  149.     CMP    AL,BS            ;Is it a backspace character?
  150.     JNE    NOT_BS            ;Nope
  151.     CALL    BACK_SPACE        ;Yes, delete character
  152.     CMP    BL,2            ;Is buffer empty?
  153.     JE    START_OVER        ;Yes, can now read extended ASCII again
  154.     JMP    SHORT READ_NEXT_CHAR    ;No, continue reading normal characters
  155. NOT_BS:    CMP    AL,ESCAPE        ;Is it an ESC--purge buffer?
  156.     JE    PURGE_BUFFER        ;Yes, then purge the buffer
  157.     CMP    BL,[SI]            ;Check to see if buffer is full
  158.     JA    BUFFER_FULL        ;Buffer is full
  159.     MOV    [SI+BX],AL        ;Else save char in buffer
  160.     INC    BX            ;Point to next free character in buffer
  161.     PUSH    DX
  162.     MOV    DL,AL            ;Echo character to screen
  163.     CALL    WRITE_CHAR
  164.     POP    DX
  165. READ_NEXT_CHAR:
  166.     CALL    UPDATE_REAL_CURSOR    ;Move real cursor to virtual cursor
  167.     CALL    READ_KEY
  168.     OR    AH,AH            ;An extended ASCII char is not valid
  169.                     ; when the buffer is not empty
  170.     JZ    STRING_NOT_EXTENDED    ;Char is valid
  171.  
  172. ;-----------------------------------------------;
  173. ; Signal an error condition by sending a beep    ;
  174. ; character to the display: chr$(7).        ;
  175. ;-----------------------------------------------;
  176. SIGNAL_ERROR:
  177.     PUSH    DX
  178.     MOV    DL,7            ;Sound the bell by writing chr$(7)
  179.     MOV    AH,2
  180.     INT    21h
  181.     POP    DX
  182.     JMP    SHORT READ_NEXT_CHAR    ;Now read next character
  183.  
  184. ;-----------------------------------------------;
  185. ; Empty the string buffer and erase all the    ;
  186. ; characters displayed on the screen.        ;
  187. ;-----------------------------------------------;
  188. PURGE_BUFFER:
  189.     PUSH    CX
  190.     MOV    CL,[SI]            ;Backspace over maximum number of
  191.     XOR    CH,CH
  192. PURGE_LOOP:                ; characters in buffer.  BACK_SPACE
  193.     CALL    BACK_SPACE        ; will keep the cursor from moving too
  194.     LOOP    PURGE_LOOP        ; far back
  195.     POP    CX
  196.     JMP    START_OVER        ;Can now read extended ASCII characters
  197.                     ; since the buffer is empty
  198.  
  199. ;-----------------------------------------------;
  200. ; The buffer was full, so can't read another    ;
  201. ; character.  Send a beep to alert user of    ;
  202. ; buffer-full condition.            ;
  203. ;-----------------------------------------------;
  204. BUFFER_FULL:
  205.     JMP    SHORT SIGNAL_ERROR    ;If buffer full, just beep
  206.  
  207. ;-----------------------------------------------;
  208. ; Read the extended ASCII code and place this    ;
  209. ; in the buffer as the only character, then    ;
  210. ; return -1 as the number of characters read.    ;
  211. ;-----------------------------------------------;
  212. EXTENDED:                ;Read an extended ASCII code
  213.     MOV    [SI+2],AL        ;Place just this char in buffer
  214.     MOV    BL,0FFh            ;Num chars read = -1 for special
  215.     JMP    SHORT END_STRING
  216.  
  217. ;-----------------------------------------------;
  218. ; Save the count of the number of characters    ;
  219. ; read and return.                ;
  220. ;-----------------------------------------------;
  221. END_INPUT:                ;Done with input
  222.     SUB    BL,2            ;Count of characters read
  223. END_STRING:
  224.     MOV    [SI+1],BL        ;Return number of chars read
  225.     POP    SI
  226.     POP    BX
  227.     POP    AX
  228.     RET
  229. READ_STRING    ENDP
  230.  
  231.  
  232.     PUBLIC    BACK_SPACE
  233.     EXTRN    WRITE_CHAR:PROC
  234. ;-----------------------------------------------------------------------;
  235. ; This procedure deletes characters, one at a time, from the buffer and    ;
  236. ; the screen when the buffer is not empty.  BACK_SPACE simply returns    ;
  237. ; when the buffer is empty.                        ;
  238. ;                                    ;
  239. ;    DS:SI+BX    Most recent character still in buffer        ;
  240. ;                                    ;
  241. ; Uses:        WRITE_CHAR                        ;
  242. ;-----------------------------------------------------------------------;
  243. BACK_SPACE    PROC            ;Delete one character
  244.     PUSH    AX
  245.     PUSH    DX
  246.     CMP    BX,2            ;Is buffer empty?
  247.     JE    END_BS            ;Yes, read the next character
  248.     DEC    BX            ;Remove one character from buffer
  249.     MOV    AH,2            ;Remove character from screen
  250.     MOV    DL,BS
  251.     INT    21h
  252.     MOV    DL,20h            ;Write space there
  253.     CALL    WRITE_CHAR
  254.     MOV    DL,BS            ;Back up again
  255.     INT    21h
  256. END_BS:    POP    DX
  257.     POP    AX
  258.     RET
  259. BACK_SPACE    ENDP
  260.  
  261.     PUBLIC    READ_BYTE
  262. ;-----------------------------------------------------------------------;
  263. ; This procedure reads either a single ASCII character or a two-digit    ;
  264. ; hex number.  This is just a test version of READ_BYTE.        ;
  265. ;                                    ;
  266. ; Returns byte in    AL    Character code (unless AH = 0)        ;
  267. ;            AH    0 if read ASCII char            ;
  268. ;                1 if read a special key            ;
  269. ;                -1 if no characters read        ;
  270. ;                                    ;
  271. ; Uses:        HEX_TO_BYTE, STRING_TO_UPPER, READ_STRING        ;
  272. ; Reads:    KEYBOARD_INPUT, etc.                    ;
  273. ; Writes:    KEYBOARD_INPUT, etc.                    ;
  274. ;-----------------------------------------------------------------------;
  275. READ_BYTE    PROC
  276.     PUSH    DX
  277.     MOV    CHAR_NUM_LIMIT,3    ;Allow only two characters (plus Enter)
  278.     LEA    DX,KEYBOARD_INPUT
  279.     CALL    READ_STRING
  280.     CMP    NUM_CHARS_READ,1    ;See how many characters
  281.     JE    ASCII_INPUT        ;Just one, treat as ASCII character
  282.     JB    NO_CHARACTERS        ;Only Enter key hit
  283.     CMP    BYTE PTR NUM_CHARS_READ,0FFh    ;Special function key?
  284.     JE    SPECIAL_KEY        ;Yes
  285.     CALL    STRING_TO_UPPER        ;No, convert string to uppercase
  286.     LEA    DX,CHARS        ;Address of string to convert
  287.     CALL    HEX_TO_BYTE        ;Convert string from hex to byte
  288.     JC    NO_CHARACTERS        ;Error, so return 'no characters read'
  289.     XOR    AH,AH            ;Signal read one byte
  290. DONE_READ:
  291.     POP    DX
  292.     RET
  293. NO_CHARACTERS:
  294.     XOR    AH,AH            ;Set to 'no characters read'
  295.     NOT    AH            ;Return -1 in AH
  296.     JMP    DONE_READ
  297. ASCII_INPUT:
  298.     MOV    AL,CHARS        ;Load character read
  299.     XOR    AH,AH            ;Signal read one byte
  300.     JMP    DONE_READ
  301. SPECIAL_KEY:
  302.     MOV    AL,CHARS[0]        ;Return the scan code
  303.     MOV    AH,1            ;Signal special key with 1
  304.     JMP    DONE_READ
  305. READ_BYTE    ENDP
  306.  
  307.  
  308.     PUBLIC    READ_KEY
  309. ;-----------------------------------------------------------------------;
  310. ; This procedure reads one key from the keyboard.            ;
  311. ;                                    ;
  312. ; Returns:    AL    Character code (unless AH = 1)            ;
  313. ;        AH    0 if read ASCII char                ;
  314. ;            1 if read a special key                ;
  315. ;-----------------------------------------------------------------------;
  316. READ_KEY    PROC
  317.     XOR    AH,AH            ;Ask for keyboard read function
  318.     INT    16h            ;Read character/scan code from keyboard
  319.     OR    AL,AL            ;Is it an extended code?
  320.     JZ    EXTENDED_CODE        ;Yes
  321. NOT_EXTENDED:
  322.     XOR    AH,AH            ;Return just the ASCII code
  323. DONE_READING:
  324.     RET
  325.  
  326. EXTENDED_CODE:
  327.     MOV    AL,AH            ;Put scan code into AL
  328.     MOV    AH,1            ;Signal extended code
  329.     JMP    DONE_READING
  330. READ_KEY    ENDP
  331.  
  332.  
  333.     PUBLIC    READ_DECIMAL
  334. ;-----------------------------------------------------------------------;
  335. ; This procedure takes the output buffer of READ_STRING and converts    ;
  336. ; the string of decimal digits to a word.                ;
  337. ;                                    ;
  338. ;    AX    Word converted from decimal                ;
  339. ;    CF    Set if error, clear if no error                ;
  340. ;                                    ;
  341. ; Uses:        READ_STRING                        ;
  342. ; Reads:    KEYBOARD_INPUT, etc.                    ;
  343. ; Writes:    KEYBOARD_INPUT, etc.                    ;
  344. ;-----------------------------------------------------------------------;
  345. READ_DECIMAL    PROC
  346.     PUSH    BX
  347.     PUSH    CX
  348.     PUSH    DX
  349.     MOV    CHAR_NUM_LIMIT,6    ;Max number is 5 digits (65535)
  350.     LEA    DX,KEYBOARD_INPUT
  351.     CALL    READ_STRING
  352.     MOV    CL,NUM_CHARS_READ    ;Get number of characters read
  353.     XOR    CH,CH            ;Set upper byte of count to 0
  354.     CMP    CL,0            ;Return error if no characters read
  355.     JLE    BAD_DECIMAL_DIGIT    ;No chars read, signal error
  356.     XOR    AX,AX            ;Start with number set to 0
  357.     XOR    BX,BX            ;Start at beginning of string
  358. CONVERT_DIGIT:
  359.     MOV    DX,10            ;Multiply number by 10
  360.     MUL    DX            ;Multiply AX by 10
  361.     JC    BAD_DECIMAL_DIGIT    ;CF set if MUL overflowed one word
  362.     MOV    DL,CHARS[BX]        ;Get the next digit
  363.     SUB    DL,'0'            ;And convert to a nibble (4 bits)
  364.     JS    BAD_DECIMAL_DIGIT    ;Bad digit if < 0
  365.     CMP    DL,9            ;Is this a bad digit?
  366.     JA    BAD_DECIMAL_DIGIT    ;Yes
  367.     ADD    AX,DX            ;No, so add it to number
  368.     INC    BX            ;Point to next character
  369.     LOOP    CONVERT_DIGIT        ;Get the next digit
  370. DONE_DECIMAL:
  371.     POP    DX
  372.     POP    CX
  373.     POP    BX
  374.     RET
  375. BAD_DECIMAL_DIGIT:
  376.     STC                ;Set carry to signal error
  377.     JMP    DONE_DECIMAL
  378. READ_DECIMAL    ENDP
  379.  
  380.  
  381.     END
  382.