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 @
 
|