程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> 更多編程語言 >> 匯編語言 >> 5個DOS專用文件的6種io重定向(實現管道原理)

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 @

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved