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

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 @

时间: 2024-10-31 05:48:24

5个DOS专用文件的6种io重定向(实现管道原理)的相关文章

《Netty 权威指南》—— 4种IO的对比

声明:本文是<Netty 权威指南>的样章,感谢博文视点授权并发编程网站发布样章,禁止以任何形式转载此文. 2.5.1.概念澄清 为了防止由于对一些技术概念和术语的理解或者叫法不一致引起歧义,本小节特意对本书中的专业术语或者技术用语做下声明,如果它们与其它的一些技术书籍术语不一致,请以本小节的解释为准. 2.5.1.1. 异步非阻塞IO 很多人喜欢将JDK1.4提供的NIO框架称为异步非阻塞IO,但是,如果严格按照Unix网络编程模型和JDK的实现进行区分,实际上它只能被称为非阻塞IO,不能叫

Linux 下的五种 IO 模型详细介绍_Linux

概念说明 用户空间与内核空间 现在操作系统都是采用虚拟存储器,那么对32位操作系统而言,它的寻址空间(虚拟存储空间)为4G(2的32次方).操作系统的核心是内核,独立于普通的应用程序,可以访问受保护的内存空间,也有访问底层硬件设备的所有权限.为了保证用户进程不能直接操作内核(kernel),保证内核的安全,操作系统将虚拟空间划分为两部分,一部分为内核空间,一部分为用户空间.针对linux操作系统而言,将最高的1G字节(从虚拟地址0xC0000000到0xFFFFFFFF),供内核使用,称为内核空

btrfs cfq, noop, deadline三种IO调度策略下的IO性能表现

btrfs 格式化和挂载参数: # mkfs.btrfs -m raid10 -d raid10 -n 4096 -f /dev/sdb /dev/sdc /dev/sdd /dev/sde # mount -o noatime,nodiratime,ssd_spread,discard,space_cache /dev/sdb /data01 从结果来看,建议使用deadline. 测试结果: [root@digoal data01]# echo noop > /sys/block/sdb/q

Linux五种IO模型性能分析

socket阻塞与非阻塞,同步与异步 1. 概念理解      在进行网络编程时,我们常常见到同步(Sync)/异步(Async),阻塞(Block)/非阻塞(Unblock)四种调用方式:同步:       所谓同步,就是在发出一个功能调用时,在没有得到结果之前,该调用就不返回.也就是必须一件一件事做,等前一件做完了才能做下一件事. 例如普通B/S模式(同步):提交请求->等待服务器处理->处理完毕返回 这个期间客户端浏览器不能干任何事 异步:       异步的概念和同步相对.当一个异步过

进入DOS环境的几种方法

对于初学者来说,熟悉几条必需的DOS命令是必不可少的,但有些朋友不知如何进入DOS环境,更别提学习了.下面笔者挑选几种常用的方法告诉大家. 1.若电脑虽然有问题但还能进入Windows,请依次点击"开始→程序→ MS-DOS方式",你还可以点击"开始→运行",在打开的对话框里输入"command"(不带引号,下同).若你的系统是Windows XP/2000,则输入"cmd",同样可以进入DOS. 2.对于http://www

如何理解IIS 7的两种应用程序池的管道模式(Managed Pipeline Mode)

之前我写过一篇博客文章,讲的是.NET 4.0的应用程序部署问题.有网友问到一个相关问题就是:如何理解IIS 7中的应用程序池的管道模式,尤其是如何理解托管模型(integrated mode),今天特意再写一篇文章来介绍这个问题. IIS 7是微软最新版本的IIS版本,从Vista开始提供,目前在Vista,Windows 7,Windows Server 2008中提供.这个全新的版本中,一个突出的亮点就是,它提供了两种管道模式,来支持不同的应用程序场景. 这里提到的管道模式,指的是应用程序

详解python的几种标准输出重定向方式_python

一. 背景 在Python中,文件对象sys.stdin.sys.stdout和sys.stderr分别对应解释器的标准输入.标准输出和标准出错流.在程序启动时,这些对象的初值由sys.__stdin__.sys.__stdout__和sys.__stderr__保存,以便用于收尾(finalization)时恢复标准流对象. Windows系统中IDLE(Python GUI)由pythonw.exe,该GUI没有控制台.因此,IDLE将标准输出句柄替换为特殊的PseudoOutputFile

《Unix编程艺术》重读笔记(三)

题外:从老家从早到晚总算折腾回了杭州,进站太早,火车晚点,提包带断,什么倒霉事也遇上了,先发个已经整理好的部分,后续仍待整理. 多道程序设计:分离进程为独立的功能 无论在协作进程还是在同一进程的协作子过程层面上,Unix设计风格都运用"做单件事并做好的方法",强调用定义良好的进程间通信或共享文件来连通小型进程,提倡将程序分解为更简单的子进程,并专注考虑这些子进程间的接口,这至少需要通过以下三种方法来实现: 1.降低进程生成的开销(思考下Erlang的process) 2.提供方法(sh

Csh的基本语法介绍_linux shell

在*unix系统中,常用的shell有sh,bash,csh/tcsh, ksh. sh来自于systemV的Unix,是传统的Unix的shell,直到现在很多的系统管理员仍然喜欢使用sh. bash来自于BSD Unix,语法非常类似于C语言,所以通常有C/C++编程背景的开发人员最喜欢使用. ksh是对sh的扩展,且吸收了csh的一些有用的功能,但是由于开始ksh的license是AT&T,所以后来出现了很多的ksh的开源版本,例如mksh,pdksh等. bash是现在很多Linux的发