home *** CD-ROM | disk | FTP | other *** search
/ Programmer 7500 / MAX_PROGRAMMERS.iso / PROGRAMS / UTILS / DOS_HELP / ADVMSDOS.ZIP / TALK.ASM < prev    next >
Encoding:
Assembly Source File  |  1986-06-19  |  11.9 KB  |  446 lines

  1.     name      talk
  2.         page      55,132
  3.         .lfcond             ;list false conditionals too
  4.         title     'TALK --- IBM PC terminal emulator'
  5. ;
  6. ; TALK.ASM  --- a simple terminal emulator for the IBM PC
  7. ; Copyright (c) 1983, 1984, 1985 Ray Duncan
  8. ;
  9. ; To assemble, link, and convert this program into 
  10. ; a COM file, follow these steps:
  11. ;
  12. ;    C>MASM TALK;
  13. ;     C>LINK TALK;
  14. ;    C>EXE2BIN TALK.EXE TALK.COM
  15. ;    C>DEL TALK.EXE
  16. ;
  17. ; Ignore the message "Warning: no stack segment" from the Linker.
  18.  
  19. cr     equ     0dh           ;ASCII carriage return
  20. lf      equ     0ah           ;ASCII line feed
  21. bsp    equ    08h        ;ASCII backspace
  22. esc     equ     1bh           ;ASCII escape code
  23.  
  24. dattr    equ    07h        ;display attribute to use
  25.                 ;while in emulation mode
  26.  
  27. echo    equ      0             ;0=full-duplex, -1=half-duplex
  28.  
  29. comm_port equ    0             ;set =0 for COM1, <>0 for COM2
  30.  
  31. pic_mask  equ    21h        ;port address, 8259 mask register
  32. pic_eoi   equ   20h        ;port address, 8259 EOI instr.
  33.     
  34.     if     comm_port    ;define physical port assignments
  35. comm_data equ    02f8h        ;for COM2
  36. comm_ier  equ    02f9h
  37. comm_mcr  equ   02fch
  38. comm_stat equ   02fdh
  39. com_int      equ    0bh
  40. int_mask  equ   08h        ;Mask for 8529, COM2 is IRQ3
  41.     else
  42. comm_data equ    03f8h        ;port assignments for COM1 
  43. comm_ier  equ    03f9h
  44. comm_mcr  equ   03fch
  45. comm_stat equ   03fdh
  46. com_int      equ    0ch
  47. int_mask  equ   10h        ;Mask for 8259, COM1 is IRQ4    
  48.     endif
  49.     page
  50.  
  51. cseg    segment    para public 'CODE'
  52.  
  53.     org    100h
  54.  
  55.     assume    cs:cseg,ds:cseg,es:cseg,ss:cseg  ;COM file...
  56.  
  57. talk    proc     far          ;entry point from PC-DOS
  58.  
  59.                                  ;initialize display for 
  60.                 ;terminal emulator mode
  61.  
  62.            mov      ah,15         ;determine display width
  63.     int     10h           ;using get mode function of ROM
  64.         dec     ah            ;BIOS video driver, save it for use
  65.          mov      columns,ah    ;by the screen clear routine.
  66.          cmp      al,7          ;make sure display is text mode.
  67.          je       talk2         ;mode 7 ok, proceed
  68.          cmp      al,3
  69.          jbe      talk2         ;modes 0-3 ok,proceed
  70.          mov      dx,offset msg1
  71.         jmp     talk6         ;print error message and exit
  72.  
  73. talk2:
  74.         mov      bh,dattr        ;now clear screen with special
  75.     call    cls        ;attribute if needed, home cursor
  76.  
  77.     call    asc_enb        ;set up communications interrupt
  78.                 ;service routine and enable int.
  79.  
  80. talk3:    call     pc_stat       ;check character waiting
  81.                                  ;from the IBM PC keyboard
  82.         jz      talk4         ;nothing waiting, jump
  83.         call    pc_in         ;read char. from PC keyboard
  84.         cmp     al,0        ;is it a function key?
  85.     jne    talk32        ;not function key, jump
  86.     call    pc_in        ;read and discard the 2nd char
  87.                 ;of function key sequence
  88.         jmp    talk5         ;then exit the terminal emulator
  89.  
  90. talk32:                ;character received from PC keyboard
  91.     if    echo
  92.         push    ax            ;if running half-duplex, echo
  93.         call    pc_out        ;the character to the PC display
  94.         pop     ax            
  95.         endif
  96.           call      com_out       ;write char. to the comm port
  97.  
  98. talk4:  call       com_stat      ;check if character waiting
  99.                                  ;from the comm port
  100.         jz      talk3         ;no, loop
  101.           call    com_in        ;read char. from comm port
  102.  
  103.     cmp    al,20h        ;is it control code?
  104.     jae    talk45        ;no
  105.     call    ctrl_code    ;yes,process it
  106.     jmp    talk3        ;check local keyboard
  107.  
  108. talk45:
  109.     call     pc_out        ;write it to the PC display
  110.     jmp    talk4        ;see if any more waiting
  111.  
  112. talk5:                           ;ESC key detected, prepare
  113.                                  ;to exit the terminal emulator.
  114.     mov     bh,07h        ;clear screen & home cursor
  115.         call    cls        ;with "normal" video attribute 
  116.     mov       dx,offset msg2  ;print farewell message
  117.  
  118. talk6:  push    dx        ;save message addr
  119.     call    asc_dsb        ;disable controller and
  120.     pop    dx        ;release interrupt vector
  121.     mov    ah,9        ;print message
  122.     int    21h
  123.     mov    ax,4c00h    ;exit with ret code=0
  124.     int    21h
  125.  
  126. talk     endp
  127.  
  128.  
  129. com_stat proc    near        ;Check asynch status, returns     
  130.                                  ;Z=false if character ready
  131.                                  ;Z=true if nothing waiting
  132.     push    dx
  133.     mov    dx,asc_in    ;compare ring buffer pointers
  134.     cmp    dx,asc_out
  135.     pop    dx
  136.     ret
  137. com_stat endp
  138.  
  139.  
  140. com_in     proc     near        ;get a char from asynch line    
  141.     push    bx              ;returns char in AL            
  142. com_in1:            ;if no char waiting, loop
  143.     mov    bx,asc_out    ;until one is received.
  144.     cmp    bx,asc_in
  145.     je    com_in1
  146.     mov    al,[bx+asc_buf]
  147.     inc    bx
  148.     cmp    bx,asc_buf_len
  149.     jne    com_in2
  150.     xor    bx,bx        ;reset ring pointer
  151. com_in2:
  152.     mov    asc_out,bx    ;store updated pointer
  153.     pop    bx
  154.     ret
  155. com_in  endp
  156.  
  157.  
  158. com_out    proc      near        ;write character in AL to COM port   
  159.     push    dx
  160.     push    ax        ;save char
  161.      mov    dx,comm_stat    ;check TBE status
  162. com_out1:
  163.     in    al,dx
  164.     and    al,20h
  165.     jz    com_out1
  166.     pop    ax        ;write char    
  167.     mov    dx,comm_data
  168.     out    dx,al
  169.     pop    dx
  170.     ret
  171. com_out endp
  172.  
  173.  
  174. pc_stat proc     near         ;read status for the IBM
  175.                                  ;PC's keyboard, returns
  176.                                  ;Z=false if character ready
  177.                                  ;Z=true if nothing waiting.
  178.                                  ;register DX destroyed.
  179.         mov     al,in_flag    ;if a character is already    
  180.         or      al,al           ;waiting,just return status   
  181.         jnz     pc_stat1
  182.         mov     ah,6          ;otherwise call PC-DOS to
  183.         mov     dl,0ffh       ;determine status
  184.         int     21h
  185.         jz      pc_stat1      ;jump,nothing ready
  186.                                  ;got a char, save it for
  187.                                  ;"pc_in" routine.
  188.     mov     in_char,al
  189.     mov    in_flag,0ffh
  190. pc_stat1:                        ;return to caller with
  191.     ret                     ;Z flag set appropriately
  192. pc_stat endp
  193.  
  194.  
  195. pc_in    proc    near        ;read a character from the
  196.                                  ;IBM PC's keyboard, return
  197.                                  ;it in AL.  DX may be destroyed.
  198.         mov        al,in_flag
  199.         or         al,al         ;any character waiting?
  200.         jnz        pc_in1        ;yes,return it to caller
  201.         call       pc_stat       ;try and read a character
  202.         jmp        pc_in
  203. pc_in1:    mov        in_flag,0    ;clear char waiting flag
  204.     mov    al,in_char    ;exit with AL=char 
  205.         ret 
  206. pc_in   endp
  207.  
  208.  
  209. pc_out    proc    near        ;write the character in AL
  210.                                  ;to the PC's display.
  211.     mov    ah,0eh        ;use ROM BIOS TTY output fxn
  212.     push    bx        ;save register
  213.     xor    bx,bx        ;assume page 0
  214.     int    10h        ;call ROM BIOS video driver
  215.     pop    bx        ;restore register
  216.     ret
  217. pc_out    endp
  218.  
  219.  
  220. cls    proc    near          ;clear the display and set
  221.                                  ;it to the attribute in BH.
  222.                                  ;registers AX, CX, DX destroyed.
  223.         mov     dl,columns
  224.         mov     dh,24         ;DL,DH=X,Y of lower right
  225.                                  ;corner of "window".
  226.         mov     cx,0          ;CL,CH=X,Y of upper left
  227.                                  ;corner of "window".
  228.         mov     ax,600h       ;AH=6 for "scroll or initialize
  229.                                  ;window" function, AL=0 for
  230.                                  ;number of lines to scroll.
  231.         int     10h           ;call ROM BIOS video driver.
  232.     call    home        ;set cursor at (0,0)
  233.         ret
  234. cls    endp
  235.  
  236.  
  237. clreol    proc    near          ;clear from cursor to end of line
  238.                                  ;using the attribute in BH.
  239.                                  ;registers AX, CX, DX destroyed.
  240.     call    getxy
  241.     mov    cx,dx        ;current position = "upper left"
  242.                 ;corner of window
  243.         mov     dl,columns    ;for "lower right", X is max columns,
  244.                 ; Y is the same
  245.         mov     ax,600h       ;AH=6 for "scroll or initialize
  246.                                  ;window" function, AL=0 for
  247.                                  ;number of lines to scroll.
  248.         int     10h           ;call ROM BIOS video driver.
  249.         ret
  250. clreol    endp
  251.  
  252.  
  253. home    proc     near        ;home cursor (set X,Y=0,0)
  254.         mov      dx,0        
  255.     call    gotoxy
  256.         ret
  257. home    endp
  258.  
  259.  
  260. gotoxy    proc    near        ;position the cursor, call
  261.                 ;with (DL,DH)=(X,Y)
  262.     push    bx        ;save registers
  263.     push    ax
  264.     mov    bh,0        ;assume page 0
  265.     mov    ah,2
  266.     int    10h        ;call ROM BIOS video driver
  267.     pop    ax        ;restore registers
  268.     pop    bx
  269.     ret
  270. gotoxy    endp
  271.  
  272.  
  273. getxy    proc    near        ;get the current cursor position,
  274.                 ;returns (DL,DH)=(X,Y)
  275.     push    ax        ;save registers
  276.     push    bx
  277.     push    cx
  278.     mov    ah,3
  279.     mov    bh,0        ;assume page 0
  280.     int    10h        ;call ROM BIOS video driver
  281.     pop    cx        ;restore registers
  282.     pop    bx
  283.     pop    ax
  284.     ret
  285. getxy    endp
  286.  
  287.  
  288. ctrl_code proc    near        ;process a control code character
  289.                 ;call with AL=char
  290.     cmp    al,cr        ;if line feed or carriage
  291.     je    ctrl8        ;return, just send it    
  292.     cmp    al,lf
  293.     je    ctrl8
  294.     cmp    al,bsp        ;or if backspace, just send it
  295.     je    ctrl8
  296.  
  297.     cmp    al,26        ;is it clearscreen
  298.     jne    ctrl7        ;no,jump
  299.     mov    bh,dattr
  300.     call    cls        ;clear screen and home cursor
  301.     ret
  302.  
  303. ctrl7:
  304.     cmp    al,esc        ;is it escape char?
  305.     jne    ctrl9        ;no,throw it away
  306.     call    esc_seq        ;yes,emulate CRT terminal
  307.     ret
  308.  
  309. ctrl8:    call    pc_out        ;send CR or LF to display
  310.  
  311. ctrl9:    ret            ;and exit
  312.  
  313. ctrl_code endp
  314.  
  315.  
  316. esc_seq    proc    near        ;decode Televideo 950 escape
  317.                 ;sequence to control the screen
  318.     call    com_in
  319.     cmp    al,84        ;clear to end of line
  320.     jne    esc_seq1
  321.     mov    bh,dattr
  322.     call    clreol
  323.     ret
  324. esc_seq1:
  325.     cmp    al,61        ;cursor positioning
  326.     jne    esc_seq2
  327.     call    com_in        ;get Y
  328.     sub    al,33        ;remove offset
  329.     mov    dh,al
  330.     call    com_in        ;get X
  331.     sub    al,33        ;remove offset
  332.     mov    dl,al
  333.     call    gotoxy        ;set cursor
  334. esc_seq2:
  335.     ret
  336. esc_seq    endp
  337.  
  338.  
  339. asc_enb    proc    near        ;set up communications interrupt
  340.                 ;vector, and enable interrupt
  341.     mov    ah,35h        ;get current address of asynch
  342.     mov    al,com_int    ;port's interrupt handler
  343.     int    21h        ;ES:BX = addr
  344.     mov    intc_seg,es    ;save segment
  345.     mov    intc_offs,bx    ;save offset
  346.  
  347.     mov    dx,offset asc_int
  348.     mov    ah,25h        ;set address of new handler
  349.     mov    al,com_int
  350.     int    21h
  351.     
  352.     mov    dx,comm_mcr    ;modem controller DTR & OUT2
  353.     mov    al,0bh
  354.     out    dx,al
  355.  
  356.     mov    dx,comm_ier    ;interrupt enable register
  357.     mov    al,1        ;on asynch controller
  358.     out    dx,al
  359.  
  360.     in    al,pic_mask    ;read current 8259 int. mask
  361.     and    al,not int_mask    ;reset mask for this COM port
  362.     out    pic_mask,al    ;write back 8259 int. mask
  363.  
  364.     ret
  365.  
  366. asc_enb    endp
  367.      
  368. asc_dsb proc    near        ;disable interrupt and release
  369.                 ;service vector
  370.                 ;vector, and enable interrupt
  371.     
  372.     in    al,pic_mask    ;read current 8259 int. mask
  373.     or    al,int_mask    ;set mask for this COM port
  374.     out    pic_mask,al    ;write int. mask back to 8259
  375.  
  376.     push    ds
  377.     mov    dx,intc_offs      ;saved offset
  378.     mov    ds,intc_seg    ;saved segment
  379.     mov    ah,25h        ;restore address of original
  380.     mov    al,com_int    ;com port interrupt handler
  381.     int    21h        
  382.     pop    ds
  383.     ret
  384. asc_dsb    endp
  385.  
  386.  
  387. asc_int    proc    far        ;interrupt service routine
  388.                 ;for asynch controller
  389.  
  390.     sti            ;turn interrupts back on
  391.     push    ax        ;save all necessary registers
  392.     push    bx
  393.     push    dx
  394.     push    ds
  395.     mov    ax,cs
  396.     mov    ds,ax
  397.     mov    dx,comm_data
  398.     in    al,dx        ;read this character
  399.     cli            ;clear interrupts for
  400.                 ;pointer manipulation
  401.     mov    bx,asc_in    ;get buffer pointer
  402.     mov    [asc_buf+bx],al ;store this character
  403.     inc    bx        ;bump pointer
  404.     cmp    bx,asc_buf_len    ;time for wrap?
  405.     jne    asc_int1    ;no,jump
  406.     xor    bx,bx        ;yes,reset pointer
  407. asc_int1:
  408.     mov    asc_in,bx    ;store back updated pointer
  409.     sti            ;turn interrupts back on
  410.     mov    al,20h        ;send EOI to 8259
  411.     out    pic_eoi,al
  412.     pop    ds        ;restore all registers
  413.     pop    dx
  414.     pop    bx
  415.     pop    ax
  416.     iret            ;and exit handler
  417. asc_int    endp
  418.  
  419.  
  420. in_char    db     0             ;PC keyboard input char.
  421. in_flag    db    0        ;<>0 if char waiting
  422.  
  423. columns    db      0             ;highest numbered column in
  424.                     ;current display mode (39 or 79)
  425.  
  426. msg1         db        cr,lf,'Display must be text mode.'
  427.              db        cr,lf,'$'
  428.  
  429. msg2         db        cr,lf,lf,'Exit from terminal emulator.'
  430.              db        cr,lf,'$'
  431.  
  432. intc_offs    dw    0    ;original contents of Int 0CH
  433. intc_seg    dw    0    ;service vector
  434.  
  435. asc_in        dw    0    ;input pointer to ring buffer
  436. asc_out        dw    0    ;output pointer to ring buffer
  437.  
  438. asc_buf_len    equ    16384
  439.  
  440. asc_buf        equ    this byte
  441.  
  442. cseg     ends
  443.  
  444.          end       talk
  445.