操作系统  办公  实用知识  设计  开发  WEB开发  移动开发  数据库  软件工程  网管  安全  管理  信息化  答疑  渠道 

5个DOS专用文件的6种io重定向,more实现管道原理

2006-9-29 网友评论 0 条 点击进入论坛
 1. 重定向
 
  以下a.asm,用含''t''及回车13的txt,仿command.com,依masm命令行的arg符号值N,(如masm /Darg=0 a;),实现5个DOS打开专用文件(STD_)的6种io重定向:
 
  N=0:是STDIN句柄,先bin方式读1符,再从txt输''t''到char
  N=1:是STDOUT句柄,输出char的''1''到txt
  N=2:是STDERR句柄,输出char的''2''到txt
 
  N=30,31:
  3是STDAUX句柄,N=30,从txt输''t''到char;N=31,输出char的''3''到txt
 
  N=41:
  4是STDPRN句柄,输出char的''4''到txt
 
  asm调用如下功能:
 
  N=0时,44,读/写设备info,敲键符值入100h,其ascii/scan对,入106h,扩展键时,首对,入104h,次值,入101h.
  如1,得(31,31,2),ctl_c,得(3,3,2e),F1,得(0,0,3bh),(3bh,0,3bh)
 
  3d,依读写方式,打开txt,保存句柄到si
  45,保存STD_句柄的复制值到di
  46,将来访问(cx)句柄,变为访问(bx)=(si)句柄,开始重定向
  3f/40,用STD_输入/出,字符数1,偏置char
  46,将来访问(cx)句柄,变为访问(bx)=(di)句柄,结束重定向
  3e,关闭txt
 
  DEBUG行完a.com,对输入,见103h的char,变''t'',对输出,type txt,见1~4.
 
  ACT=2
  IFDEF arg
      IF arg GT 2
          IF arg EQ 30
              ACT=30
          ENDIF
 
          IF arg EQ 31
              ACT=31
          ENDIF
 
          IF arg EQ 41
              ACT=41
          ENDIF
 
          STD_=arg/10
      ELSE
          IF arg GE 0
              ACT=1
              STD_=arg
 
              IF arg EQ 0
                  ACT=0
              ENDIF
          ENDIF
      ENDIF
  ENDIF
 
  IF ACT EQ 2    无效
      %OUT /Darg=0|1|2|30|31|41
      .ERR
  ENDIF
 
  just    macro
          local    j
 
          mov    di,es:[26]    敲键,i9写低asc,高scan到[1Ch尾引字++],i16读[1Ah首引字++]到3f功能的ax
          sub    di,2
 
          cmp di,1ch    未重划键区,现在回头
          ja j
 
          mov di,3ch    刚才入尾
 
  j:        mov ax,es:[di]
          endm
 
  c    segment
      assume    cs:c,ds:c
 
      org    100h
 
  @:    jmp    @1
 
  char    db    ''0''+STD_
  txt    db      ''txt'',0
 
  @1:    mov     ah,3dh        open
      mov    al,ACT and 1
            lea     dx,txt
          int     21h
 
      mov    si,ax        han
 
      mov    bx,ACT        stdin
      test    bx,63    >41   
      jnz    @3
 
      mov    ax,4400h    I/O,从/到fil\nul定向,dx=42h\80c4,否则80d3
      int    21h
 
      mov    ax,4401h
      or    dl,32        bin
      xor    dh,dh
      push    dx
      int    21h
 
      mov    ax,64        bios数据区seg,1E~3D是键区
      mov    es,ax
 
      mov    ah,3fh        不等回车读
      mov    cx,1        1符
      lea    dx,@        入256
      int    21h
 
      test    byte ptr cs:[256],255    测扩展
      jnz    @2
 
      just
      mov    word ptr txt,ax
 
      mov    ah,3fh        取真
      inc    dx
      int    21h
 
  @2:    just
      mov word ptr txt[2],ax
 
      mov    ax,4401h    复原
      pop    dx
      and    dx,not 32
      int    21h
 
  @3:    mov     ah,45h    duplica
      mov    bx,STD_
      int     21h
 
      mov    di,ax        han
 
      mov    ah,46h        force han
      mov    bx,si
      mov    cx,STD_
      int    21h
 
      mov    ah,3fh+ACT    r/w=3f/40
      mov    bx,STD_
      mov    cx,1
      lea    dx,char
      int    21h
 
      mov    ah,46h
      mov    bx,di
      mov    cx,STD_
      int    21h
 
      mov    ah,3eh        close
      mov    bx,si
      int    21h
 
      ret
 
  c    ends
      end    @
 
  2. 管道
 
  反汇编DOS_3.31_more,得[100,1e9]是代码区,[1ea,219]是数据区,初值为18/50的1ea/leb,记录屏幕配置行/列数,初值1/1的1ec/1ed,记录已处理行/列数.
 
  流程:
 
  (2.1) 100处,用功能30,取DOS主/次版本号al/ah,若非3/1f,就显1fc处的"MORE: Incorrect DOS version",用110处的int 20,退
  (2.2) 置1ea=19,用int 10,ah=0f,得屏幕列数到1eb,如50
 
  (2.3) 用功能45,复制stdin(bx=0)句柄到bp,如5,用功能3e,关闭stdin句柄
 
  (2.4) 用功能45,复制stderr(bx=2)句柄(也可复制被@1的si句柄),必得刚关闭的句柄0,
  为看完满屏而读键盘一符时,从stderr或si读,而不移管道stdin指针.
 
  (2.5) 139处,用功能3f,打开bp句柄,字节数cx=1000,目的地21a,读stdin
 
  用|接入管道时,more不创建新进程.
 
  未接入时,将读键盘行,如读"135",此串及回车0d,换行0a,被存目的地,被存长度5返到ax,键入符数多于cx时,前面cx个字符被存目的地.对^Z单行,ax返回0.
 
  若ax=0,就用14a处的int 20退出,否则
 
  (2.6) 150处,读目的地每个字符到al
 
  读到^Z,则转14a退出
 
  读到0d,置列数1ed=1,转1ac
 
  读到0a,行数1ec加1,转1ac
 
  读到回退符08,当1ed=1,转1ac,否则列数减1后,转1ac
 
  读到制表符09,则1ed置为下个制表位置,转1ac
 
  读到响铃符07,则不占输出列,转1ac
 
  读到其它符,1ed加1,比较屏幕配置列数1eb,不大于则转1ac,否则
 
  1ec加1,再置1ed=1
 
  (2.7) 1ac处,
 
  用功能2,显出al到stdout,以再接管道
 
  若1ec小于屏幕配置行数1ea,则转1e1处,否则用功能09,显出1f0处的"-- More --",用功能0c,且al=08,清键盘输入后,内调功能08,无回显,从stderr读键盘一符
 
  输出2空行,再置1ed=1,1ec=1
 
  (2.8) 1e1处,
 
  cx减1,结果为0,转139,否则转150
 
  成文:
 
  BLKSZ=1000h
 
  c        segment
          assume cs:c;ds:c,es:c,ss:c
 
          org    100h
  @:        jmp    init
 
  cfg_r        db    19h
  cfg_c        db    50h
  cur_r        db    1
  cur_c        db    1
 
  buf        db    BLKSZ    dup    (0)
  msg        db    ''-more-$''
  cr        db    13,10,36
 
  init:        xor    bx,bx
          mov    ah,45h
          int    21h
 
          mov    bp,ax
 
          mov    ah,3eh
          int    21h
 
          mov    bx,2
          mov    ah,45h
          int    21h
 
  read:        lea    dx,buf
          mov    cx,BLKSZ
          mov    bx,bp
          mov    ah,3fh
          int    21h
 
          or    ax,ax
          jnz    read1
 
  quit:        int    20h
 
  read1:        mov    cx,ax
          mov    si,dx
 
  nxtch:        lodsb
 
          cmp    al,1ah
          jz    quit
 
          cmp    al,13
          jnz    ?newlin
 
          mov    cur_c,1
          jmp    show
 
  ?newlin:    cmp    al,10
          jnz    ?back
 
          inc    cur_r
          jmp    show
 
  ?back:        cmp    al,8
          jnz    ?tab
 
          cmp    cur_c,1
          jz    show
 
          dec    cur_c
          jmp    show
 
  ?tab:        cmp    al,9
          jnz    ?bell
 
          mov    ah,cur_c   
          add    ah,7
          and    ah,0f8h
          inc    ah
          mov    cur_c,ah
          jmp    show
 
  ?bell:        cmp    al,7
          jz    show
 
          inc    cur_c
 
          mov    ah,cur_c
          cmp    ah,cfg_c
          jbe    show
 
          inc    cur_r
          mov    cur_c,1
 
  show:        mov    dl,al
          mov    ah,2       
          int    21h
 
          mov    ah,cur_r
          cmp    ah,cfg_r
          jb    ?endblk
 
          lea    dx,msg
          mov    ah,9
          int    21h
 
          mov    ax,0c08h
          int    21h
 
          lea    dx,cr
          mov    ah,9    1 cr
          int    21h
 
          mov    cur_c,1
          mov    cur_r,1
 
  ?endblk:    dec    cx
          jz    read@
          jmp    nxtc
  read@:        jmp    read
 
  c        ends
          end @
已有 0 位对此文章感兴趣的网友发布了看法    
我来评两句 登录邮箱: 密码:
  匿名发表
今日推荐
技术文库(共有 46430 篇文章)
操作系统
办公软件
实用知识
网络管理
软件开发
WEB开发
软件工程
数据库
设计在线
信息安全
行业信息化
管理信息化
重点推荐
电子杂志订阅
点击电子杂志名称查看样刊
输入E-mail地址即可订阅
E-mail