/* NOTE: this code is indented using tabs set every 4 columns, not 8. */ /* * Rudimentary communication program; written in C with I/O * routines in assembler, using "#asm" construct in DeSmet C. */ #define TRUE 1 #define FALSE 0 #define NULL 0 #define comm_stat head!=tail int head=0, tail=0; char comm_buffer[8192]; main() { char commget(); int c, echo=FALSE, verbose=FALSE; initcomm(); goto inside; while((c=my_ci())<256) /* alt's and function keys are >=256 */ { commput(c); if(echo) my_co(c); inside: while(my_stat()==0) if(comm_stat) if(is_nice(c=commget())) my_co(c); else if(verbose) { my_co('^'); my_co(127&(c+'@')); } } switch(c>>8) /* process function key */ { case '\060': /* b send break */ make_break(); my_puts("** break **\n"); break; case '\022': /* e echo toggle */ echo = !echo; if(echo) my_puts("** echo on **\n"); else my_puts("** echo off **\n"); break; case '\020': /* q quit */ my_puts("** returning to DOS **\n"); goto byebye; case '\057': /* v verbose */ verbose = !verbose; if(verbose) my_puts("** verbose on **\n"); else my_puts("** verbose off **\n"); break; } goto inside; byebye: killcomm(); } initcomm() { #asm ; initialize communication port, ; and install interrupt handler ; save dseg for interrupt handler mov ax,ds mov cs:dssave,ax ; set int vector to my handler push ds xor ax,ax mov ds,ax mov [30h],offset handler mov ax,cs mov [32h],ax pop ds ; assert DTR, RTS, and OUT2 mov dx,3fch mov al,11 out dx,al ; enable interrupts for data ready mov dx,3f9h mov al,1 out dx,al ; clear any outstanding int mov dx,3f8h in al,dx ; enable interrupts sti ; enable IRQ4 on 8259A in al,21h and al,0efh out 21h,al ; and return jmp init_finis dssave: dw 0 handler: push ds push ax push dx push bx ; restore appropriate dseg mov ax,cs:dssave mov ds,ax ; grab the byte from comm port mov dx,3f8h in al,dx ; put it in the buffer mov bx,tail_ mov comm_buffer_[bx],al ; tail=tail+1 (mod 8192) inc bx cmp bx,8192 jl handler_around xor bx,bx handler_around: mov tail_,bx ; tell the 8259A EOI mov dx,20h mov al,32 out dx,al pop bx pop dx pop ax pop ds ; reenable interrupts sti iret init_finis: # } commput(c) int c; { #asm ; put the character out the port mov dx,3f8h mov ax,[bp+4] out dx,al # } char commget() { char temp; temp=comm_buffer[head++]; head%=8192; return(temp); } killcomm() { #asm ; disconnect the interrupt handler in al,21h or al,10h out 21h,al # } make_break() { #asm ; set bit on LCR mov dx,3fbh in al,dx push ax or al,40h out dx,al ; wait a wee bit (~200 ms) mov bx,8 outer: mov cx,7000 tight: loop tight dec bx jnz outer ; and turn break back off pop ax out dx,al # } is_nice(c) /* true for those characters that "should" be received */ char c; { c&=127; if(c>=' ' && c<='~') /* printable */ return(TRUE); if(c>6 && c<11) /* BEL, BS, HT, LF */ return(TRUE); if(c==13 || c==27) /* CR, ESC */ return(TRUE); return(FALSE); } my_puts(s) /* puts, using my_co() */ char *s; { while(*s) { if(*s=='\n') my_co('\r'); my_co(*(s++)); } } my_co(c) /* character output, smaller and faster than DeSmet's, using DOS function call 2.00 */ char c; { #asm mov ah,2 mov dx,[bp+4] int 21h # } my_stat() /* true if character is ready from keyboard */ { #asm mov ah,1 int 16h jz stat_no_char mov ax,1 jmp stat_finis stat_no_char: xor ax,ax stat_finis: # } my_ci() /* get character from keyboard, using BIOS function call */ { #asm xor ah,ah int 16h or al,al jz my_ci_finis xor ah,ah my_ci_finis: # } ------------------------------------------------------------------------------ The termcap for DOS 2.00 with ansi device driver follows: ------------------------------------------------------------------------------ pm|pcmon|IBM-PC using DOS 2.00 ansi device driver (monochrome)|\ :am:bc=^H:bw:ce=\E[K:cl=\E[2J:cm=\E[%i%d;%dH:co#80:cr=^M:\ :do=^J:ho=\E[H:kb=^H:li#25:ll=\E[25H:nd=\E[C:\ :pt:se=\E[0m:so=\E[1m:ta=^I:up=\E[A:xt: pc|pccol|IBM-PC using DOS 2.00 ansi device driver (color)|\ :am:bc=^H:bw:ce=\E[K:cl=\E[2J:cm=\E[%i%d;%dH:co#80:cr=^M:\ :do=^J:ho=\E[H:kb=^H:li#25:ll=\E[25H:nd=\E[C:\ :pt:se=\E[0;32m:so=\E[1m:ta=^I:up=\E[A:xt: ------------------------------------------------------------------------------ and that's it! Enjoy. I place this in the public domain, and would appreciate feedback. Improvements and bug reports especially desired. If the code is too cryptic or uncommented, feel free to send questions to: Bennett Todd ...{decvax,ihnp4,akgua}!mcnc!ecsvax!bet