5个DOS专用文件的6种io重定向,more实现管道原理
   作者:马文晓 于2003-12-20上传 

  1. 重定向
  
  以下a.asm,用含't'及回车13的txt,仿command.com,依masm命令行的arg符号值N,(如masm /Darg=0 a;),重定向5个DOS开启文件(STD_):
  
  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
  
  调用功能:
  
  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
  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    @4
  
      mov    ax,4400h    I/O,从/到fil\nul定向,dx=42h\80c4,否则80d3
      int    21h
  
      xor    dh,dh
      push    dx
  
      mov    ax,4401h
      or    dl,32        bin
      int    21h
  
      mov    ax,64        bios数据区seg,1E~3D是键区
      mov    es,ax
  
      mov    ah,3fh        不等回车读
      mov    cx,1        1符
      lea    dx,@        入256
      int    21h
  
      cmp    byte ptr cs:[256],224    测扩展
      jz    @2
  
      test    byte ptr cs:[256],255    再测
      jnz    @3
  
  @2:    just
      mov    word ptr txt,ax
  
      mov    ah,3fh        取真
      inc    dx
      int    21h
  
  @3:    just
      mov word ptr txt[2],ax
  
      pop    dx
  
      mov    ax,4401h    复原
      int    21h
  
  @4:    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,得[100,1e9]/[1ea,219]是代码/数据,初值为18/50的1ea/leb,记录屏幕配置行/列数,初值1/1的1ec/1ed,记录已处理行/列数.
  
  流程:
  
  (2.1) 100处,用功能30,取主/次版号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)句柄(也可复制运行时打开的si),必得已关句柄0,
  为看完满屏而读键盘1符时,从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,显当前符于stdout,以再接管道
  
  若1ec小于屏幕配置行数1ea,则转1e1处,否则用功能09,显出1f0处的"-- More --",用功能0c,且al=08,清键盘输入+调功能08,无回显,从stderr读键盘1符
  
  输出2空行,再置1ed=1,1ec=1
  
  (2.8) 1e1处,
  
  cx减1,结果为0,转139,否则转150
  
  (2.9) 用a.com实现:
  
  type a.asm | a.com时,AT机,每秒响铃,或
  a.com a.com时,fcb,han各打开a.com,1次dup,1次force_dup,执行子进程,显计数11231123
  
  c        segment
          assume    cs:c;ds:c
  
          org        100h
  @:        jmp        init
  
  cfg_r    db        25
  cfg_c    db        80
  cur_r    db        1
  cur_c    db        1
  
  buf    db        "a.com"
      db        1000h-($-buf)    dup(0)
  buf_=$
  
  key        db        '-KEY-$'
  cr        db        13,10,36
  
  old4a    dd        59    V6
  
  parablk db      parasz
  para    db      -1
  parasz=$-para
          db      13
  
  env     dw      0
  paraoff dw      parablk
  paraseg dw      ?            
  FCB0    dw        92,?
          dd        -1
  
  adj        macro r,u
          local a
          mov al,r
          inc al
          daa
          cmp al,u
          stc
          jne a
          xor al,al
  a:        mov r,al
          endm
  
  harp    macro
          local h
  
          mov ah,2
          int 26
  
          adj dh,96    秒BCD
          jc h
  
          adj cl,96
          jc h
  
          adj ch,36
  
  h:        mov ah,7    clr
          int 26
  
          mov ah,6    set
          int 26
  
          endm
  
  alarm:    push ax
          push cx
          push dx
  
          mov al,7
          int 29h
          harp
  
          pop dx
          pop cx
          pop ax
  
          jmp cs:old4a
  
  J2S        macro    h
          mov        di,h
          mov        al,cs:24[di]    原JFT
          push    si
          push    es
          call    ref
          pop        es
          pop        si
          endm
  
  ref        proc
          cbw
  grp:    cmp        ax,es:4[si]    ;cnt
          jl        SFT
  
          sub        ax,es:4[si]
  
          les        si,es:[si]      ;next_addr
          jmp        grp
  
  SFT:    mul        word ptr old4a
          add        si,ax
          
          mov        al,byte ptr es:6[si]
          add        al,48
          int        41
          ret
  ref        endp
  
  open    proc
          mov        ah,82
          int        21h
          les     si,es:[bx+di]    矢SFT
  
          cmp        di,4
          jz      unix
  
          mov     ah,15
          mov     dx,92
          int     21h
          or      al,al
          jnz     open1
  open0:    ret
  
  unix:    mov        ax,3d00h
          lea     dx,buf
          int     21h
          jnc        open0
  open1:    int     20h
  open    endp
  
  init:    cmp        byte ptr cs:[129],-1    参数,ALT+数字,都无法键入
          je        LST_LST
  
          mov        ax,4406h
          xor        bx,bx
          int        21h
          or        al,al
          jz        heir
          jmp        bell    已改向
  
  heir:    lea        sp,buf_    宽栈
  
          mov     ah,4ah    新mem,始es节,长bx节
          lea     bx,bell
          add     bx,15
  
          rept    4
          shr     bx,1    字节转节
          endm
  
          int     21h
  
  LST_LST:mov     di,26
          call    open
  
          mov     al,cs:[116]
          call    ref
  
          mov     bp,sp    为关闭
  
          mov        di,4
          call    open
          push    ax
  
          mov        bx,ax
          J2S        bx
  
          mov        ah,45h    dup
          int        21h
          push    ax
          J2S        ax
  
          mov        al,cs:[24]    stdin
          mov        byte ptr @,al
  
          mov        ah,46h    force
          xor        cx,cx
          int        21h
  
          push    cx
          J2S        cx
  
          mov        ah,16    为exec,关fcb
          mov        dx,92
          int        21h
  
          cmp        byte ptr cs:[129],-1
          je        close
  
          mov     ax,cs
          mov        es,ax
  
          mov     paraseg,ax
          mov     FCB0[2],ax
  
          lea     bx,env  ;es:bx矢参数块
          lea        dx,buf    ds:dx矢执行名
  
          mov     ax,4b00h
          int     21h
                  
  close:    mov        ah,3eh
  
  close0:    cmp        bp,sp
          jz        close1
          pop        bx
          int        21h    释放24[bx]
          jmp        close0
  
  close1:    mov        al,byte ptr @
          mov        cs:[24],al
  
          int        20h
  
  bell:    mov    ax,354ah
          int 21h
  
          mov word ptr old4a,bx
          mov word ptr [old4a+2],es
  
          mov ah,37
          lea dx,alarm
          int 21h
  
          harp
  
          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,size buf
          mov    bx,bp
          mov    ah,3fh
          int    21h
  
          or    ax,ax
          jnz    read1
  
  quit:    lds dx,cs:old4a
          mov    ax,254ah
          int 21h
  
          int    20h
  
  read1:    mov    cx,ax
          mov    si,dx
  
  next:    lodsb
  
          cmp    al,1ah
          jz    quit
  
          cmp    al,13
          jnz    CTL_CR
  
          mov    cur_c,1
          jmp    show
  
  CTL_CR:    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,248
          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,key
          mov    ah,9
          int    21h
  
          mov    ax,0c08h
          int    21h
  
          lea    dx,cr
          mov    ah,9
          int    21h
  
          mov    cur_c,1
          mov    cur_r,1
  
  endblk:    dec    cx
          jz    read@
          jmp    next
  
  read@:    jmp    read
  
  c        ends
          end @



欢迎访问AoGo汇编小站:http://www.aogosoft.com