首页 / 软件开发 / 汇编语言 / 5个DOS专用文件的6种io重定向(实现管道原理)
5个DOS专用文件的6种io重定向(实现管道原理)2007-05-021. 重定向以下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"到txtN=30,31:
3是STDAUX句柄,N=30,从txt输"t"到char;N=31,输出char的"3"到txtN=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,关闭txtDEBUG做完a.com,对输入,见103h的char,变"t",对输出,type txt,见1~4.ACT=2
IFDEF arg
IF arg GT 2
IF arg EQ 30
ACT=30
ENDIFIF arg EQ 31
ACT=31
ENDIFIF arg EQ 41
ACT=41
ENDIFSTD_=arg/10
ELSE
IF arg GE 0
ACT=1
STD_=argIF arg EQ 0
ACT=0
ENDIF
ENDIF
ENDIF
ENDIFIF ACT EQ 2 无效
%OUT /Darg=0|1|2|30|31|41
.ERR
ENDIFjust macro
local jmov di,es:[26] 敲键,i9写低asc,高scan到[1Ch尾引字++],i16读[1Ah首引字++]到3f功能的ax
sub di,2cmp di,1ch 未重划键区,现在回头
ja jmov di,3ch 刚才入尾j: mov ax,es:[di]
endmc segment
assume cs:c,ds:corg 100h@: jmp @1char db "0"+STD_
txt db "txt",0@1: mov ah,3dh open
mov al,ACT and 1
lea dx,txt
int 21hmov si,ax hanmov bx,ACT stdin
test bx,63 >41
jnz @4mov ax,4400h I/O,从/到fil
ul定向,dx=42h80c4,否则80d3
int 21hxor dh,dh
push dxmov ax,4401h
or dl,32 bin
int 21hmov ax,64 bios数据区seg,1E~3D是键区
mov es,axmov ah,3fh 不等回车读
mov cx,1 1符
lea dx,@ 入256
int 21hcmp byte ptr cs:[256],224 测扩展
jz @2test byte ptr cs:[256],255 再测
jnz @3@2: just
mov word ptr txt,axmov ah,3fh 取真
inc dx
int 21h@3: just
mov word ptr txt[2],axpop dxmov ax,4401h 复原
int 21h@4: mov ah,45h duplica
mov bx,STD_
int 21hmov di,ax hanmov ah,46h force han
mov bx,si
mov cx,STD_
int 21hmov ah,3fh+ACT r/w=3f/40
mov bx,STD_
mov cx,1
lea dx,char
int 21hmov ah,46h
mov bx,di
mov cx,STD_
int 21hmov ah,3eh close
mov bx,si
int 21hretc 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,执行子进程,显计数11231123c segment
assume cs:c;ds:corg 100h
@: jmp initcfg_r db 25
cfg_c db 80
cur_r db 1
cur_c db 1buf db "a.com"
db 1000h-($-buf) dup(0)
buf_=$key db "-KEY-$"
cr db 13,10,36old4a dd 59 V6parablk db parasz
para db -1
parasz=$-para
db 13env dw 0
paraoff dw parablk
paraseg dw ?
FCB0 dw 92,?
dd -1adj macro r,u
local a
mov al,r
inc al
daa
cmp al,u
stc
jne a
xor al,al
a: mov r,al
endmharp macro
local hmov ah,2
int 26adj dh,96 秒BCD
jc hadj cl,96
jc hadj ch,36h: mov ah,7 clr
int 26mov ah,6 set
int 26endmalarm: push ax
push cx
push dxmov al,7
int 29h
harppop dx
pop cx
pop axjmp cs:old4aJ2S macro h
mov di,h
mov al,cs:24[di] 原JFT
push si
push es
call ref
pop es
pop si
endmref proc
cbw
grp: cmp ax,es:4[si] ;cnt
jl SFTsub ax,es:4[si]les si,es:[si] ;next_addr
jmp grpSFT: mul word ptr old4a
add si,axmov al,byte ptr es:6[si]
add al,48
int 41
ret
ref endpopen proc
mov ah,82
int 21h
les si,es:[bx+di] 矢SFTcmp di,4
jz unixmov ah,15
mov dx,92
int 21h
or al,al
jnz open1
open0: retunix: mov ax,3d00h
lea dx,buf
int 21h
jnc open0
open1: int 20h
open endpinit: cmp byte ptr cs:[129],-1 参数,ALT+数字,都无法键入
je LST_LSTmov 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,15rept 4
shr bx,1 字节转节
endmint 21hLST_LST:mov di,26
call openmov al,cs:[116]
call refmov bp,sp 为关闭mov di,4
call open
push axmov bx,ax
J2S bxmov ah,45h dup
int 21h
push ax
J2S axmov al,cs:[24] stdin
mov byte ptr @,almov ah,46h force
xor cx,cx
int 21hpush cx
J2S cxmov ah,16 为exec,关fcb
mov dx,92
int 21hcmp byte ptr cs:[129],-1
je closemov ax,cs
mov es,axmov paraseg,ax
mov FCB0[2],axlea bx,env ;es:bx矢参数块
lea dx,buf ds:dx矢执行名mov ax,4b00h
int 21hclose: mov ah,3ehclose0: cmp bp,sp
jz close1
pop bx
int 21h 释放24[bx]
jmp close0close1: mov al,byte ptr @
mov cs:[24],alint 20hbell: mov ax,354ah
int 21hmov word ptr old4a,bx
mov word ptr [old4a+2],esmov ah,37
lea dx,alarm
int 21hharpxor bx,bx
mov ah,45h
int 21hmov bp,axmov ah,3eh
int 21hmov bx,2
mov ah,45h
int 21hread: lea dx,buf
mov cx,size buf
mov bx,bp
mov ah,3fh
int 21hor ax,ax
jnz read1quit: lds dx,cs:old4a
mov ax,254ah
int 21hint 20hread1: mov cx,ax
mov si,dxnext: lodsbcmp al,1ah
jz quitcmp al,13
jnz CTL_CRmov cur_c,1
jmp showCTL_CR: cmp al,10
jnz ?backinc cur_r
jmp show?back: cmp al,8
jnz ?tabcmp cur_c,1
jz showdec cur_c
jmp show?tab: cmp al,9
jnz ?bellmov ah,cur_c
add ah,7
and ah,248
inc ah
mov cur_c,ah
jmp show?bell: cmp al,7
jz showinc cur_cmov ah,cur_c
cmp ah,cfg_c
jbe showinc cur_r
mov cur_c,1show: mov dl,al
mov ah,2
int 21hmov ah,cur_r
cmp ah,cfg_r
jb endblklea dx,key
mov ah,9
int 21hmov ax,0c08h
int 21hlea dx,cr
mov ah,9
int 21hmov cur_c,1
mov cur_r,1endblk: dec cx
jz read@
jmp nextread@: jmp readc ends
end @